summaryrefslogtreecommitdiffstats
path: root/base/win
diff options
context:
space:
mode:
authorjar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-22 22:07:41 +0000
committerjar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-22 22:07:41 +0000
commitf21ed6f5ea007d05256d4621ebe87c8a24a882ad (patch)
tree18e82f98912da7a97a25cb9cf5cc65658257d026 /base/win
parent6a460669aee6e389ba02851b147ec7d8e9df2658 (diff)
downloadchromium_src-f21ed6f5ea007d05256d4621ebe87c8a24a882ad.zip
chromium_src-f21ed6f5ea007d05256d4621ebe87c8a24a882ad.tar.gz
chromium_src-f21ed6f5ea007d05256d4621ebe87c8a24a882ad.tar.bz2
Provide windows notification of thread termination
[Relanding revert 114954 with fix to be compatible wit new re-linking strategy. Better care was needed in bracketing the callbacks that were used, to be sure the new linker left all items located together.] This code should only have much of an impact on the XP platform, where thread teardown notification are not currently made. Provide an automatic fallback scan of the linker list of notification callbacks via DllMain. This fallback is ONLY used if there are no notifications coming via the linker list. This allows all existing code to continue working as it does today, and provides thread teardown notification on XP even though we use the LoadLibrary call. It is a minimal change, suitable for pushing to other channels (beta? stable?). r=siggi bug=107974,103209 Review URL: http://codereview.chromium.org/9024015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@115622 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/win')
-rw-r--r--base/win/dllmain.cc115
1 files changed, 115 insertions, 0 deletions
diff --git a/base/win/dllmain.cc b/base/win/dllmain.cc
new file mode 100644
index 0000000..fad9519
--- /dev/null
+++ b/base/win/dllmain.cc
@@ -0,0 +1,115 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Windows doesn't support pthread_key_create's destr_function, and in fact
+// it's a bit tricky to get code to run when a thread exits. This is
+// cargo-cult magic from http://www.codeproject.com/threads/tls.asp.
+// We are trying to be compatible with both a LoadLibrary style invocation, as
+// well as static linking. This code only needs to be included if we use
+// LoadLibrary, but it hooks into the "standard" set of TLS callbacks that are
+// provided for static linking.
+
+// This code is deliberately written to match the style of calls seen in
+// base/threading/thread_local_storage_win.cc. Please keep the two in sync if
+// coding conventions are changed.
+
+// WARNING: Do *NOT* try to include this in the construction of the base
+// library, even though it potentially drives code in
+// base/threading/thread_local_storage_win.cc. If you do, some users will end
+// up getting duplicate definition of DllMain() in some of their later links.
+
+// 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_dllmain_typical_entry to prevent whole
+// program optimization from discarding the variables.
+
+#include <windows.h>
+
+#include "base/logging.h"
+
+// Indicate if another service is scanning the callbacks. When this becomes
+// set to true, then DllMain() will stop supporting the callback service. This
+// value is set to true the first time any of our callbacks are called, as that
+// shows that some other service is handling callbacks.
+static bool linker_notifications_are_active = false;
+
+// This will be our mostly no-op callback that we'll list. We won't
+// deliberately call it, and if it is called, that means we don't need to do any
+// of the callbacks anymore. We expect such a call to arrive via a
+// THREAD_ATTACH message, long before we'd have to perform our THREAD_DETACH
+// callbacks.
+static void NTAPI on_callback(PVOID h, DWORD reason, PVOID reserved);
+
+#ifdef _WIN64
+
+#pragma comment(linker, "/INCLUDE:_tls_used")
+#pragma comment(linker, "/INCLUDE:p_thread_callback_dllmain_typical_entry")
+
+#else // _WIN64
+
+#pragma comment(linker, "/INCLUDE:__tls_used")
+#pragma comment(linker, "/INCLUDE:_p_thread_callback_dllmain_typical_entry")
+
+#endif // _WIN64
+
+// Explicitly depend on tlssup.cc variable to bracket the list of TLS callbacks.
+extern "C" PIMAGE_TLS_CALLBACK __xl_a;
+extern "C" PIMAGE_TLS_CALLBACK __xl_z;
+
+// extern "C" suppresses C++ name mangling so we know the symbol names for the
+// linker /INCLUDE:symbol pragmas above.
+extern "C" {
+#ifdef _WIN64
+
+// .CRT section is merged with .rdata on x64 so it must be constant data.
+#pragma data_seg(push, old_seg)
+// Use a typical possible name in the .CRT$XL? list of segments.
+#pragma const_seg(".CRT$XLB")
+// When defining a const variable, it must have external linkage to be sure the
+// linker doesn't discard it.
+extern const PIMAGE_TLS_CALLBACK p_thread_callback_dllmain_typical_entry;
+const PIMAGE_TLS_CALLBACK p_thread_callback_dllmain_typical_entry = on_callback;
+#pragma data_seg(pop, old_seg)
+
+#else // _WIN64
+
+#pragma data_seg(push, old_seg)
+// Use a typical possible name in the .CRT$XL? list of segments.
+#pragma data_seg(".CRT$XLB")
+PIMAGE_TLS_CALLBACK p_thread_callback_dllmain_typical_entry = on_callback;
+#pragma data_seg(pop, old_seg)
+
+#endif // _WIN64
+} // extern "C"
+
+
+// Make DllMain call the listed callbacks. This way any third parties that are
+// linked in will also be called.
+BOOL WINAPI DllMain(PVOID h, DWORD reason, PVOID reserved) {
+ if (DLL_THREAD_DETACH != reason && DLL_PROCESS_DETACH != reason)
+ return true; // We won't service THREAD_ATTACH calls.
+
+ if (linker_notifications_are_active)
+ return true; // Some other service is doing this work.
+
+ for (PIMAGE_TLS_CALLBACK* it = &__xl_a; it < &__xl_z; ++it) {
+ if (*it == NULL || *it == on_callback)
+ continue; // Don't bother to call our own callback.
+ (*it)(h, reason, reserved);
+ }
+ return true;
+}
+
+static void NTAPI on_callback(PVOID h, DWORD reason, PVOID reserved) {
+ // Do nothing. We were just a place holder in the list used to test that we
+ // call all items.
+ // If we are called, it means that some other system is scanning the callbacks
+ // and we don't need to do so in DllMain().
+ linker_notifications_are_active = true;
+ // Note: If some other routine some how plays this same game... we could both
+ // decide not to do the scanning <sigh>, but this trick should suppress
+ // duplicate calls on Vista, where the runtime takes care of the callbacks,
+ // and allow us to do the callbacks on XP, where we are currently devoid of
+ // callbacks (due to an explicit LoadLibrary call).
+}