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