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_ */ 480