Home | History | Annotate | Download | only in windows
      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 WIN32_LEAN_AND_MEAN
     53 #define WIN32_LEAN_AND_MEAN  /* We always want minimal includes */
     54 #endif
     55 #include <windows.h>
     56 #include <io.h>              /* because we so often use open/close/etc */
     57 #include <direct.h>          /* for _getcwd */
     58 #include <process.h>         /* for _getpid */
     59 #include <limits.h>          /* for PATH_MAX */
     60 #include <stdarg.h>          /* for va_list */
     61 #include <stdio.h>           /* need this to override stdio's (v)snprintf */
     62 #include <sys/types.h>       /* for _off_t */
     63 #include <assert.h>
     64 #include <stdlib.h>          /* for rand, srand, _strtoxxx */
     65 
     66 /*
     67  * 4018: signed/unsigned mismatch is common (and ok for signed_i < unsigned_i)
     68  * 4244: otherwise we get problems when subtracting two size_t's to an int
     69  * 4288: VC++7 gets confused when a var is defined in a loop and then after it
     70  * 4267: too many false positives for "conversion gives possible data loss"
     71  * 4290: it's ok windows ignores the "throw" directive
     72  * 4996: Yes, we're ok using "unsafe" functions like vsnprintf and getenv()
     73  * 4146: internal_logging.cc intentionally negates an unsigned value
     74  */
     75 #ifdef _MSC_VER
     76 #pragma warning(disable:4018 4244 4288 4267 4290 4996 4146)
     77 #endif
     78 
     79 #ifndef __cplusplus
     80 /* MSVC does not support C99 */
     81 # if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
     82 #  ifdef _MSC_VER
     83 #    define inline __inline
     84 #  else
     85 #    define inline static
     86 #  endif
     87 # endif
     88 #endif
     89 
     90 #ifdef __cplusplus
     91 # define EXTERN_C  extern "C"
     92 #else
     93 # define EXTERN_C  extern
     94 #endif
     95 
     96 /* ----------------------------------- BASIC TYPES */
     97 
     98 #ifndef HAVE_STDINT_H
     99 #ifndef HAVE___INT64    /* we need to have all the __intX names */
    100 # error  Do not know how to set up type aliases.  Edit port.h for your system.
    101 #endif
    102 
    103 typedef __int8 int8_t;
    104 typedef __int16 int16_t;
    105 typedef __int32 int32_t;
    106 typedef __int64 int64_t;
    107 typedef unsigned __int8 uint8_t;
    108 typedef unsigned __int16 uint16_t;
    109 typedef unsigned __int32 uint32_t;
    110 typedef unsigned __int64 uint64_t;
    111 #endif  /* #ifndef HAVE_STDINT_H */
    112 
    113 /* I guess MSVC's <types.h> doesn't include ssize_t by default? */
    114 #ifdef _MSC_VER
    115 typedef intptr_t ssize_t;
    116 #endif
    117 
    118 /* ----------------------------------- THREADS */
    119 
    120 #ifndef HAVE_PTHREAD   /* not true for MSVC, but may be true for MSYS */
    121 typedef DWORD pthread_t;
    122 typedef DWORD pthread_key_t;
    123 typedef LONG pthread_once_t;
    124 enum { PTHREAD_ONCE_INIT = 0 };   /* important that this be 0! for SpinLock */
    125 
    126 inline pthread_t pthread_self(void) {
    127   return GetCurrentThreadId();
    128 }
    129 
    130 #ifdef __cplusplus
    131 inline bool pthread_equal(pthread_t left, pthread_t right) {
    132   return left == right;
    133 }
    134 
    135 /* This replaces maybe_threads.{h,cc} */
    136 EXTERN_C pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*));  /* port.cc */
    137 
    138 inline int perftools_pthread_key_create(pthread_key_t *pkey,
    139                                         void (*destructor)(void*)) {
    140   pthread_key_t key = PthreadKeyCreate(destructor);
    141   if (key != TLS_OUT_OF_INDEXES) {
    142     *(pkey) = key;
    143     return 0;
    144   } else {
    145     return GetLastError();
    146   }
    147 }
    148 
    149 inline void* perftools_pthread_getspecific(DWORD key) {
    150   DWORD err = GetLastError();
    151   void* rv = TlsGetValue(key);
    152   if (err) SetLastError(err);
    153   return rv;
    154 }
    155 
    156 inline int perftools_pthread_setspecific(pthread_key_t key, const void *value) {
    157   if (TlsSetValue(key, (LPVOID)value))
    158     return 0;
    159   else
    160     return GetLastError();
    161 }
    162 
    163 EXTERN_C int perftools_pthread_once(pthread_once_t *once_control,
    164                                     void (*init_routine)(void));
    165 
    166 #endif  /* __cplusplus */
    167 #endif  /* HAVE_PTHREAD */
    168 
    169 inline void sched_yield(void) {
    170   Sleep(0);
    171 }
    172 
    173 /*
    174  * __declspec(thread) isn't usable in a dll opened via LoadLibrary().
    175  * But it doesn't work to LoadLibrary() us anyway, because of all the
    176  * things we need to do before main()!  So this kind of TLS is safe for us.
    177  */
    178 #define __thread __declspec(thread)
    179 
    180 /*
    181  * This code is obsolete, but I keep it around in case we are ever in
    182  * an environment where we can't or don't want to use google spinlocks
    183  * (from base/spinlock.{h,cc}).  In that case, uncommenting this out,
    184  * and removing spinlock.cc from the build, should be enough to revert
    185  * back to using native spinlocks.
    186  */
    187 #if 0
    188 // Windows uses a spinlock internally for its mutexes, making our life easy!
    189 // However, the Windows spinlock must always be initialized, making life hard,
    190 // since we want LINKER_INITIALIZED.  We work around this by having the
    191 // linker initialize a bool to 0, and check that before accessing the mutex.
    192 // This replaces spinlock.{h,cc}, and all the stuff it depends on (atomicops)
    193 #ifdef __cplusplus
    194 class SpinLock {
    195  public:
    196   SpinLock() : initialize_token_(PTHREAD_ONCE_INIT) {}
    197   // Used for global SpinLock vars (see base/spinlock.h for more details).
    198   enum StaticInitializer { LINKER_INITIALIZED };
    199   explicit SpinLock(StaticInitializer) : initialize_token_(PTHREAD_ONCE_INIT) {
    200     perftools_pthread_once(&initialize_token_, InitializeMutex);
    201   }
    202 
    203   // It's important SpinLock not have a destructor: otherwise we run
    204   // into problems when the main thread has exited, but other threads
    205   // are still running and try to access a main-thread spinlock.  This
    206   // means we leak mutex_ (we should call DeleteCriticalSection()
    207   // here).  However, I've verified that all SpinLocks used in
    208   // perftools have program-long scope anyway, so the leak is
    209   // perfectly fine.  But be aware of this for the future!
    210 
    211   void Lock() {
    212     // You'd thionk this would be unnecessary, since we call
    213     // InitializeMutex() in our constructor.  But sometimes Lock() can
    214     // be called before our constructor is!  This can only happen in
    215     // global constructors, when this is a global.  If we live in
    216     // bar.cc, and some global constructor in foo.cc calls a routine
    217     // in bar.cc that calls this->Lock(), then Lock() may well run
    218     // before our global constructor does.  To protect against that,
    219     // we do this check.  For SpinLock objects created after main()
    220     // has started, this pthread_once call will always be a noop.
    221     perftools_pthread_once(&initialize_token_, InitializeMutex);
    222     EnterCriticalSection(&mutex_);
    223   }
    224   void Unlock() {
    225     LeaveCriticalSection(&mutex_);
    226   }
    227 
    228   // Used in assertion checks: assert(lock.IsHeld()) (see base/spinlock.h).
    229   inline bool IsHeld() const {
    230     // This works, but probes undocumented internals, so I've commented it out.
    231     // c.f. http://msdn.microsoft.com/msdnmag/issues/03/12/CriticalSections/
    232     //return mutex_.LockCount>=0 && mutex_.OwningThread==GetCurrentThreadId();
    233     return true;
    234   }
    235  private:
    236   void InitializeMutex() { InitializeCriticalSection(&mutex_); }
    237 
    238   pthread_once_t initialize_token_;
    239   CRITICAL_SECTION mutex_;
    240 };
    241 
    242 class SpinLockHolder {  // Acquires a spinlock for as long as the scope lasts
    243  private:
    244   SpinLock* lock_;
    245  public:
    246   inline explicit SpinLockHolder(SpinLock* l) : lock_(l) { l->Lock(); }
    247   inline ~SpinLockHolder() { lock_->Unlock(); }
    248 };
    249 #endif  // #ifdef __cplusplus
    250 
    251 // This keeps us from using base/spinlock.h's implementation of SpinLock.
    252 #define BASE_SPINLOCK_H_ 1
    253 
    254 #endif  /* #if 0 */
    255 
    256 /* ----------------------------------- MMAP and other memory allocation */
    257 
    258 #ifndef HAVE_MMAP   /* not true for MSVC, but may be true for msys */
    259 #define MAP_FAILED  0
    260 #define MREMAP_FIXED  2  /* the value in linux, though it doesn't really matter */
    261 /* These, when combined with the mmap invariants below, yield the proper action */
    262 #define PROT_READ      PAGE_READWRITE
    263 #define PROT_WRITE     PAGE_READWRITE
    264 #define MAP_ANONYMOUS  MEM_RESERVE
    265 #define MAP_PRIVATE    MEM_COMMIT
    266 #define MAP_SHARED     MEM_RESERVE   /* value of this #define is 100% arbitrary */
    267 
    268 #if __STDC__ && !defined(__MINGW32__)
    269 typedef _off_t off_t;
    270 #endif
    271 
    272 /* VirtualAlloc only replaces for mmap when certain invariants are kept. */
    273 inline void *mmap(void *addr, size_t length, int prot, int flags,
    274                   int fd, off_t offset) {
    275   if (addr == NULL && fd == -1 && offset == 0 &&
    276       prot == (PROT_READ|PROT_WRITE) && flags == (MAP_PRIVATE|MAP_ANONYMOUS)) {
    277     return VirtualAlloc(0, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    278   } else {
    279     return NULL;
    280   }
    281 }
    282 
    283 inline int munmap(void *addr, size_t length) {
    284   return VirtualFree(addr, 0, MEM_RELEASE) ? 0 : -1;
    285 }
    286 #endif  /* HAVE_MMAP */
    287 
    288 /* We could maybe use VirtualAlloc for sbrk as well, but no need */
    289 inline void *sbrk(intptr_t increment) {
    290   // sbrk returns -1 on failure
    291   return (void*)-1;
    292 }
    293 
    294 
    295 /* ----------------------------------- STRING ROUTINES */
    296 
    297 /*
    298  * We can't just use _vsnprintf and _snprintf as drop-in-replacements,
    299  * because they don't always NUL-terminate. :-(  We also can't use the
    300  * name vsnprintf, since windows defines that (but not snprintf (!)).
    301  */
    302 #if defined(_MSC_VER) && _MSC_VER >= 1400
    303 /* We can use safe CRT functions, which the required functionality */
    304 inline int perftools_vsnprintf(char *str, size_t size, const char *format,
    305                                va_list ap) {
    306   return vsnprintf_s(str, size, _TRUNCATE, format, ap);
    307 }
    308 #else
    309 inline int perftools_vsnprintf(char *str, size_t size, const char *format,
    310                                va_list ap) {
    311   if (size == 0)        /* not even room for a \0? */
    312     return -1;        /* not what C99 says to do, but what windows does */
    313   str[size-1] = '\0';
    314   return _vsnprintf(str, size-1, format, ap);
    315 }
    316 #endif
    317 
    318 #ifndef HAVE_SNPRINTF
    319 inline int snprintf(char *str, size_t size, const char *format, ...) {
    320   va_list ap;
    321   int r;
    322   va_start(ap, format);
    323   r = perftools_vsnprintf(str, size, format, ap);
    324   va_end(ap);
    325   return r;
    326 }
    327 #endif
    328 
    329 #define PRIx64  "I64x"
    330 #define SCNx64  "I64x"
    331 #define PRId64  "I64d"
    332 #define SCNd64  "I64d"
    333 #define PRIu64  "I64u"
    334 #ifdef _WIN64
    335 # define PRIuPTR "llu"
    336 # define PRIxPTR "llx"
    337 #else
    338 # define PRIuPTR "lu"
    339 # define PRIxPTR "lx"
    340 #endif
    341 
    342 /* ----------------------------------- FILE IO */
    343 
    344 #ifndef PATH_MAX
    345 #define PATH_MAX 1024
    346 #endif
    347 #ifndef __MINGW32__
    348 enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
    349 #endif
    350 #ifndef O_RDONLY
    351 #define O_RDONLY  _O_RDONLY
    352 #endif
    353 
    354 #if __STDC__ && !defined(__MINGW32__)
    355 /* These functions are considered non-standard */
    356 inline int access(const char *pathname, int mode) {
    357   return _access(pathname, mode);
    358 }
    359 inline int open(const char *pathname, int flags, int mode = 0) {
    360   return _open(pathname, flags, mode);
    361 }
    362 inline int close(int fd) {
    363   return _close(fd);
    364 }
    365 inline ssize_t read(int fd, void *buf, size_t count) {
    366   return _read(fd, buf, count);
    367 }
    368 inline ssize_t write(int fd, const void *buf, size_t count) {
    369   return _write(fd, buf, count);
    370 }
    371 inline off_t lseek(int fd, off_t offset, int whence) {
    372   return _lseek(fd, offset, whence);
    373 }
    374 inline char *getcwd(char *buf, size_t size) {
    375   return _getcwd(buf, size);
    376 }
    377 inline int mkdir(const char *pathname, int) {
    378   return _mkdir(pathname);
    379 }
    380 
    381 inline FILE *popen(const char *command, const char *type) {
    382   return _popen(command, type);
    383 }
    384 inline int pclose(FILE *stream) {
    385   return _pclose(stream);
    386 }
    387 #endif
    388 
    389 EXTERN_C PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len);
    390 
    391 /* ----------------------------------- SYSTEM/PROCESS */
    392 
    393 typedef int pid_t;
    394 #if __STDC__ && !defined(__MINGW32__)
    395 inline pid_t getpid(void) { return _getpid(); }
    396 #endif
    397 inline pid_t getppid(void) { return 0; }
    398 
    399 /* Handle case when poll is used to simulate sleep. */
    400 inline int poll(struct pollfd* fds, int nfds, int timeout) {
    401   assert(fds == NULL);
    402   assert(nfds == 0);
    403   Sleep(timeout);
    404   return 0;
    405 }
    406 
    407 EXTERN_C int getpagesize();   /* in port.cc */
    408 
    409 /* ----------------------------------- OTHER */
    410 
    411 inline void srandom(unsigned int seed) { srand(seed); }
    412 inline long random(void) { return rand(); }
    413 inline unsigned int sleep(unsigned int seconds) {
    414   Sleep(seconds * 1000);
    415   return 0;
    416 }
    417 
    418 // mingw64 seems to define timespec (though mingw.org mingw doesn't),
    419 // protected by the _TIMESPEC_DEFINED macro.
    420 #ifndef _TIMESPEC_DEFINED
    421 struct timespec {
    422   int tv_sec;
    423   int tv_nsec;
    424 };
    425 #endif
    426 
    427 inline int nanosleep(const struct timespec *req, struct timespec *rem) {
    428   Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000);
    429   return 0;
    430 }
    431 
    432 #ifndef __MINGW32__
    433 inline long long int strtoll(const char *nptr, char **endptr, int base) {
    434     return _strtoi64(nptr, endptr, base);
    435 }
    436 inline unsigned long long int strtoull(const char *nptr, char **endptr,
    437                                        int base) {
    438     return _strtoui64(nptr, endptr, base);
    439 }
    440 inline long long int strtoq(const char *nptr, char **endptr, int base) {
    441     return _strtoi64(nptr, endptr, base);
    442 }
    443 inline unsigned long long int strtouq(const char *nptr, char **endptr,
    444                                       int base) {
    445     return _strtoui64(nptr, endptr, base);
    446 }
    447 inline long long atoll(const char *nptr) {
    448   return _atoi64(nptr);
    449 }
    450 #endif
    451 
    452 #define __THROW throw()
    453 
    454 /* ----------------------------------- TCMALLOC-SPECIFIC */
    455 
    456 /* tcmalloc.cc calls this so we can patch VirtualAlloc() et al. */
    457 extern void PatchWindowsFunctions();
    458 
    459 // ----------------------------------- BUILD-SPECIFIC
    460 
    461 /*
    462  * windows/port.h defines compatibility APIs for several .h files, which
    463  * we therefore shouldn't be #including directly.  This hack keeps us from
    464  * doing so.  TODO(csilvers): do something more principled.
    465  */
    466 #define GOOGLE_MAYBE_THREADS_H_ 1
    467 
    468 
    469 #endif  /* _WIN32 */
    470 
    471 #undef inline
    472 #undef EXTERN_C
    473 
    474 #endif  /* GOOGLE_BASE_WINDOWS_H_ */
    475