1 /* Copyright (c) 2007, Google Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
31 * Author: Craig Silverstein
33 * These are some portability typedefs and defines to make it a bit
34 * easier to compile this code under VC++.
36 * Several of these are taken from glib:
37 * http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html
40 #ifndef GOOGLE_BASE_WINDOWS_H_
41 #define GOOGLE_BASE_WINDOWS_H_
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"
52 #ifndef WIN32_LEAN_AND_MEAN
53 #define WIN32_LEAN_AND_MEAN /* We always want minimal includes */
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 */
64 #include <stdlib.h> /* for rand, srand, _strtoxxx */
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
76 #pragma warning(disable:4018 4244 4288 4267 4290 4996 4146)
80 /* MSVC does not support C99 */
81 # if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
83 # define inline __inline
85 # define inline static
91 # define EXTERN_C extern "C"
93 # define EXTERN_C extern
96 /* ----------------------------------- BASIC TYPES */
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.
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 */
113 /* I guess MSVC's <types.h> doesn't include ssize_t by default? */
115 typedef intptr_t ssize_t
;
118 /* ----------------------------------- THREADS */
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 */
126 inline pthread_t
pthread_self(void) {
127 return GetCurrentThreadId();
131 inline bool pthread_equal(pthread_t left
, pthread_t right
) {
132 return left
== right
;
135 /* This replaces maybe_threads.{h,cc} */
136 EXTERN_C pthread_key_t
PthreadKeyCreate(void (*destr_fn
)(void*)); /* port.cc */
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
) {
145 return GetLastError();
149 inline void* perftools_pthread_getspecific(DWORD key
) {
150 DWORD err
= GetLastError();
151 void* rv
= TlsGetValue(key
);
152 if (err
) SetLastError(err
);
156 inline int perftools_pthread_setspecific(pthread_key_t key
, const void *value
) {
157 if (TlsSetValue(key
, (LPVOID
)value
))
160 return GetLastError();
163 EXTERN_C
int perftools_pthread_once(pthread_once_t
*once_control
,
164 void (*init_routine
)(void));
166 #endif /* __cplusplus */
167 #endif /* HAVE_PTHREAD */
169 inline void sched_yield(void) {
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.
178 #define __thread __declspec(thread)
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.
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)
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
);
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!
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_
);
225 LeaveCriticalSection(&mutex_
);
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();
236 void InitializeMutex() { InitializeCriticalSection(&mutex_
); }
238 pthread_once_t initialize_token_
;
239 CRITICAL_SECTION mutex_
;
242 class SpinLockHolder
{ // Acquires a spinlock for as long as the scope lasts
246 inline explicit SpinLockHolder(SpinLock
* l
) : lock_(l
) { l
->Lock(); }
247 inline ~SpinLockHolder() { lock_
->Unlock(); }
249 #endif // #ifdef __cplusplus
251 // This keeps us from using base/spinlock.h's implementation of SpinLock.
252 #define BASE_SPINLOCK_H_ 1
256 /* ----------------------------------- MMAP and other memory allocation */
258 #ifndef HAVE_MMAP /* not true for MSVC, but may be true for msys */
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 */
268 #if __STDC__ && !defined(__MINGW32__)
269 typedef _off_t off_t
;
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
);
283 inline int munmap(void *addr
, size_t length
) {
284 return VirtualFree(addr
, 0, MEM_RELEASE
) ? 0 : -1;
286 #endif /* HAVE_MMAP */
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
295 /* ----------------------------------- STRING ROUTINES */
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 (!)).
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
,
306 return vsnprintf_s(str
, size
, _TRUNCATE
, format
, ap
);
309 inline int perftools_vsnprintf(char *str
, size_t size
, const char *format
,
311 if (size
== 0) /* not even room for a \0? */
312 return -1; /* not what C99 says to do, but what windows does */
314 return _vsnprintf(str
, size
-1, format
, ap
);
318 #ifndef HAVE_SNPRINTF
319 inline int snprintf(char *str
, size_t size
, const char *format
, ...) {
322 va_start(ap
, format
);
323 r
= perftools_vsnprintf(str
, size
, format
, ap
);
329 #define PRIx64 "I64x"
330 #define SCNx64 "I64x"
331 #define PRId64 "I64d"
332 #define SCNd64 "I64d"
333 #define PRIu64 "I64u"
335 # define PRIuPTR "llu"
336 # define PRIxPTR "llx"
338 # define PRIuPTR "lu"
339 # define PRIxPTR "lx"
342 /* ----------------------------------- FILE IO */
345 #define PATH_MAX 1024
348 enum { STDIN_FILENO
= 0, STDOUT_FILENO
= 1, STDERR_FILENO
= 2 };
351 #define O_RDONLY _O_RDONLY
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
);
359 inline int open(const char *pathname
, int flags
, int mode
= 0) {
360 return _open(pathname
, flags
, mode
);
362 inline int close(int fd
) {
365 inline ssize_t
read(int fd
, void *buf
, size_t count
) {
366 return _read(fd
, buf
, count
);
368 inline ssize_t
write(int fd
, const void *buf
, size_t count
) {
369 return _write(fd
, buf
, count
);
371 inline off_t
lseek(int fd
, off_t offset
, int whence
) {
372 return _lseek(fd
, offset
, whence
);
374 inline char *getcwd(char *buf
, size_t size
) {
375 return _getcwd(buf
, size
);
377 inline int mkdir(const char *pathname
, int) {
378 return _mkdir(pathname
);
381 inline FILE *popen(const char *command
, const char *type
) {
382 return _popen(command
, type
);
384 inline int pclose(FILE *stream
) {
385 return _pclose(stream
);
389 EXTERN_C PERFTOOLS_DLL_DECL
void WriteToStderr(const char* buf
, int len
);
391 /* ----------------------------------- SYSTEM/PROCESS */
394 #if __STDC__ && !defined(__MINGW32__)
395 inline pid_t
getpid(void) { return _getpid(); }
397 inline pid_t
getppid(void) { return 0; }
399 /* Handle case when poll is used to simulate sleep. */
400 inline int poll(struct pollfd
* fds
, int nfds
, int timeout
) {
407 EXTERN_C
int getpagesize(); /* in port.cc */
409 /* ----------------------------------- OTHER */
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);
418 // mingw64 seems to define timespec (though mingw.org mingw doesn't),
419 // protected by the _TIMESPEC_DEFINED macro.
420 #ifndef _TIMESPEC_DEFINED
427 inline int nanosleep(const struct timespec
*req
, struct timespec
*rem
) {
428 Sleep(req
->tv_sec
* 1000 + req
->tv_nsec
/ 1000000);
433 inline long long int strtoll(const char *nptr
, char **endptr
, int base
) {
434 return _strtoi64(nptr
, endptr
, base
);
436 inline unsigned long long int strtoull(const char *nptr
, char **endptr
,
438 return _strtoui64(nptr
, endptr
, base
);
440 inline long long int strtoq(const char *nptr
, char **endptr
, int base
) {
441 return _strtoi64(nptr
, endptr
, base
);
443 inline unsigned long long int strtouq(const char *nptr
, char **endptr
,
445 return _strtoui64(nptr
, endptr
, base
);
447 inline long long atoll(const char *nptr
) {
448 return _atoi64(nptr
);
452 #define __THROW throw()
454 /* ----------------------------------- TCMALLOC-SPECIFIC */
456 /* tcmalloc.cc calls this so we can patch VirtualAlloc() et al. */
457 extern void PatchWindowsFunctions();
459 // ----------------------------------- BUILD-SPECIFIC
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.
466 #define GOOGLE_MAYBE_THREADS_H_ 1
474 #endif /* GOOGLE_BASE_WINDOWS_H_ */