summaryrefslogtreecommitdiff
path: root/src/windows/port.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/windows/port.h')
-rw-r--r--src/windows/port.h352
1 files changed, 239 insertions, 113 deletions
diff --git a/src/windows/port.h b/src/windows/port.h
index ff6b714..0faba01 100644
--- a/src/windows/port.h
+++ b/src/windows/port.h
@@ -40,8 +40,8 @@
#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).
+/* 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"
@@ -54,21 +54,45 @@
#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 */
-
-// 4018: signed/unsigned mismatch is common (and ok for signed_i < unsigned_i)
-// 4244: otherwise we get problems when substracting 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()
+#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 substracting 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()
+ */
#ifdef _MSC_VER
#pragma warning(disable:4018 4244 4288 4267 4290 4996)
#endif
-// ----------------------------------- BASIC TYPES
+#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 */
@@ -83,53 +107,78 @@ 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
+#endif /* #ifndef HAVE_STDINT_H */
-// I guess MSVC's <types.h> doesn't include ssize_t by default?
+/* I guess MSVC's <types.h> doesn't include ssize_t by default? */
#ifdef _MSC_VER
typedef intptr_t ssize_t;
#endif
-// ----------------------------------- THREADS
+/* ----------------------------------- THREADS */
-#ifndef HAVE_PTHREAD // not true for MSVC, but may be true for MSYS
+#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
-#define pthread_self GetCurrentThreadId
-#define pthread_equal(pthread_t_1, pthread_t_2) ((pthread_t_1)==(pthread_t_2))
+enum { PTHREAD_ONCE_INIT = 0 }; /* important that this be 0! for SpinLock */
+
+inline pthread_t pthread_self(void) {
+ return GetCurrentThreadId();
+}
#ifdef __cplusplus
-// This replaces maybe_threads.{h,cc}
-extern pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)); // in port.cc
-#define perftools_pthread_key_create(pkey, destr_fn) \
- *(pkey) = PthreadKeyCreate(destr_fn)
+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;
}
-#define perftools_pthread_setspecific(key, val) \
- TlsSetValue((key), (val))
-// NOTE: this is Win2K and later. For Win98 we could use a CRITICAL_SECTION...
-#define perftools_pthread_once(once, init) do { \
- if (InterlockedCompareExchange(once, 1, 0) == 0) (init)(); \
-} while (0)
-#endif // __cplusplus
-#endif // HAVE_PTHREAD
-
-// __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.
+
+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 */
+
+/*
+ * __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.
+/*
+ * 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,
@@ -197,51 +246,80 @@ class SpinLockHolder { // Acquires a spinlock for as long as the scope lasts
// This keeps us from using base/spinlock.h's implementation of SpinLock.
#define BASE_SPINLOCK_H_ 1
-#endif // #if 0
-
-// This replaces testutil.{h,cc}
-extern PERFTOOLS_DLL_DECL void RunInThread(void (*fn)());
-extern PERFTOOLS_DLL_DECL void RunManyInThread(void (*fn)(), int count);
-extern PERFTOOLS_DLL_DECL void RunManyInThreadWithId(void (*fn)(int), int count,
- int stacksize);
+#endif /* #if 0 */
+/* ----------------------------------- MMAP and other memory allocation */
-// ----------------------------------- MMAP and other memory allocation
-
-#ifndef HAVE_MMAP // not true for MSVC, but may be true for msys
+#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 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
+#define MAP_SHARED MEM_RESERVE /* value of this #define is 100% arbitrary */
-// VirtualAlloc is only a replacement for mmap when certain invariants are kept
-#define mmap(start, length, prot, flags, fd, offset) \
- ( (start) == NULL && (fd) == -1 && (offset) == 0 && \
- (prot) == (PROT_READ|PROT_WRITE) && (flags) == (MAP_PRIVATE|MAP_ANONYMOUS)\
- ? VirtualAlloc(0, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) \
- : NULL )
+#if __STDC__
+typedef _off_t off_t;
+#endif
-#define munmap(start, length) (VirtualFree(start, 0, MEM_RELEASE) ? 0 : -1)
-#endif // HAVE_MMAP
+/* 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;
+ }
+}
-// We could maybe use VirtualAlloc for sbrk as well, but no need
-#define sbrk(increment) ( (void*)-1 ) // sbrk returns -1 on failure
+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 (!)).
-extern PERFTOOLS_DLL_DECL int snprintf(char *str, size_t size,
- const char *format, ...);
-extern PERFTOOLS_DLL_DECL int safe_vsnprintf(char *str, size_t size,
- const char *format, va_list ap);
-#define vsnprintf(str, size, format, ap) safe_vsnprintf(str, size, format, ap)
+/* ----------------------------------- 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"
@@ -256,84 +334,132 @@ extern PERFTOOLS_DLL_DECL int safe_vsnprintf(char *str, size_t size,
# define PRIxPTR "lx"
#endif
-// ----------------------------------- FILE IO
+/* ----------------------------------- FILE IO */
+
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#ifndef __MINGW32__
enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
#endif
-#define getcwd _getcwd
-#define access _access
-#define open _open
-#define read _read
-#define write _write
-#define lseek _lseek
-#define close _close
-#define popen _popen
-#define pclose _pclose
-#define mkdir(dirname, mode) _mkdir(dirname)
#ifndef O_RDONLY
#define O_RDONLY _O_RDONLY
#endif
-#ifdef __cplusplus
-extern "C"
+#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);
+}
#endif
-PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len);
-// ----------------------------------- SYSTEM/PROCESS
-typedef int pid_t;
-#define getpid _getpid
-#define getppid() (0)
+inline FILE *popen(const char *command, const char *type) {
+ return _popen(command, type);
+}
+inline int pclose(FILE *stream) {
+ return _pclose(stream);
+}
+
+EXTERN_C PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len);
+
+/* ----------------------------------- SYSTEM/PROCESS */
-// Handle case when poll is used to simulate sleep.
-#define poll(r, w, t) \
- do { \
- assert(r == 0); \
- assert(w == 0); \
- Sleep(t); \
- } while(0)
+typedef int pid_t;
+#if __STDC__
+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 PERFTOOLS_DLL_DECL int getpagesize(); // in port.cc
+EXTERN_C int getpagesize(); /* in port.cc */
-// ----------------------------------- OTHER
+/* ----------------------------------- OTHER */
-#define srandom srand
-#define random rand
-#define sleep(t) Sleep(t * 1000)
+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;
+}
struct timespec {
int tv_sec;
int tv_nsec;
};
-#define nanosleep(tm_ptr, ignored) \
- Sleep((tm_ptr)->tv_sec * 1000 + (tm_ptr)->tv_nsec / 1000000)
+inline int nanosleep(const struct timespec *req, struct timespec *rem) {
+ Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000);
+ return 0;
+}
#ifndef __MINGW32__
-#define strtoq _strtoi64
-#define strtouq _strtoui64
-#define strtoll _strtoi64
-#define strtoull _strtoui64
-#define atoll _atoi64
+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-SPECIFIC */
-// tcmalloc.cc calls this so we can patch VirtualAlloc() et al.
-extern PERFTOOLS_DLL_DECL void PatchWindowsFunctions();
+/* 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.
+/*
+ * 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_ */