15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Copyright (c) 2007, Google Inc. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modification, are permitted provided that the following conditions are 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * met: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Redistributions in binary form must reproduce the above 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the documentation and/or other materials provided with the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distribution. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * --- 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Author: Craig Silverstein 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef _WIN32 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# error You should only be including windows/port.cc in a windows environment! 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NOMINMAX // so std::max, below, compiles correctly 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <config.h> 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> // for strlen(), memset(), memcmp() 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h> 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdarg.h> // for va_list, va_start, va_end 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "port.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/spinlock.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "internal_logging.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "system-alloc.h" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------- 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Basic libraries 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int getpagesize() { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int pagesize = 0; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pagesize == 0) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SYSTEM_INFO system_info; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSystemInfo(&system_info); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pagesize = std::max(system_info.dwPageSize, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_info.dwAllocationGranularity); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pagesize; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL void* __sbrk(ptrdiff_t increment) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(FATAL, "Windows doesn't implement sbrk!\n"); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We need to write to 'stderr' without having windows allocate memory. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The safest way is via a low-level call like WriteConsoleA(). But 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// even then we need to be sure to print in small bursts so as to not 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// require memory allocation. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL void WriteToStderr(const char* buf, int len) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Looks like windows allocates for writes of >80 bytes 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < len; i += 80) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) write(STDERR_FILENO, buf + i, std::min(80, len - i)); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------- 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Threads code 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Declared (not extern "C") in thread_cache.h 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CheckIfKernelSupportsTLS() { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(csilvers): return true (all win's since win95, at least, support this) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows doesn't support pthread_key_create's destr_function, and in 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fact it's a bit tricky to get code to run when a thread exits. This 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is cargo-cult magic from http://www.codeproject.com/threads/tls.asp. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This code is for VC++ 7.1 and later; VC++ 6.0 support is possible 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but more busy-work -- see the webpage for how to do it. If all 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this fails, we could use DllMain instead. The big problem with 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DllMain is it doesn't run if this code is statically linked into a 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// binary (it also doesn't run if the thread is terminated via 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TerminateThread, which if we're lucky this routine does). 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Force a reference to _tls_used to make the linker create the TLS directory 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if it's not already there (that is, even if __declspec(thread) is not used). 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Force a reference to p_thread_callback_tcmalloc and p_process_term_tcmalloc 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to prevent whole program optimization from discarding the variables. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _MSC_VER 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_M_IX86) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(linker, "/INCLUDE:__tls_used") 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(linker, "/INCLUDE:_p_thread_callback_tcmalloc") 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(linker, "/INCLUDE:_p_process_term_tcmalloc") 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(_M_X64) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(linker, "/INCLUDE:_tls_used") 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(linker, "/INCLUDE:p_thread_callback_tcmalloc") 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(linker, "/INCLUDE:p_process_term_tcmalloc") 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When destr_fn eventually runs, it's supposed to take as its 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// argument the tls-value associated with key that pthread_key_create 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// creates. (Yeah, it sounds confusing but it's really not.) We 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// store the destr_fn/key pair in this data structure. Because we 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// store this in a single var, this implies we can only have one 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// destr_fn in a program! That's enough in practice. If asserts 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// trigger because we end up needing more, we'll have to turn this 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// into an array. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DestrFnClosure { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*destr_fn)(void*); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_key_t key_for_destr_fn_arg; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static DestrFnClosure destr_fn_info; // initted to all NULL/0. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int on_process_term(void) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (destr_fn_info.destr_fn) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *ptr = TlsGetValue(destr_fn_info.key_for_destr_fn_arg); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This shouldn't be necessary, but in Release mode, Windows 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sometimes trashes the pointer in the TLS slot, so we need to 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // remove the pointer from the TLS slot before the thread dies. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TlsSetValue(destr_fn_info.key_for_destr_fn_arg, NULL); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ptr) // pthread semantics say not to call if ptr is NULL 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*destr_fn_info.destr_fn)(ptr); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void NTAPI on_tls_callback(HINSTANCE h, DWORD dwReason, PVOID pv) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dwReason == DLL_THREAD_DETACH) { // thread is being destroyed! 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) on_process_term(); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _MSC_VER 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// extern "C" suppresses C++ name mangling so we know the symbol names 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for the linker /INCLUDE:symbol pragmas above. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This tells the linker to run these functions. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma data_seg(push, old_seg) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma data_seg(".CRT$XLB") 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void (NTAPI *p_thread_callback_tcmalloc)( 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HINSTANCE h, DWORD dwReason, PVOID pv) = on_tls_callback; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma data_seg(".CRT$XTU") 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int (*p_process_term_tcmalloc)(void) = on_process_term; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma data_seg(pop, old_seg) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // extern "C" 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else // #ifdef _MSC_VER [probably msys/mingw] 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We have to try the DllMain solution here, because we can't use the 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// msvc-specific pragmas. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI DllMain(HINSTANCE h, DWORD dwReason, PVOID pv) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dwReason == DLL_THREAD_DETACH) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) on_tls_callback(h, dwReason, pv); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (dwReason == DLL_PROCESS_DETACH) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) on_process_term(); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // #ifdef _MSC_VER 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Semantics are: we create a new key, and then promise to call 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // destr_fn with TlsGetValue(key) when the thread is destroyed 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (as long as TlsGetValue(key) is not NULL). 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pthread_key_t key = TlsAlloc(); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (destr_fn) { // register it 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this assert fails, we'll need to support an array of destr_fn_infos 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(destr_fn_info.destr_fn == NULL); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) destr_fn_info.destr_fn = destr_fn; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) destr_fn_info.key_for_destr_fn_arg = key; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return key; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: this is Win2K and later. For Win98 we could use a CRITICAL_SECTION... 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" int perftools_pthread_once(pthread_once_t *once_control, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*init_routine)(void)) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try for a fast path first. Note: this should be an acquire semantics read. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It is on x86 and x64, where Windows runs. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*once_control != 1) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (InterlockedCompareExchange(once_control, 2, 0)) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 0: 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) init_routine(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InterlockedExchange(once_control, 1); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 1: 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The initializer has already been executed 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The initializer is being processed by another thread 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SwitchToThread(); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------- 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These functions replace system-alloc.cc 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is mostly like MmapSysAllocator::Alloc, except it does these weird 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// munmap's in the middle of the page, which is forbidden in windows. 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t alignment) { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Align on the pagesize boundary 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int pagesize = getpagesize(); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alignment < pagesize) alignment = pagesize; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size = ((size + alignment - 1) / alignment) * alignment; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Safest is to make actual_size same as input-size. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (actual_size) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *actual_size = size; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ask for extra memory if alignment > pagesize 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t extra = 0; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alignment > pagesize) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extra = alignment - pagesize; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* result = VirtualAlloc(0, size + extra, 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == NULL) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adjust the return memory so it is aligned 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t ptr = reinterpret_cast<uintptr_t>(result); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t adjust = 0; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((ptr & (alignment - 1)) != 0) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) adjust = alignment - (ptr & (alignment - 1)); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr += adjust; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<void*>(ptr); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TCMalloc_SystemRelease(void* start, size_t length) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(csilvers): should I be calling VirtualFree here? 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RegisterSystemAllocator(SysAllocator *allocator, int priority) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // we don't allow registration on windows, right now 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DumpSystemAllocatorStats(TCMalloc_Printer* printer) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't dump stats on windows, right now 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The current system allocator 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SysAllocator* sys_alloc = NULL; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------- 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These functions rework existing functions of the same name in the 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Google codebase. 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A replacement for HeapProfiler::CleanupOldProfiles. 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeleteMatchingFiles(const char* prefix, const char* full_glob) { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WIN32_FIND_DATAA found; // that final A is for Ansi (as opposed to Unicode) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE hFind = FindFirstFileA(full_glob, &found); // A is for Ansi 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hFind != INVALID_HANDLE_VALUE) { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int prefix_length = strlen(prefix); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *fname = found.cFileName; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((strlen(fname) >= prefix_length) && 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (memcmp(fname, prefix, prefix_length) == 0)) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(0, "Removing old heap profile %s\n", fname); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(csilvers): we really need to unlink dirname + fname 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _unlink(fname); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (FindNextFileA(hFind, &found) != FALSE); // A is for Ansi 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FindClose(hFind); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 295