| /* Copyright (c) 2007, Google Inc. | 
 |  * All rights reserved. | 
 |  * | 
 |  * Redistribution and use in source and binary forms, with or without | 
 |  * modification, are permitted provided that the following conditions are | 
 |  * met: | 
 |  * | 
 |  *     * Redistributions of source code must retain the above copyright | 
 |  * notice, this list of conditions and the following disclaimer. | 
 |  *     * Redistributions in binary form must reproduce the above | 
 |  * copyright notice, this list of conditions and the following disclaimer | 
 |  * in the documentation and/or other materials provided with the | 
 |  * distribution. | 
 |  *     * Neither the name of Google Inc. nor the names of its | 
 |  * contributors may be used to endorse or promote products derived from | 
 |  * this software without specific prior written permission. | 
 |  * | 
 |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
 |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
 |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
 |  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
 |  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
 |  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
 |  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
 |  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
 |  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
 |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
 |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
 |  * | 
 |  * --- | 
 |  * Author: Craig Silverstein | 
 |  * | 
 |  * These are some portability typedefs and defines to make it a bit | 
 |  * easier to compile this code under VC++. | 
 |  * | 
 |  * Several of these are taken from glib: | 
 |  *    http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html | 
 |  */ | 
 |  | 
 | #ifndef GOOGLE_BASE_WINDOWS_H_ | 
 | #define GOOGLE_BASE_WINDOWS_H_ | 
 |  | 
 | /* You should never include this file directly, but always include it | 
 |    from either config.h (MSVC) or mingw.h (MinGW/msys). */ | 
 | #if !defined(GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_) && \ | 
 |     !defined(GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_) | 
 | # error "port.h should only be included from config.h or mingw.h" | 
 | #endif | 
 |  | 
 | #ifdef _WIN32 | 
 |  | 
 | #ifndef WIN32_LEAN_AND_MEAN | 
 | #define WIN32_LEAN_AND_MEAN  /* We always want minimal includes */ | 
 | #endif | 
 | #include <windows.h> | 
 | #include <io.h>              /* because we so often use open/close/etc */ | 
 | #include <direct.h>          /* for _getcwd */ | 
 | #include <process.h>         /* for _getpid */ | 
 | #include <limits.h>          /* for PATH_MAX */ | 
 | #include <stdarg.h>          /* for va_list */ | 
 | #include <stdio.h>           /* need this to override stdio's (v)snprintf */ | 
 | #include <sys/types.h>       /* for _off_t */ | 
 | #include <assert.h> | 
 | #include <stdlib.h>          /* for rand, srand, _strtoxxx */ | 
 |  | 
 | /* | 
 |  * 4018: signed/unsigned mismatch is common (and ok for signed_i < unsigned_i) | 
 |  * 4244: otherwise we get problems when subtracting two size_t's to an int | 
 |  * 4288: VC++7 gets confused when a var is defined in a loop and then after it | 
 |  * 4267: too many false positives for "conversion gives possible data loss" | 
 |  * 4290: it's ok windows ignores the "throw" directive | 
 |  * 4996: Yes, we're ok using "unsafe" functions like vsnprintf and getenv() | 
 |  * 4146: internal_logging.cc intentionally negates an unsigned value | 
 |  */ | 
 | #ifdef _MSC_VER | 
 | #pragma warning(disable:4018 4244 4288 4267 4290 4996 4146) | 
 | #endif | 
 |  | 
 | #ifndef __cplusplus | 
 | /* MSVC does not support C99 */ | 
 | # if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L | 
 | #  ifdef _MSC_VER | 
 | #    define inline __inline | 
 | #  else | 
 | #    define inline static | 
 | #  endif | 
 | # endif | 
 | #endif | 
 |  | 
 | #ifdef __cplusplus | 
 | # define EXTERN_C  extern "C" | 
 | #else | 
 | # define EXTERN_C  extern | 
 | #endif | 
 |  | 
 | /* ----------------------------------- BASIC TYPES */ | 
 |  | 
 | #ifndef HAVE_STDINT_H | 
 | #ifndef HAVE___INT64    /* we need to have all the __intX names */ | 
 | # error  Do not know how to set up type aliases.  Edit port.h for your system. | 
 | #endif | 
 |  | 
 | typedef __int8 int8_t; | 
 | typedef __int16 int16_t; | 
 | typedef __int32 int32_t; | 
 | typedef __int64 int64_t; | 
 | typedef unsigned __int8 uint8_t; | 
 | typedef unsigned __int16 uint16_t; | 
 | typedef unsigned __int32 uint32_t; | 
 | typedef unsigned __int64 uint64_t; | 
 | #endif  /* #ifndef HAVE_STDINT_H */ | 
 |  | 
 | /* I guess MSVC's <types.h> doesn't include ssize_t by default? */ | 
 | #ifdef _MSC_VER | 
 | typedef intptr_t ssize_t; | 
 | #endif | 
 |  | 
 | /* ----------------------------------- THREADS */ | 
 |  | 
 | #ifndef HAVE_PTHREAD   /* not true for MSVC, but may be true for MSYS */ | 
 | typedef DWORD pthread_t; | 
 | typedef DWORD pthread_key_t; | 
 | typedef LONG pthread_once_t; | 
 | enum { PTHREAD_ONCE_INIT = 0 };   /* important that this be 0! for SpinLock */ | 
 |  | 
 | inline pthread_t pthread_self(void) { | 
 |   return GetCurrentThreadId(); | 
 | } | 
 |  | 
 | #ifdef __cplusplus | 
 | inline bool pthread_equal(pthread_t left, pthread_t right) { | 
 |   return left == right; | 
 | } | 
 |  | 
 | /* This replaces maybe_threads.{h,cc} */ | 
 | EXTERN_C pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*));  /* port.cc */ | 
 |  | 
 | inline int perftools_pthread_key_create(pthread_key_t *pkey, | 
 |                                         void (*destructor)(void*)) { | 
 |   pthread_key_t key = PthreadKeyCreate(destructor); | 
 |   if (key != TLS_OUT_OF_INDEXES) { | 
 |     *(pkey) = key; | 
 |     return 0; | 
 |   } else { | 
 |     return GetLastError(); | 
 |   } | 
 | } | 
 |  | 
 | inline void* perftools_pthread_getspecific(DWORD key) { | 
 |   DWORD err = GetLastError(); | 
 |   void* rv = TlsGetValue(key); | 
 |   if (err) SetLastError(err); | 
 |   return rv; | 
 | } | 
 |  | 
 | inline int perftools_pthread_setspecific(pthread_key_t key, const void *value) { | 
 |   if (TlsSetValue(key, (LPVOID)value)) | 
 |     return 0; | 
 |   else | 
 |     return GetLastError(); | 
 | } | 
 |  | 
 | EXTERN_C int perftools_pthread_once(pthread_once_t *once_control, | 
 |                                     void (*init_routine)(void)); | 
 |  | 
 | #endif  /* __cplusplus */ | 
 | #endif  /* HAVE_PTHREAD */ | 
 |  | 
 | inline void sched_yield(void) { | 
 |   Sleep(0); | 
 | } | 
 |  | 
 | /* | 
 |  * __declspec(thread) isn't usable in a dll opened via LoadLibrary(). | 
 |  * But it doesn't work to LoadLibrary() us anyway, because of all the | 
 |  * things we need to do before main()!  So this kind of TLS is safe for us. | 
 |  */ | 
 | #define __thread __declspec(thread) | 
 |  | 
 | /* | 
 |  * This code is obsolete, but I keep it around in case we are ever in | 
 |  * an environment where we can't or don't want to use google spinlocks | 
 |  * (from base/spinlock.{h,cc}).  In that case, uncommenting this out, | 
 |  * and removing spinlock.cc from the build, should be enough to revert | 
 |  * back to using native spinlocks. | 
 |  */ | 
 | #if 0 | 
 | // Windows uses a spinlock internally for its mutexes, making our life easy! | 
 | // However, the Windows spinlock must always be initialized, making life hard, | 
 | // since we want LINKER_INITIALIZED.  We work around this by having the | 
 | // linker initialize a bool to 0, and check that before accessing the mutex. | 
 | // This replaces spinlock.{h,cc}, and all the stuff it depends on (atomicops) | 
 | #ifdef __cplusplus | 
 | class SpinLock { | 
 |  public: | 
 |   SpinLock() : initialize_token_(PTHREAD_ONCE_INIT) {} | 
 |   // Used for global SpinLock vars (see base/spinlock.h for more details). | 
 |   enum StaticInitializer { LINKER_INITIALIZED }; | 
 |   explicit SpinLock(StaticInitializer) : initialize_token_(PTHREAD_ONCE_INIT) { | 
 |     perftools_pthread_once(&initialize_token_, InitializeMutex); | 
 |   } | 
 |  | 
 |   // It's important SpinLock not have a destructor: otherwise we run | 
 |   // into problems when the main thread has exited, but other threads | 
 |   // are still running and try to access a main-thread spinlock.  This | 
 |   // means we leak mutex_ (we should call DeleteCriticalSection() | 
 |   // here).  However, I've verified that all SpinLocks used in | 
 |   // perftools have program-long scope anyway, so the leak is | 
 |   // perfectly fine.  But be aware of this for the future! | 
 |  | 
 |   void Lock() { | 
 |     // You'd thionk this would be unnecessary, since we call | 
 |     // InitializeMutex() in our constructor.  But sometimes Lock() can | 
 |     // be called before our constructor is!  This can only happen in | 
 |     // global constructors, when this is a global.  If we live in | 
 |     // bar.cc, and some global constructor in foo.cc calls a routine | 
 |     // in bar.cc that calls this->Lock(), then Lock() may well run | 
 |     // before our global constructor does.  To protect against that, | 
 |     // we do this check.  For SpinLock objects created after main() | 
 |     // has started, this pthread_once call will always be a noop. | 
 |     perftools_pthread_once(&initialize_token_, InitializeMutex); | 
 |     EnterCriticalSection(&mutex_); | 
 |   } | 
 |   void Unlock() { | 
 |     LeaveCriticalSection(&mutex_); | 
 |   } | 
 |  | 
 |   // Used in assertion checks: assert(lock.IsHeld()) (see base/spinlock.h). | 
 |   inline bool IsHeld() const { | 
 |     // This works, but probes undocumented internals, so I've commented it out. | 
 |     // c.f. http://msdn.microsoft.com/msdnmag/issues/03/12/CriticalSections/ | 
 |     //return mutex_.LockCount>=0 && mutex_.OwningThread==GetCurrentThreadId(); | 
 |     return true; | 
 |   } | 
 |  private: | 
 |   void InitializeMutex() { InitializeCriticalSection(&mutex_); } | 
 |  | 
 |   pthread_once_t initialize_token_; | 
 |   CRITICAL_SECTION mutex_; | 
 | }; | 
 |  | 
 | class SpinLockHolder {  // Acquires a spinlock for as long as the scope lasts | 
 |  private: | 
 |   SpinLock* lock_; | 
 |  public: | 
 |   inline explicit SpinLockHolder(SpinLock* l) : lock_(l) { l->Lock(); } | 
 |   inline ~SpinLockHolder() { lock_->Unlock(); } | 
 | }; | 
 | #endif  // #ifdef __cplusplus | 
 |  | 
 | // This keeps us from using base/spinlock.h's implementation of SpinLock. | 
 | #define BASE_SPINLOCK_H_ 1 | 
 |  | 
 | #endif  /* #if 0 */ | 
 |  | 
 | /* ----------------------------------- MMAP and other memory allocation */ | 
 |  | 
 | #ifndef HAVE_MMAP   /* not true for MSVC, but may be true for msys */ | 
 | #define MAP_FAILED  0 | 
 | #define MREMAP_FIXED  2  /* the value in linux, though it doesn't really matter */ | 
 | /* These, when combined with the mmap invariants below, yield the proper action */ | 
 | #define PROT_READ      PAGE_READWRITE | 
 | #define PROT_WRITE     PAGE_READWRITE | 
 | #define MAP_ANONYMOUS  MEM_RESERVE | 
 | #define MAP_PRIVATE    MEM_COMMIT | 
 | #define MAP_SHARED     MEM_RESERVE   /* value of this #define is 100% arbitrary */ | 
 |  | 
 | #if __STDC__ && !defined(__MINGW32__) | 
 | typedef _off_t off_t; | 
 | #endif | 
 |  | 
 | /* VirtualAlloc only replaces for mmap when certain invariants are kept. */ | 
 | inline void *mmap(void *addr, size_t length, int prot, int flags, | 
 |                   int fd, off_t offset) { | 
 |   if (addr == NULL && fd == -1 && offset == 0 && | 
 |       prot == (PROT_READ|PROT_WRITE) && flags == (MAP_PRIVATE|MAP_ANONYMOUS)) { | 
 |     return VirtualAlloc(0, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); | 
 |   } else { | 
 |     return NULL; | 
 |   } | 
 | } | 
 |  | 
 | inline int munmap(void *addr, size_t length) { | 
 |   return VirtualFree(addr, 0, MEM_RELEASE) ? 0 : -1; | 
 | } | 
 | #endif  /* HAVE_MMAP */ | 
 |  | 
 | /* We could maybe use VirtualAlloc for sbrk as well, but no need */ | 
 | inline void *sbrk(intptr_t increment) { | 
 |   // sbrk returns -1 on failure | 
 |   return (void*)-1; | 
 | } | 
 |  | 
 |  | 
 | /* ----------------------------------- STRING ROUTINES */ | 
 |  | 
 | /* | 
 |  * We can't just use _vsnprintf and _snprintf as drop-in-replacements, | 
 |  * because they don't always NUL-terminate. :-(  We also can't use the | 
 |  * name vsnprintf, since windows defines that (but not snprintf (!)). | 
 |  */ | 
 | #if defined(_MSC_VER) && _MSC_VER >= 1400 | 
 | /* We can use safe CRT functions, which the required functionality */ | 
 | inline int perftools_vsnprintf(char *str, size_t size, const char *format, | 
 |                                va_list ap) { | 
 |   return vsnprintf_s(str, size, _TRUNCATE, format, ap); | 
 | } | 
 | #else | 
 | inline int perftools_vsnprintf(char *str, size_t size, const char *format, | 
 |                                va_list ap) { | 
 |   if (size == 0)        /* not even room for a \0? */ | 
 |     return -1;        /* not what C99 says to do, but what windows does */ | 
 |   str[size-1] = '\0'; | 
 |   return _vsnprintf(str, size-1, format, ap); | 
 | } | 
 | #endif | 
 |  | 
 | #ifndef HAVE_SNPRINTF | 
 | inline int snprintf(char *str, size_t size, const char *format, ...) { | 
 |   va_list ap; | 
 |   int r; | 
 |   va_start(ap, format); | 
 |   r = perftools_vsnprintf(str, size, format, ap); | 
 |   va_end(ap); | 
 |   return r; | 
 | } | 
 | #endif | 
 |  | 
 | #define PRIx64  "I64x" | 
 | #define SCNx64  "I64x" | 
 | #define PRId64  "I64d" | 
 | #define SCNd64  "I64d" | 
 | #define PRIu64  "I64u" | 
 | #ifdef _WIN64 | 
 | # define PRIuPTR "llu" | 
 | # define PRIxPTR "llx" | 
 | #else | 
 | # define PRIuPTR "lu" | 
 | # define PRIxPTR "lx" | 
 | #endif | 
 |  | 
 | /* ----------------------------------- FILE IO */ | 
 |  | 
 | #ifndef PATH_MAX | 
 | #define PATH_MAX 1024 | 
 | #endif | 
 | #ifndef __MINGW32__ | 
 | enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 }; | 
 | #endif | 
 | #ifndef O_RDONLY | 
 | #define O_RDONLY  _O_RDONLY | 
 | #endif | 
 |  | 
 | #if __STDC__ && !defined(__MINGW32__) | 
 | /* These functions are considered non-standard */ | 
 | inline int access(const char *pathname, int mode) { | 
 |   return _access(pathname, mode); | 
 | } | 
 | inline int open(const char *pathname, int flags, int mode = 0) { | 
 |   return _open(pathname, flags, mode); | 
 | } | 
 | inline int close(int fd) { | 
 |   return _close(fd); | 
 | } | 
 | inline ssize_t read(int fd, void *buf, size_t count) { | 
 |   return _read(fd, buf, count); | 
 | } | 
 | inline ssize_t write(int fd, const void *buf, size_t count) { | 
 |   return _write(fd, buf, count); | 
 | } | 
 | inline off_t lseek(int fd, off_t offset, int whence) { | 
 |   return _lseek(fd, offset, whence); | 
 | } | 
 | inline char *getcwd(char *buf, size_t size) { | 
 |   return _getcwd(buf, size); | 
 | } | 
 | inline int mkdir(const char *pathname, int) { | 
 |   return _mkdir(pathname); | 
 | } | 
 |  | 
 | inline FILE *popen(const char *command, const char *type) { | 
 |   return _popen(command, type); | 
 | } | 
 | inline int pclose(FILE *stream) { | 
 |   return _pclose(stream); | 
 | } | 
 | #endif | 
 |  | 
 | EXTERN_C PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len); | 
 |  | 
 | /* ----------------------------------- SYSTEM/PROCESS */ | 
 |  | 
 | typedef int pid_t; | 
 | #if __STDC__ && !defined(__MINGW32__) | 
 | inline pid_t getpid(void) { return _getpid(); } | 
 | #endif | 
 | inline pid_t getppid(void) { return 0; } | 
 |  | 
 | /* Handle case when poll is used to simulate sleep. */ | 
 | inline int poll(struct pollfd* fds, int nfds, int timeout) { | 
 |   assert(fds == NULL); | 
 |   assert(nfds == 0); | 
 |   Sleep(timeout); | 
 |   return 0; | 
 | } | 
 |  | 
 | EXTERN_C int getpagesize();   /* in port.cc */ | 
 |  | 
 | /* ----------------------------------- OTHER */ | 
 |  | 
 | inline void srandom(unsigned int seed) { srand(seed); } | 
 | inline long random(void) { return rand(); } | 
 | inline unsigned int sleep(unsigned int seconds) { | 
 |   Sleep(seconds * 1000); | 
 |   return 0; | 
 | } | 
 |  | 
 | // mingw64 seems to define timespec (though mingw.org mingw doesn't), | 
 | // protected by the _TIMESPEC_DEFINED macro. | 
 | #ifndef _TIMESPEC_DEFINED | 
 | struct timespec { | 
 |   int tv_sec; | 
 |   int tv_nsec; | 
 | }; | 
 | #endif | 
 |  | 
 | inline int nanosleep(const struct timespec *req, struct timespec *rem) { | 
 |   Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000); | 
 |   return 0; | 
 | } | 
 |  | 
 | #ifndef __MINGW32__ | 
 | inline long long int strtoll(const char *nptr, char **endptr, int base) { | 
 |     return _strtoi64(nptr, endptr, base); | 
 | } | 
 | inline unsigned long long int strtoull(const char *nptr, char **endptr, | 
 |                                        int base) { | 
 |     return _strtoui64(nptr, endptr, base); | 
 | } | 
 | inline long long int strtoq(const char *nptr, char **endptr, int base) { | 
 |     return _strtoi64(nptr, endptr, base); | 
 | } | 
 | inline unsigned long long int strtouq(const char *nptr, char **endptr, | 
 |                                       int base) { | 
 |     return _strtoui64(nptr, endptr, base); | 
 | } | 
 | inline long long atoll(const char *nptr) { | 
 |   return _atoi64(nptr); | 
 | } | 
 | #endif | 
 |  | 
 | #define __THROW throw() | 
 |  | 
 | /* ----------------------------------- TCMALLOC-SPECIFIC */ | 
 |  | 
 | /* tcmalloc.cc calls this so we can patch VirtualAlloc() et al. */ | 
 | extern void PatchWindowsFunctions(); | 
 |  | 
 | // ----------------------------------- BUILD-SPECIFIC | 
 |  | 
 | /* | 
 |  * windows/port.h defines compatibility APIs for several .h files, which | 
 |  * we therefore shouldn't be #including directly.  This hack keeps us from | 
 |  * doing so.  TODO(csilvers): do something more principled. | 
 |  */ | 
 | #define GOOGLE_MAYBE_THREADS_H_ 1 | 
 |  | 
 |  | 
 | #endif  /* _WIN32 */ | 
 |  | 
 | #undef inline | 
 | #undef EXTERN_C | 
 |  | 
 | #endif  /* GOOGLE_BASE_WINDOWS_H_ */ |