summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-23 01:48:08 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-23 01:48:08 +0000
commitce53c9e6d9b9211f853e0d6f426a12b0bab6a875 (patch)
treeb3442d07d630c501138f2dd159a74d9f85a7b0f5
parent12a601cb8b1fdbbb630ab86063f9e6f36125027c (diff)
downloadchromium_src-ce53c9e6d9b9211f853e0d6f426a12b0bab6a875.zip
chromium_src-ce53c9e6d9b9211f853e0d6f426a12b0bab6a875.tar.gz
chromium_src-ce53c9e6d9b9211f853e0d6f426a12b0bab6a875.tar.bz2
Use the /INCLUDE:symbol linker option pragmas to force
references to the magic variables we added to the data segment for TLS callbacks. The references prevent whole program optimization from optimizing away those variables. This requires three changes: 1) the variables cannot be declared as static. 2) the variables must be declared extern "C" to suppress C++ name mangling. 3) the variables cannot have the same name. R=jar,maruel BUG=40663 TEST=none Review URL: http://codereview.chromium.org/1752004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45405 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/thread_local_storage_win.cc30
-rw-r--r--third_party/tcmalloc/chromium/src/windows/port.cc21
2 files changed, 33 insertions, 18 deletions
diff --git a/base/thread_local_storage_win.cc b/base/thread_local_storage_win.cc
index 361167e..7f8ea27 100644
--- a/base/thread_local_storage_win.cc
+++ b/base/thread_local_storage_win.cc
@@ -129,23 +129,24 @@ void ThreadLocalStorage::ThreadExit() {
// This magic is from http://www.codeproject.com/threads/tls.asp
// and it works for VC++ 7.0 and later.
+// Force a reference to _tls_used to make the linker create the TLS directory
+// if it's not already there. (e.g. if __declspec(thread) is not used).
+// Force a reference to p_thread_callback_base to prevent whole program
+// optimization from discarding the variable.
#ifdef _WIN64
-// This makes the linker create the TLS directory if it's not already
-// there. (e.g. if __declspec(thread) is not used).
#pragma comment(linker, "/INCLUDE:_tls_used")
+#pragma comment(linker, "/INCLUDE:p_thread_callback_base")
#else // _WIN64
-// This makes the linker create the TLS directory if it's not already
-// there. (e.g. if __declspec(thread) is not used).
#pragma comment(linker, "/INCLUDE:__tls_used")
+#pragma comment(linker, "/INCLUDE:_p_thread_callback_base")
#endif // _WIN64
// Static callback function to call with each thread termination.
-void NTAPI OnThreadExit(PVOID module, DWORD reason, PVOID reserved)
-{
+void NTAPI OnThreadExit(PVOID module, DWORD reason, PVOID reserved) {
// On XP SP0 & SP1, the DLL_PROCESS_ATTACH is never seen. It is sent on SP2+
// and on W2K and W2K3. So don't assume it is sent.
if (DLL_THREAD_DETACH == reason || DLL_PROCESS_DETACH == reason)
@@ -162,15 +163,21 @@ void NTAPI OnThreadExit(PVOID module, DWORD reason, PVOID reserved)
// implicitly loaded.
//
// See VC\crt\src\tlssup.c for reference.
+
+// extern "C" suppresses C++ name mangling so we know the symbol name for the
+// linker /INCLUDE:symbol pragma above.
+extern "C" {
+// The linker must not discard p_thread_callback_base. (We force a reference
+// to this variable with a linker /INCLUDE:symbol pragma to ensure that.) If
+// this variable is discarded, the OnThreadExit function will never be called.
#ifdef _WIN64
// .CRT section is merged with .rdata on x64 so it must be constant data.
#pragma const_seg(".CRT$XLB")
// When defining a const variable, it must have external linkage to be sure the
-// linker doesn't discard it. If this value is discarded, the OnThreadExit
-// function will never be called.
-extern const PIMAGE_TLS_CALLBACK p_thread_callback;
-const PIMAGE_TLS_CALLBACK p_thread_callback = OnThreadExit;
+// linker doesn't discard it.
+extern const PIMAGE_TLS_CALLBACK p_thread_callback_base;
+const PIMAGE_TLS_CALLBACK p_thread_callback_base = OnThreadExit;
// Reset the default section.
#pragma const_seg()
@@ -178,9 +185,10 @@ const PIMAGE_TLS_CALLBACK p_thread_callback = OnThreadExit;
#else // _WIN64
#pragma data_seg(".CRT$XLB")
-PIMAGE_TLS_CALLBACK p_thread_callback = OnThreadExit;
+PIMAGE_TLS_CALLBACK p_thread_callback_base = OnThreadExit;
// Reset the default section.
#pragma data_seg()
#endif // _WIN64
+} // extern "C"
diff --git a/third_party/tcmalloc/chromium/src/windows/port.cc b/third_party/tcmalloc/chromium/src/windows/port.cc
index 574e926..eaa93b7 100644
--- a/third_party/tcmalloc/chromium/src/windows/port.cc
+++ b/third_party/tcmalloc/chromium/src/windows/port.cc
@@ -100,10 +100,14 @@ bool CheckIfKernelSupportsTLS() {
// binary (it also doesn't run if the thread is terminated via
// TerminateThread, which if we're lucky this routine does).
-// This makes the linker create the TLS directory if it's not already
-// there (that is, even if __declspec(thead) is not used).
+// Force a reference to _tls_used to make the linker create the TLS directory
+// if it's not already there (that is, even if __declspec(thread) is not used).
+// 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
#pragma comment(linker, "/INCLUDE:__tls_used")
+#pragma comment(linker, "/INCLUDE:_p_thread_callback_tcmalloc")
+#pragma comment(linker, "/INCLUDE:_p_process_term_tcmalloc")
#endif
// When destr_fn eventually runs, it's supposed to take as its
@@ -142,14 +146,18 @@ static void NTAPI on_tls_callback(HINSTANCE h, DWORD dwReason, PVOID pv) {
#ifdef _MSC_VER
+// extern "C" suppresses C++ name mangling so we know the symbol names for the
+// linker /INCLUDE:symbol pragmas above.
+extern "C" {
// This tells the linker to run these functions.
#pragma data_seg(push, old_seg)
#pragma data_seg(".CRT$XLB")
-static void (NTAPI *p_thread_callback)(HINSTANCE h, DWORD dwReason, PVOID pv)
- = on_tls_callback;
+void (NTAPI *p_thread_callback_tcmalloc)(
+ HINSTANCE h, DWORD dwReason, PVOID pv) = on_tls_callback;
#pragma data_seg(".CRT$XTU")
-static int (*p_process_term)(void) = on_process_term;
+int (*p_process_term_tcmalloc)(void) = on_process_term;
#pragma data_seg(pop, old_seg)
+} // extern "C"
#else // #ifdef _MSC_VER [probably msys/mingw]
@@ -241,8 +249,7 @@ void TCMalloc_SystemRelease(void* start, size_t length) {
}
}
-void TCMalloc_SystemCommit(void* start, size_t length)
-{
+void TCMalloc_SystemCommit(void* start, size_t length) {
if (VirtualAlloc(start, length, MEM_COMMIT, PAGE_READWRITE) == start)
return;