Index: third_party/tcmalloc/chromium/src/windows/port.cc |
=================================================================== |
--- third_party/tcmalloc/chromium/src/windows/port.cc (revision 88335) |
+++ third_party/tcmalloc/chromium/src/windows/port.cc (working copy) |
@@ -35,6 +35,7 @@ |
# error You should only be including windows/port.cc in a windows environment! |
#endif |
+#define NOMINMAX // so std::max, below, compiles correctly |
#include <config.h> |
#include <string.h> // for strlen(), memset(), memcmp() |
#include <assert.h> |
@@ -43,29 +44,12 @@ |
#include "port.h" |
#include "base/logging.h" |
#include "base/spinlock.h" |
+#include "internal_logging.h" |
#include "system-alloc.h" |
// ----------------------------------------------------------------------- |
// Basic libraries |
-// These call the windows _vsnprintf, but always NUL-terminate. |
-int safe_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); |
-} |
- |
-#ifndef HAVE_SNPRINTF |
-int snprintf(char *str, size_t size, const char *format, ...) { |
- va_list ap; |
- va_start(ap, format); |
- const int r = vsnprintf(str, size, format, ap); |
- va_end(ap); |
- return r; |
-} |
-#endif |
- |
int getpagesize() { |
static int pagesize = 0; |
if (pagesize == 0) { |
@@ -82,9 +66,22 @@ |
return NULL; |
} |
+// We need to write to 'stderr' without having windows allocate memory. |
+// The safest way is via a low-level call like WriteConsoleA(). But |
+// even then we need to be sure to print in small bursts so as to not |
+// require memory allocation. |
+extern "C" PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len) { |
+ // Looks like windows allocates for writes of >80 bytes |
+ for (int i = 0; i < len; i += 80) { |
+ write(STDERR_FILENO, buf + i, std::min(80, len - i)); |
+ } |
+} |
+ |
+ |
// ----------------------------------------------------------------------- |
// Threads code |
+// Declared (not extern "C") in thread_cache.h |
bool CheckIfKernelSupportsTLS() { |
// TODO(csilvers): return true (all win's since win95, at least, support this) |
return false; |
@@ -105,10 +102,16 @@ |
// Force a reference to p_thread_callback_tcmalloc and p_process_term_tcmalloc |
// to prevent whole program optimization from discarding the variables. |
#ifdef _MSC_VER |
+#if defined(_M_IX86) |
#pragma comment(linker, "/INCLUDE:__tls_used") |
#pragma comment(linker, "/INCLUDE:_p_thread_callback_tcmalloc") |
#pragma comment(linker, "/INCLUDE:_p_process_term_tcmalloc") |
+#elif defined(_M_X64) |
+#pragma comment(linker, "/INCLUDE:_tls_used") |
+#pragma comment(linker, "/INCLUDE:p_thread_callback_tcmalloc") |
+#pragma comment(linker, "/INCLUDE:p_process_term_tcmalloc") |
#endif |
+#endif |
// When destr_fn eventually runs, it's supposed to take as its |
// argument the tls-value associated with key that pthread_key_create |
@@ -173,7 +176,7 @@ |
#endif // #ifdef _MSC_VER |
-pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)) { |
+extern "C" pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)) { |
// Semantics are: we create a new key, and then promise to call |
// destr_fn with TlsGetValue(key) when the thread is destroyed |
// (as long as TlsGetValue(key) is not NULL). |
@@ -187,10 +190,38 @@ |
return key; |
} |
+// NOTE: this is Win2K and later. For Win98 we could use a CRITICAL_SECTION... |
+extern "C" int perftools_pthread_once(pthread_once_t *once_control, |
+ void (*init_routine)(void)) { |
+ // Try for a fast path first. Note: this should be an acquire semantics read. |
+ // It is on x86 and x64, where Windows runs. |
+ if (*once_control != 1) { |
+ while (true) { |
+ switch (InterlockedCompareExchange(once_control, 2, 0)) { |
+ case 0: |
+ init_routine(); |
+ InterlockedExchange(once_control, 1); |
+ return 0; |
+ case 1: |
+ // The initializer has already been executed |
+ return 0; |
+ default: |
+ // The initializer is being processed by another thread |
+ SwitchToThread(); |
+ } |
+ } |
+ } |
+ return 0; |
+} |
+ |
// ----------------------------------------------------------------------- |
// These functions replace system-alloc.cc |
+// The current system allocator. Because we don't link with system-alloc.cc, |
+// we need to define our own. |
+SysAllocator* sys_alloc = NULL; |
+ |
// This is mostly like MmapSysAllocator::Alloc, except it does these weird |
// munmap's in the middle of the page, which is forbidden in windows. |
extern void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, |