Chromium Code Reviews| Index: third_party/tcmalloc/chromium/src/windows/port.cc |
| =================================================================== |
| --- third_party/tcmalloc/chromium/src/windows/port.cc (revision 87277) |
| +++ 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,37 @@ |
| 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. |
|
antonm
2011/06/02 13:37:35
may you elaborate why? e.g. does it require pthre
Alexander Potapenko
2011/06/09 09:35:24
The latter one, http://code.google.com/p/google-pe
|
| + 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 |
| +SysAllocator* sys_alloc = NULL; |
|
Alexander Potapenko
2011/06/09 09:35:24
These lines differ from the upstream version: we n
antonm
2011/06/14 14:15:35
Please, add a comment and consider backporting thi
Alexander Potapenko
2011/06/15 16:32:20
For some strange reason the trunk perftools do not
Alexander Potapenko
2011/06/16 14:49:47
Done.
I've also put system-alloc.cc back to the li
|
| + |
| // 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, |