- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / tcmalloc / chromium / src / windows / port.h
1 /* Copyright (c) 2007, Google Inc.
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
17  *
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.
29  *
30  * ---
31  * Author: Craig Silverstein
32  *
33  * These are some portability typedefs and defines to make it a bit
34  * easier to compile this code under VC++.
35  *
36  * Several of these are taken from glib:
37  *    http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
38  */
39
40 #ifndef GOOGLE_BASE_WINDOWS_H_
41 #define GOOGLE_BASE_WINDOWS_H_
42
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
49
50 #ifdef _WIN32
51
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 */
68
69 /*
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
77  */
78 #ifdef _MSC_VER
79 #pragma warning(disable:4018 4244 4288 4267 4290 4996 4146)
80 #endif
81
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
92
93 #ifdef __cplusplus
94 # define EXTERN_C  extern "C"
95 #else
96 # define EXTERN_C  extern
97 #endif
98
99 /* ----------------------------------- BASIC TYPES */
100
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
105
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 */
115
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
120
121 /* ----------------------------------- THREADS */
122
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 */
128
129 inline pthread_t pthread_self(void) {
130   return GetCurrentThreadId();
131 }
132
133 #ifdef __cplusplus
134 inline bool pthread_equal(pthread_t left, pthread_t right) {
135   return left == right;
136 }
137
138 /* This replaces maybe_threads.{h,cc} */
139 EXTERN_C pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*));  /* port.cc */
140
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();
149   }
150 }
151
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;
157 }
158
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();
164 }
165
166 EXTERN_C int perftools_pthread_once(pthread_once_t *once_control,
167                                     void (*init_routine)(void));
168
169 #endif  /* __cplusplus */
170 #endif  /* HAVE_PTHREAD */
171
172 inline void sched_yield(void) {
173   Sleep(0);
174 }
175
176 /*
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.
180  */
181 #define __thread __declspec(thread)
182
183 /*
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.
189  */
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);
204   }
205
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!
213
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_);
226   }
227   void Unlock() {
228     LeaveCriticalSection(&mutex_);
229   }
230
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;
237   }
238  private:
239   void InitializeMutex() { InitializeCriticalSection(&mutex_); }
240
241   pthread_once_t initialize_token_;
242   CRITICAL_SECTION mutex_;
243 };
244
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(); }
251 };
252 #endif  // #ifdef __cplusplus
253
254 // This keeps us from using base/spinlock.h's implementation of SpinLock.
255 #define BASE_SPINLOCK_H_ 1
256
257 #endif  /* #if 0 */
258
259 /* ----------------------------------- MMAP and other memory allocation */
260
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 */
270
271 #if __STDC__ && !defined(__MINGW32__)
272 typedef _off_t off_t;
273 #endif
274
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;
283   }
284 }
285
286 inline int munmap(void *addr, size_t length) {
287   return VirtualFree(addr, 0, MEM_RELEASE) ? 0 : -1;
288 }
289 #endif  /* HAVE_MMAP */
290
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;
295 }
296
297
298 /* ----------------------------------- STRING ROUTINES */
299
300 /*
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 (!)).
304  */
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);
310 }
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);
318 }
319 #endif
320
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;
329 }
330 #endif
331
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
344
345 /* ----------------------------------- FILE IO */
346
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
356
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);
361 }
362 inline int open(const char *pathname, int flags, int mode = 0) {
363   return _open(pathname, flags, mode);
364 }
365 inline int close(int fd) {
366   return _close(fd);
367 }
368 inline ssize_t read(int fd, void *buf, size_t count) {
369   return _read(fd, buf, count);
370 }
371 inline ssize_t write(int fd, const void *buf, size_t count) {
372   return _write(fd, buf, count);
373 }
374 inline off_t lseek(int fd, off_t offset, int whence) {
375   return _lseek(fd, offset, whence);
376 }
377 inline char *getcwd(char *buf, size_t size) {
378   return _getcwd(buf, size);
379 }
380 inline int mkdir(const char *pathname, int) {
381   return _mkdir(pathname);
382 }
383
384 inline FILE *popen(const char *command, const char *type) {
385   return _popen(command, type);
386 }
387 inline int pclose(FILE *stream) {
388   return _pclose(stream);
389 }
390 #endif
391
392 EXTERN_C PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len);
393
394 /* ----------------------------------- SYSTEM/PROCESS */
395
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; }
401
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;
408 }
409
410 EXTERN_C int getpagesize();   /* in port.cc */
411
412 /* ----------------------------------- OTHER */
413
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;
419 }
420
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;
427 };
428 #endif
429
430 inline int nanosleep(const struct timespec *req, struct timespec *rem) {
431   Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000);
432   return 0;
433 }
434
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);
439 }
440 inline unsigned long long int strtoull(const char *nptr, char **endptr,
441                                        int base) {
442     return _strtoui64(nptr, endptr, base);
443 }
444 inline long long int strtoq(const char *nptr, char **endptr, int base) {
445     return _strtoi64(nptr, endptr, base);
446 }
447 #endif
448 inline unsigned long long int strtouq(const char *nptr, char **endptr,
449                                       int base) {
450     return _strtoui64(nptr, endptr, base);
451 }
452 inline long long atoll(const char *nptr) {
453   return _atoi64(nptr);
454 }
455 #endif
456
457 #define __THROW throw()
458
459 /* ----------------------------------- TCMALLOC-SPECIFIC */
460
461 /* tcmalloc.cc calls this so we can patch VirtualAlloc() et al. */
462 extern void PatchWindowsFunctions();
463
464 // ----------------------------------- BUILD-SPECIFIC
465
466 /*
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.
470  */
471 #define GOOGLE_MAYBE_THREADS_H_ 1
472
473
474 #endif  /* _WIN32 */
475
476 #undef inline
477 #undef EXTERN_C
478
479 #endif  /* GOOGLE_BASE_WINDOWS_H_ */