port.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
  2. /* Copyright (c) 2007, Google Inc.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above
  12. * copyright notice, this list of conditions and the following disclaimer
  13. * in the documentation and/or other materials provided with the
  14. * distribution.
  15. * * Neither the name of Google Inc. nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. * ---
  32. * Author: Craig Silverstein
  33. *
  34. * These are some portability typedefs and defines to make it a bit
  35. * easier to compile this code under VC++.
  36. *
  37. * Several of these are taken from glib:
  38. * http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
  39. */
  40. #ifndef GOOGLE_BASE_WINDOWS_H_
  41. #define GOOGLE_BASE_WINDOWS_H_
  42. /* You should never include this file directly, but always include it
  43. from either config.h (MSVC) or mingw.h (MinGW/msys). */
  44. #if !defined(GOOGLE_PERFTOOLS_WINDOWS_CONFIG_H_) && \
  45. !defined(GOOGLE_PERFTOOLS_WINDOWS_MINGW_H_)
  46. # error "port.h should only be included from config.h or mingw.h"
  47. #endif
  48. #ifdef _WIN32
  49. #ifndef WIN32_LEAN_AND_MEAN
  50. #define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
  51. #endif
  52. #include <windows.h>
  53. #include <io.h> /* because we so often use open/close/etc */
  54. #include <direct.h> /* for _getcwd */
  55. #include <process.h> /* for _getpid */
  56. #include <limits.h> /* for PATH_MAX */
  57. #include <stdarg.h> /* for va_list */
  58. #include <stdio.h> /* need this to override stdio's (v)snprintf */
  59. #include <sys/types.h> /* for _off_t */
  60. #include <assert.h>
  61. #include <stdlib.h> /* for rand, srand, _strtoxxx */
  62. #if defined(_MSC_VER) && _MSC_VER >= 1900
  63. #define _TIMESPEC_DEFINED
  64. #include <time.h>
  65. #endif
  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. #ifndef __cplusplus
  79. /* MSVC does not support C99 */
  80. # if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
  81. # ifdef _MSC_VER
  82. # define inline __inline
  83. # else
  84. # define inline static
  85. # endif
  86. # endif
  87. #endif
  88. #ifdef __cplusplus
  89. # define EXTERN_C extern "C"
  90. #else
  91. # define EXTERN_C extern
  92. #endif
  93. /* ----------------------------------- BASIC TYPES */
  94. #ifndef HAVE_STDINT_H
  95. #ifndef HAVE___INT64 /* we need to have all the __intX names */
  96. # error Do not know how to set up type aliases. Edit port.h for your system.
  97. #endif
  98. typedef __int8 int8_t;
  99. typedef __int16 int16_t;
  100. typedef __int32 int32_t;
  101. typedef __int64 int64_t;
  102. typedef unsigned __int8 uint8_t;
  103. typedef unsigned __int16 uint16_t;
  104. typedef unsigned __int32 uint32_t;
  105. typedef unsigned __int64 uint64_t;
  106. #endif /* #ifndef HAVE_STDINT_H */
  107. /* I guess MSVC's <types.h> doesn't include ssize_t by default? */
  108. #ifdef _MSC_VER
  109. typedef intptr_t ssize_t;
  110. #endif
  111. /* ----------------------------------- THREADS */
  112. #ifndef HAVE_PTHREAD /* not true for MSVC, but may be true for MSYS */
  113. typedef DWORD pthread_t;
  114. typedef DWORD pthread_key_t;
  115. typedef LONG pthread_once_t;
  116. enum { PTHREAD_ONCE_INIT = 0 }; /* important that this be 0! for SpinLock */
  117. inline pthread_t pthread_self(void) {
  118. return GetCurrentThreadId();
  119. }
  120. #ifdef __cplusplus
  121. inline bool pthread_equal(pthread_t left, pthread_t right) {
  122. return left == right;
  123. }
  124. /*
  125. * windows/port.h defines compatibility APIs for several .h files, which
  126. * we therefore shouldn't be #including directly. This hack keeps us from
  127. * doing so. TODO(csilvers): do something more principled.
  128. */
  129. #define GOOGLE_MAYBE_THREADS_H_ 1
  130. /* This replaces maybe_threads.{h,cc} */
  131. EXTERN_C pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)); /* port.cc */
  132. inline int perftools_pthread_key_create(pthread_key_t *pkey,
  133. void (*destructor)(void*)) {
  134. pthread_key_t key = PthreadKeyCreate(destructor);
  135. if (key != TLS_OUT_OF_INDEXES) {
  136. *(pkey) = key;
  137. return 0;
  138. } else {
  139. return GetLastError();
  140. }
  141. }
  142. inline void* perftools_pthread_getspecific(DWORD key) {
  143. DWORD err = GetLastError();
  144. void* rv = TlsGetValue(key);
  145. if (err) SetLastError(err);
  146. return rv;
  147. }
  148. inline int perftools_pthread_setspecific(pthread_key_t key, const void *value) {
  149. if (TlsSetValue(key, (LPVOID)value))
  150. return 0;
  151. else
  152. return GetLastError();
  153. }
  154. EXTERN_C int perftools_pthread_once(pthread_once_t *once_control,
  155. void (*init_routine)(void));
  156. #endif /* __cplusplus */
  157. inline void sched_yield(void) {
  158. Sleep(0);
  159. }
  160. #endif /* HAVE_PTHREAD */
  161. /*
  162. * __declspec(thread) isn't usable in a dll opened via LoadLibrary().
  163. * But it doesn't work to LoadLibrary() us anyway, because of all the
  164. * things we need to do before main()! So this kind of TLS is safe for us.
  165. */
  166. #define __thread __declspec(thread)
  167. /*
  168. * This code is obsolete, but I keep it around in case we are ever in
  169. * an environment where we can't or don't want to use google spinlocks
  170. * (from base/spinlock.{h,cc}). In that case, uncommenting this out,
  171. * and removing spinlock.cc from the build, should be enough to revert
  172. * back to using native spinlocks.
  173. */
  174. #if 0
  175. // Windows uses a spinlock internally for its mutexes, making our life easy!
  176. // However, the Windows spinlock must always be initialized, making life hard,
  177. // since we want LINKER_INITIALIZED. We work around this by having the
  178. // linker initialize a bool to 0, and check that before accessing the mutex.
  179. // This replaces spinlock.{h,cc}, and all the stuff it depends on (atomicops)
  180. #ifdef __cplusplus
  181. class SpinLock {
  182. public:
  183. SpinLock() : initialize_token_(PTHREAD_ONCE_INIT) {}
  184. // Used for global SpinLock vars (see base/spinlock.h for more details).
  185. enum StaticInitializer { LINKER_INITIALIZED };
  186. explicit SpinLock(StaticInitializer) : initialize_token_(PTHREAD_ONCE_INIT) {
  187. perftools_pthread_once(&initialize_token_, InitializeMutex);
  188. }
  189. // It's important SpinLock not have a destructor: otherwise we run
  190. // into problems when the main thread has exited, but other threads
  191. // are still running and try to access a main-thread spinlock. This
  192. // means we leak mutex_ (we should call DeleteCriticalSection()
  193. // here). However, I've verified that all SpinLocks used in
  194. // perftools have program-long scope anyway, so the leak is
  195. // perfectly fine. But be aware of this for the future!
  196. void Lock() {
  197. // You'd thionk this would be unnecessary, since we call
  198. // InitializeMutex() in our constructor. But sometimes Lock() can
  199. // be called before our constructor is! This can only happen in
  200. // global constructors, when this is a global. If we live in
  201. // bar.cc, and some global constructor in foo.cc calls a routine
  202. // in bar.cc that calls this->Lock(), then Lock() may well run
  203. // before our global constructor does. To protect against that,
  204. // we do this check. For SpinLock objects created after main()
  205. // has started, this pthread_once call will always be a noop.
  206. perftools_pthread_once(&initialize_token_, InitializeMutex);
  207. EnterCriticalSection(&mutex_);
  208. }
  209. void Unlock() {
  210. LeaveCriticalSection(&mutex_);
  211. }
  212. // Used in assertion checks: assert(lock.IsHeld()) (see base/spinlock.h).
  213. inline bool IsHeld() const {
  214. // This works, but probes undocumented internals, so I've commented it out.
  215. // c.f. http://msdn.microsoft.com/msdnmag/issues/03/12/CriticalSections/
  216. //return mutex_.LockCount>=0 && mutex_.OwningThread==GetCurrentThreadId();
  217. return true;
  218. }
  219. private:
  220. void InitializeMutex() { InitializeCriticalSection(&mutex_); }
  221. pthread_once_t initialize_token_;
  222. CRITICAL_SECTION mutex_;
  223. };
  224. class SpinLockHolder { // Acquires a spinlock for as long as the scope lasts
  225. private:
  226. SpinLock* lock_;
  227. public:
  228. inline explicit SpinLockHolder(SpinLock* l) : lock_(l) { l->Lock(); }
  229. inline ~SpinLockHolder() { lock_->Unlock(); }
  230. };
  231. #endif // #ifdef __cplusplus
  232. // This keeps us from using base/spinlock.h's implementation of SpinLock.
  233. #define BASE_SPINLOCK_H_ 1
  234. #endif /* #if 0 */
  235. /* ----------------------------------- MMAP and other memory allocation */
  236. #ifndef HAVE_MMAP /* not true for MSVC, but may be true for msys */
  237. #define MAP_FAILED 0
  238. #define MREMAP_FIXED 2 /* the value in linux, though it doesn't really matter */
  239. /* These, when combined with the mmap invariants below, yield the proper action */
  240. #define PROT_READ PAGE_READWRITE
  241. #define PROT_WRITE PAGE_READWRITE
  242. #define MAP_ANONYMOUS MEM_RESERVE
  243. #define MAP_PRIVATE MEM_COMMIT
  244. #define MAP_SHARED MEM_RESERVE /* value of this #define is 100% arbitrary */
  245. #if __STDC__ && !defined(__MINGW32__)
  246. typedef _off_t off_t;
  247. #endif
  248. /* VirtualAlloc only replaces for mmap when certain invariants are kept. */
  249. inline void *mmap(void *addr, size_t length, int prot, int flags,
  250. int fd, off_t offset) {
  251. if (addr == NULL && fd == -1 && offset == 0 &&
  252. prot == (PROT_READ|PROT_WRITE) && flags == (MAP_PRIVATE|MAP_ANONYMOUS)) {
  253. return VirtualAlloc(0, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  254. } else {
  255. return NULL;
  256. }
  257. }
  258. inline int munmap(void *addr, size_t length) {
  259. return VirtualFree(addr, 0, MEM_RELEASE) ? 0 : -1;
  260. }
  261. #endif /* HAVE_MMAP */
  262. /* We could maybe use VirtualAlloc for sbrk as well, but no need */
  263. inline void *sbrk(intptr_t increment) {
  264. // sbrk returns -1 on failure
  265. return (void*)-1;
  266. }
  267. /* ----------------------------------- STRING ROUTINES */
  268. /*
  269. * We can't just use _vsnprintf and _snprintf as drop-in-replacements,
  270. * because they don't always NUL-terminate. :-( We also can't use the
  271. * name vsnprintf, since windows defines that (but not snprintf (!)).
  272. */
  273. #if defined(_MSC_VER) && _MSC_VER >= 1400
  274. /* We can use safe CRT functions, which the required functionality */
  275. inline int perftools_vsnprintf(char *str, size_t size, const char *format,
  276. va_list ap) {
  277. return vsnprintf_s(str, size, _TRUNCATE, format, ap);
  278. }
  279. #else
  280. inline int perftools_vsnprintf(char *str, size_t size, const char *format,
  281. va_list ap) {
  282. if (size == 0) /* not even room for a \0? */
  283. return -1; /* not what C99 says to do, but what windows does */
  284. str[size-1] = '\0';
  285. return _vsnprintf(str, size-1, format, ap);
  286. }
  287. #endif
  288. #ifndef HAVE_SNPRINTF
  289. inline int snprintf(char *str, size_t size, const char *format, ...) {
  290. va_list ap;
  291. int r;
  292. va_start(ap, format);
  293. r = perftools_vsnprintf(str, size, format, ap);
  294. va_end(ap);
  295. return r;
  296. }
  297. #endif
  298. #define PRIx64 "I64x"
  299. #define SCNx64 "I64x"
  300. #define PRId64 "I64d"
  301. #define SCNd64 "I64d"
  302. #define PRIu64 "I64u"
  303. #ifdef _WIN64
  304. # define PRIuPTR "llu"
  305. # define PRIxPTR "llx"
  306. #else
  307. # define PRIuPTR "lu"
  308. # define PRIxPTR "lx"
  309. #endif
  310. /* ----------------------------------- FILE IO */
  311. #ifndef PATH_MAX
  312. #define PATH_MAX 1024
  313. #endif
  314. #ifndef __MINGW32__
  315. enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
  316. #endif
  317. #ifndef O_RDONLY
  318. #define O_RDONLY _O_RDONLY
  319. #endif
  320. #if __STDC__ && !defined(__MINGW32__)
  321. /* These functions are considered non-standard */
  322. inline int access(const char *pathname, int mode) {
  323. return _access(pathname, mode);
  324. }
  325. inline int open(const char *pathname, int flags, int mode = 0) {
  326. return _open(pathname, flags, mode);
  327. }
  328. inline int close(int fd) {
  329. return _close(fd);
  330. }
  331. inline ssize_t read(int fd, void *buf, size_t count) {
  332. return _read(fd, buf, count);
  333. }
  334. inline ssize_t write(int fd, const void *buf, size_t count) {
  335. return _write(fd, buf, count);
  336. }
  337. inline off_t lseek(int fd, off_t offset, int whence) {
  338. return _lseek(fd, offset, whence);
  339. }
  340. inline char *getcwd(char *buf, size_t size) {
  341. return _getcwd(buf, size);
  342. }
  343. inline int mkdir(const char *pathname, int) {
  344. return _mkdir(pathname);
  345. }
  346. inline FILE *popen(const char *command, const char *type) {
  347. return _popen(command, type);
  348. }
  349. inline int pclose(FILE *stream) {
  350. return _pclose(stream);
  351. }
  352. #endif
  353. EXTERN_C PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len);
  354. /* ----------------------------------- SYSTEM/PROCESS */
  355. #ifndef HAVE_PID_T
  356. typedef int pid_t;
  357. #endif
  358. #if __STDC__ && !defined(__MINGW32__)
  359. inline pid_t getpid(void) { return _getpid(); }
  360. #endif
  361. inline pid_t getppid(void) { return 0; }
  362. /* Handle case when poll is used to simulate sleep. */
  363. inline int poll(struct pollfd* fds, int nfds, int timeout) {
  364. assert(fds == NULL);
  365. assert(nfds == 0);
  366. Sleep(timeout);
  367. return 0;
  368. }
  369. EXTERN_C PERFTOOLS_DLL_DECL int getpagesize(); /* in port.cc */
  370. /* ----------------------------------- OTHER */
  371. inline void srandom(unsigned int seed) { srand(seed); }
  372. inline long random(void) { return rand(); }
  373. #ifndef HAVE_DECL_SLEEP
  374. #define HAVE_DECL_SLEEP 0
  375. #endif
  376. #if !HAVE_DECL_SLEEP
  377. inline unsigned int sleep(unsigned int seconds) {
  378. Sleep(seconds * 1000);
  379. return 0;
  380. }
  381. #endif
  382. // mingw64 seems to define timespec (though mingw.org mingw doesn't),
  383. // protected by the _TIMESPEC_DEFINED macro.
  384. #ifndef _TIMESPEC_DEFINED
  385. struct timespec {
  386. int tv_sec;
  387. int tv_nsec;
  388. };
  389. #endif
  390. #ifndef HAVE_DECL_NANOSLEEP
  391. #define HAVE_DECL_NANOSLEEP 0
  392. #endif
  393. // latest mingw64 has nanosleep. Earlier mingw and MSVC do not
  394. #if !HAVE_DECL_NANOSLEEP
  395. inline int nanosleep(const struct timespec *req, struct timespec *rem) {
  396. Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000);
  397. return 0;
  398. }
  399. #endif
  400. #ifndef __MINGW32__
  401. #if defined(_MSC_VER) && _MSC_VER < 1800
  402. inline long long int strtoll(const char *nptr, char **endptr, int base) {
  403. return _strtoi64(nptr, endptr, base);
  404. }
  405. inline unsigned long long int strtoull(const char *nptr, char **endptr,
  406. int base) {
  407. return _strtoui64(nptr, endptr, base);
  408. }
  409. inline long long int strtoq(const char *nptr, char **endptr, int base) {
  410. return _strtoi64(nptr, endptr, base);
  411. }
  412. #endif
  413. inline unsigned long long int strtouq(const char *nptr, char **endptr,
  414. int base) {
  415. return _strtoui64(nptr, endptr, base);
  416. }
  417. inline long long atoll(const char *nptr) {
  418. return _atoi64(nptr);
  419. }
  420. #endif
  421. #define __THROW throw()
  422. /* ----------------------------------- TCMALLOC-SPECIFIC */
  423. /* tcmalloc.cc calls this so we can patch VirtualAlloc() et al. */
  424. extern void PatchWindowsFunctions();
  425. #endif /* _WIN32 */
  426. #undef inline
  427. #undef EXTERN_C
  428. #endif /* GOOGLE_BASE_WINDOWS_H_ */