Revert of Roll src/third_party/WebKit e0eac24:489c548 (svn 193311:193320) (patchset...
[chromium-blink-merge.git] / third_party / tcmalloc / chromium / src / windows / port.h
blob2b67522c1c7e5590b632f48f6687f729fa424b94
1 /* Copyright (c) 2007, Google Inc.
2 * All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * ---
31 * Author: Craig Silverstein
33 * These are some portability typedefs and defines to make it a bit
34 * easier to compile this code under VC++.
36 * Several of these are taken from glib:
37 * http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
40 #ifndef GOOGLE_BASE_WINDOWS_H_
41 #define GOOGLE_BASE_WINDOWS_H_
43 /* You should never include this file directly, but always include it
44 from either config.h (MSVC) or mingw.h (MinGW/msys). */
45 #if !defined(GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_) && \
46 !defined(GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_)
47 # error "port.h should only be included from config.h or mingw.h"
48 #endif
50 #ifdef _WIN32
52 #ifndef NOMINMAX
53 #define NOMINMAX /* Do not define min and max macros. */
54 #endif
55 #ifndef WIN32_LEAN_AND_MEAN
56 #define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
57 #endif
58 #include <windows.h>
59 #include <io.h> /* because we so often use open/close/etc */
60 #include <direct.h> /* for _getcwd */
61 #include <process.h> /* for _getpid */
62 #include <limits.h> /* for PATH_MAX */
63 #include <stdarg.h> /* for va_list */
64 #include <stdio.h> /* need this to override stdio's (v)snprintf */
65 #include <sys/types.h> /* for _off_t */
66 #include <assert.h>
67 #include <stdlib.h> /* for rand, srand, _strtoxxx */
70 * 4018: signed/unsigned mismatch is common (and ok for signed_i < unsigned_i)
71 * 4244: otherwise we get problems when subtracting two size_t's to an int
72 * 4288: VC++7 gets confused when a var is defined in a loop and then after it
73 * 4267: too many false positives for "conversion gives possible data loss"
74 * 4290: it's ok windows ignores the "throw" directive
75 * 4996: Yes, we're ok using "unsafe" functions like vsnprintf and getenv()
76 * 4146: internal_logging.cc intentionally negates an unsigned value
78 #ifdef _MSC_VER
79 #pragma warning(disable:4018 4244 4288 4267 4290 4996 4146)
80 #endif
82 #ifndef __cplusplus
83 /* MSVC does not support C99 */
84 # if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
85 # ifdef _MSC_VER
86 # define inline __inline
87 # else
88 # define inline static
89 # endif
90 # endif
91 #endif
93 #ifdef __cplusplus
94 # define EXTERN_C extern "C"
95 #else
96 # define EXTERN_C extern
97 #endif
99 /* ----------------------------------- BASIC TYPES */
101 #ifndef HAVE_STDINT_H
102 #ifndef HAVE___INT64 /* we need to have all the __intX names */
103 # error Do not know how to set up type aliases. Edit port.h for your system.
104 #endif
106 typedef __int8 int8_t;
107 typedef __int16 int16_t;
108 typedef __int32 int32_t;
109 typedef __int64 int64_t;
110 typedef unsigned __int8 uint8_t;
111 typedef unsigned __int16 uint16_t;
112 typedef unsigned __int32 uint32_t;
113 typedef unsigned __int64 uint64_t;
114 #endif /* #ifndef HAVE_STDINT_H */
116 /* I guess MSVC's <types.h> doesn't include ssize_t by default? */
117 #ifdef _MSC_VER
118 typedef intptr_t ssize_t;
119 #endif
121 /* ----------------------------------- THREADS */
123 #ifndef HAVE_PTHREAD /* not true for MSVC, but may be true for MSYS */
124 typedef DWORD pthread_t;
125 typedef DWORD pthread_key_t;
126 typedef LONG pthread_once_t;
127 enum { PTHREAD_ONCE_INIT = 0 }; /* important that this be 0! for SpinLock */
129 inline pthread_t pthread_self(void) {
130 return GetCurrentThreadId();
133 #ifdef __cplusplus
134 inline bool pthread_equal(pthread_t left, pthread_t right) {
135 return left == right;
138 /* This replaces maybe_threads.{h,cc} */
139 EXTERN_C pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)); /* port.cc */
141 inline int perftools_pthread_key_create(pthread_key_t *pkey,
142 void (*destructor)(void*)) {
143 pthread_key_t key = PthreadKeyCreate(destructor);
144 if (key != TLS_OUT_OF_INDEXES) {
145 *(pkey) = key;
146 return 0;
147 } else {
148 return GetLastError();
152 inline void* perftools_pthread_getspecific(DWORD key) {
153 DWORD err = GetLastError();
154 void* rv = TlsGetValue(key);
155 if (err) SetLastError(err);
156 return rv;
159 inline int perftools_pthread_setspecific(pthread_key_t key, const void *value) {
160 if (TlsSetValue(key, (LPVOID)value))
161 return 0;
162 else
163 return GetLastError();
166 EXTERN_C int perftools_pthread_once(pthread_once_t *once_control,
167 void (*init_routine)(void));
169 #endif /* __cplusplus */
170 #endif /* HAVE_PTHREAD */
172 inline void sched_yield(void) {
173 Sleep(0);
177 * __declspec(thread) isn't usable in a dll opened via LoadLibrary().
178 * But it doesn't work to LoadLibrary() us anyway, because of all the
179 * things we need to do before main()! So this kind of TLS is safe for us.
181 #define __thread __declspec(thread)
184 * This code is obsolete, but I keep it around in case we are ever in
185 * an environment where we can't or don't want to use google spinlocks
186 * (from base/spinlock.{h,cc}). In that case, uncommenting this out,
187 * and removing spinlock.cc from the build, should be enough to revert
188 * back to using native spinlocks.
190 #if 0
191 // Windows uses a spinlock internally for its mutexes, making our life easy!
192 // However, the Windows spinlock must always be initialized, making life hard,
193 // since we want LINKER_INITIALIZED. We work around this by having the
194 // linker initialize a bool to 0, and check that before accessing the mutex.
195 // This replaces spinlock.{h,cc}, and all the stuff it depends on (atomicops)
196 #ifdef __cplusplus
197 class SpinLock {
198 public:
199 SpinLock() : initialize_token_(PTHREAD_ONCE_INIT) {}
200 // Used for global SpinLock vars (see base/spinlock.h for more details).
201 enum StaticInitializer { LINKER_INITIALIZED };
202 explicit SpinLock(StaticInitializer) : initialize_token_(PTHREAD_ONCE_INIT) {
203 perftools_pthread_once(&initialize_token_, InitializeMutex);
206 // It's important SpinLock not have a destructor: otherwise we run
207 // into problems when the main thread has exited, but other threads
208 // are still running and try to access a main-thread spinlock. This
209 // means we leak mutex_ (we should call DeleteCriticalSection()
210 // here). However, I've verified that all SpinLocks used in
211 // perftools have program-long scope anyway, so the leak is
212 // perfectly fine. But be aware of this for the future!
214 void Lock() {
215 // You'd thionk this would be unnecessary, since we call
216 // InitializeMutex() in our constructor. But sometimes Lock() can
217 // be called before our constructor is! This can only happen in
218 // global constructors, when this is a global. If we live in
219 // bar.cc, and some global constructor in foo.cc calls a routine
220 // in bar.cc that calls this->Lock(), then Lock() may well run
221 // before our global constructor does. To protect against that,
222 // we do this check. For SpinLock objects created after main()
223 // has started, this pthread_once call will always be a noop.
224 perftools_pthread_once(&initialize_token_, InitializeMutex);
225 EnterCriticalSection(&mutex_);
227 void Unlock() {
228 LeaveCriticalSection(&mutex_);
231 // Used in assertion checks: assert(lock.IsHeld()) (see base/spinlock.h).
232 inline bool IsHeld() const {
233 // This works, but probes undocumented internals, so I've commented it out.
234 // c.f. http://msdn.microsoft.com/msdnmag/issues/03/12/CriticalSections/
235 //return mutex_.LockCount>=0 && mutex_.OwningThread==GetCurrentThreadId();
236 return true;
238 private:
239 void InitializeMutex() { InitializeCriticalSection(&mutex_); }
241 pthread_once_t initialize_token_;
242 CRITICAL_SECTION mutex_;
245 class SpinLockHolder { // Acquires a spinlock for as long as the scope lasts
246 private:
247 SpinLock* lock_;
248 public:
249 inline explicit SpinLockHolder(SpinLock* l) : lock_(l) { l->Lock(); }
250 inline ~SpinLockHolder() { lock_->Unlock(); }
252 #endif // #ifdef __cplusplus
254 // This keeps us from using base/spinlock.h's implementation of SpinLock.
255 #define BASE_SPINLOCK_H_ 1
257 #endif /* #if 0 */
259 /* ----------------------------------- MMAP and other memory allocation */
261 #ifndef HAVE_MMAP /* not true for MSVC, but may be true for msys */
262 #define MAP_FAILED 0
263 #define MREMAP_FIXED 2 /* the value in linux, though it doesn't really matter */
264 /* These, when combined with the mmap invariants below, yield the proper action */
265 #define PROT_READ PAGE_READWRITE
266 #define PROT_WRITE PAGE_READWRITE
267 #define MAP_ANONYMOUS MEM_RESERVE
268 #define MAP_PRIVATE MEM_COMMIT
269 #define MAP_SHARED MEM_RESERVE /* value of this #define is 100% arbitrary */
271 #if __STDC__ && !defined(__MINGW32__)
272 typedef _off_t off_t;
273 #endif
275 /* VirtualAlloc only replaces for mmap when certain invariants are kept. */
276 inline void *mmap(void *addr, size_t length, int prot, int flags,
277 int fd, off_t offset) {
278 if (addr == NULL && fd == -1 && offset == 0 &&
279 prot == (PROT_READ|PROT_WRITE) && flags == (MAP_PRIVATE|MAP_ANONYMOUS)) {
280 return VirtualAlloc(0, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
281 } else {
282 return NULL;
286 inline int munmap(void *addr, size_t length) {
287 return VirtualFree(addr, 0, MEM_RELEASE) ? 0 : -1;
289 #endif /* HAVE_MMAP */
291 /* We could maybe use VirtualAlloc for sbrk as well, but no need */
292 inline void *sbrk(intptr_t increment) {
293 // sbrk returns -1 on failure
294 return (void*)-1;
298 /* ----------------------------------- STRING ROUTINES */
301 * We can't just use _vsnprintf and _snprintf as drop-in-replacements,
302 * because they don't always NUL-terminate. :-( We also can't use the
303 * name vsnprintf, since windows defines that (but not snprintf (!)).
305 #if defined(_MSC_VER) && _MSC_VER >= 1400
306 /* We can use safe CRT functions, which the required functionality */
307 inline int perftools_vsnprintf(char *str, size_t size, const char *format,
308 va_list ap) {
309 return vsnprintf_s(str, size, _TRUNCATE, format, ap);
311 #else
312 inline int perftools_vsnprintf(char *str, size_t size, const char *format,
313 va_list ap) {
314 if (size == 0) /* not even room for a \0? */
315 return -1; /* not what C99 says to do, but what windows does */
316 str[size-1] = '\0';
317 return _vsnprintf(str, size-1, format, ap);
319 #endif
321 #ifndef HAVE_SNPRINTF
322 inline int snprintf(char *str, size_t size, const char *format, ...) {
323 va_list ap;
324 int r;
325 va_start(ap, format);
326 r = perftools_vsnprintf(str, size, format, ap);
327 va_end(ap);
328 return r;
330 #endif
332 #define PRIx64 "I64x"
333 #define SCNx64 "I64x"
334 #define PRId64 "I64d"
335 #define SCNd64 "I64d"
336 #define PRIu64 "I64u"
337 #ifdef _WIN64
338 # define PRIuPTR "llu"
339 # define PRIxPTR "llx"
340 #else
341 # define PRIuPTR "lu"
342 # define PRIxPTR "lx"
343 #endif
345 /* ----------------------------------- FILE IO */
347 #ifndef PATH_MAX
348 #define PATH_MAX 1024
349 #endif
350 #ifndef __MINGW32__
351 enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
352 #endif
353 #ifndef O_RDONLY
354 #define O_RDONLY _O_RDONLY
355 #endif
357 #if __STDC__ && !defined(__MINGW32__)
358 /* These functions are considered non-standard */
359 inline int access(const char *pathname, int mode) {
360 return _access(pathname, mode);
362 inline int open(const char *pathname, int flags, int mode = 0) {
363 return _open(pathname, flags, mode);
365 inline int close(int fd) {
366 return _close(fd);
368 inline ssize_t read(int fd, void *buf, size_t count) {
369 return _read(fd, buf, count);
371 inline ssize_t write(int fd, const void *buf, size_t count) {
372 return _write(fd, buf, count);
374 inline off_t lseek(int fd, off_t offset, int whence) {
375 return _lseek(fd, offset, whence);
377 inline char *getcwd(char *buf, size_t size) {
378 return _getcwd(buf, size);
380 inline int mkdir(const char *pathname, int) {
381 return _mkdir(pathname);
384 inline FILE *popen(const char *command, const char *type) {
385 return _popen(command, type);
387 inline int pclose(FILE *stream) {
388 return _pclose(stream);
390 #endif
392 EXTERN_C PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len);
394 /* ----------------------------------- SYSTEM/PROCESS */
396 typedef int pid_t;
397 #if __STDC__ && !defined(__MINGW32__)
398 inline pid_t getpid(void) { return _getpid(); }
399 #endif
400 inline pid_t getppid(void) { return 0; }
402 /* Handle case when poll is used to simulate sleep. */
403 inline int poll(struct pollfd* fds, int nfds, int timeout) {
404 assert(fds == NULL);
405 assert(nfds == 0);
406 Sleep(timeout);
407 return 0;
410 EXTERN_C int getpagesize(); /* in port.cc */
412 /* ----------------------------------- OTHER */
414 inline void srandom(unsigned int seed) { srand(seed); }
415 inline long random(void) { return rand(); }
416 inline unsigned int sleep(unsigned int seconds) {
417 Sleep(seconds * 1000);
418 return 0;
421 // mingw64 seems to define timespec (though mingw.org mingw doesn't),
422 // protected by the _TIMESPEC_DEFINED macro.
423 #ifndef _TIMESPEC_DEFINED
424 struct timespec {
425 int tv_sec;
426 int tv_nsec;
428 #endif
430 inline int nanosleep(const struct timespec *req, struct timespec *rem) {
431 Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000);
432 return 0;
435 #ifndef __MINGW32__
436 #if _MSC_VER < 1800 // Not required >= VS2013.
437 inline long long int strtoll(const char *nptr, char **endptr, int base) {
438 return _strtoi64(nptr, endptr, base);
440 inline unsigned long long int strtoull(const char *nptr, char **endptr,
441 int base) {
442 return _strtoui64(nptr, endptr, base);
444 inline long long int strtoq(const char *nptr, char **endptr, int base) {
445 return _strtoi64(nptr, endptr, base);
447 #endif
448 inline unsigned long long int strtouq(const char *nptr, char **endptr,
449 int base) {
450 return _strtoui64(nptr, endptr, base);
452 inline long long atoll(const char *nptr) {
453 return _atoi64(nptr);
455 #endif
457 #define __THROW throw()
459 /* ----------------------------------- TCMALLOC-SPECIFIC */
461 /* tcmalloc.cc calls this so we can patch VirtualAlloc() et al. */
462 extern void PatchWindowsFunctions();
464 // ----------------------------------- BUILD-SPECIFIC
467 * windows/port.h defines compatibility APIs for several .h files, which
468 * we therefore shouldn't be #including directly. This hack keeps us from
469 * doing so. TODO(csilvers): do something more principled.
471 #define GOOGLE_MAYBE_THREADS_H_ 1
474 #endif /* _WIN32 */
476 #undef inline
477 #undef EXTERN_C
479 #endif /* GOOGLE_BASE_WINDOWS_H_ */