* [PATCH] autostatic.c
@ 2012-07-27 20:26 Daniel Richard G.
0 siblings, 0 replies; only message in thread
From: Daniel Richard G. @ 2012-07-27 20:26 UTC (permalink / raw)
To: pthreads-win32
[-- Attachment #1: Type: text/plain, Size: 1624 bytes --]
My next patch is an overhaul of autostatic.c that adds support for older
MSVC versions, fixes the no-init bug in small-static builds, and smooths
out a number of rough edges.
++ autostatic.c
* Move the #includes up to the top, in case PTW32_STATIC_LIB is defined in
a header file (and a later patch from me will need a symbol from
implement.h early on)
* Added a big fat comment documenting the pre/post-main() black magic and
the anchoring business
* The init/exit routines are supposed to return int, not void, and return
a value of 0 to indicate "no error" (see the "Addendum: int Instead of
void" section in the Codeguru article)
* I got rid of the attribute_section() macro (in favor of writing things
out longhand) because it's not enough to abstract away all the
differences between the various forms of declarations needed (for
example, #pragma is needed in some cases, and that can't be stuffed into
a macro (and __pragma() isn't supported by older MSVC versions))
* The way that MSVC pre/post-main() black magic is done changed in 8.0, so
the code now implements the "old" and "new" ways. I've tested that this
works for everything back to MSVC6.
* Added a bit at the end to avoid warnings when PTW32_STATIC_LIB is not
defined in non-inlined builds
++ implement.h
* This bit sticks a reference to autostatic.obj into every object file, so
that the linker won't optimize it away (for "small static" builds)
--Daniel
--
Daniel Richard G. || danielg@teragram.com || Software Developer
Teragram Linguistic Technologies (a division of SAS)
http://www.teragram.com/
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Patch against git master --]
[-- Type: text/x-diff; name="ptw32-autostatic.patch", Size: 3795 bytes --]
diff --git a/autostatic.c b/autostatic.c
index 092aff2..21c1748 100755
--- a/autostatic.c
+++ b/autostatic.c
@@ -34,36 +34,73 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
+#include "pthread.h"
+#include "implement.h"
+
#if defined(PTW32_STATIC_LIB)
#if defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER)
-#include "pthread.h"
-#include "implement.h"
+/* For an explanation of this code (at least the MSVC parts), refer to
+ *
+ * http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c6945/
+ * ("Running Code Before and After Main")
+ *
+ * Compatibility with MSVC8 was cribbed from Boost:
+ *
+ * http://svn.boost.org/svn/boost/trunk/libs/thread/src/win32/tss_pe.cpp
+ *
+ * In addition to that, because we are in a static library, and the linker
+ * can't tell that the constructor/destructor functions are actually
+ * needed, we need a way to prevent the linker from optimizing away this
+ * module. The pthread_win32_autostatic_anchor() hack below (and in
+ * implement.h) does the job in a portable manner.
+ */
-static void on_process_init(void)
+static int on_process_init(void)
{
pthread_win32_process_attach_np ();
+ return 0;
}
-static void on_process_exit(void)
+static int on_process_exit(void)
{
pthread_win32_thread_detach_np ();
pthread_win32_process_detach_np ();
+ return 0;
}
#if defined(__MINGW64__) || defined(__MINGW32__)
-# define attribute_section(a) __attribute__((section(a)))
+__attribute__((section(".ctors"), used)) static int (*gcc_ctor)(void) = on_process_init;
+__attribute__((section(".dtors"), used)) static int (*gcc_dtor)(void) = on_process_exit;
#elif defined(_MSC_VER)
-# define attribute_section(a) __pragma(section(a,long,read)); __declspec(allocate(a))
+# if _MSC_VER >= 1400 /* MSVC8 */
+# pragma section(".CRT$XCU", long, read)
+# pragma section(".CRT$XPU", long, read)
+__declspec(allocate(".CRT$XCU")) static int (*msc_ctor)(void) = on_process_init;
+__declspec(allocate(".CRT$XPU")) static int (*msc_dtor)(void) = on_process_exit;
+# else
+# pragma data_seg(".CRT$XCU")
+static int (*msc_ctor)(void) = on_process_init;
+# pragma data_seg(".CRT$XPU")
+static int (*msc_dtor)(void) = on_process_exit;
+# pragma data_seg() /* reset data segment */
+# endif
#endif
-attribute_section(".ctors") void *gcc_ctor = on_process_init;
-attribute_section(".dtors") void *gcc_dtor = on_process_exit;
-
-attribute_section(".CRT$XCU") void *msc_ctor = on_process_init;
-attribute_section(".CRT$XPU") void *msc_dtor = on_process_exit;
-
#endif /* defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER) */
+/* This dummy function exists solely to be referenced by other modules
+ * (specifically, in implement.h), so that the linker can't optimize away
+ * this module. Don't call it.
+ */
+void pthread_win32_autostatic_anchor(void) { abort(); }
+
#endif /* PTW32_STATIC_LIB */
+
+#if ! defined(PTW32_BUILD_INLINED)
+/*
+ * Avoid "translation unit is empty" warnings
+ */
+typedef int foo;
+#endif
diff --git a/implement.h b/implement.h
index 92f5740..7529ad2 100644
--- a/implement.h
+++ b/implement.h
@@ -109,6 +109,16 @@ typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam);
# if defined(_MSC_VER) && _MSC_VER < 1300
typedef long intptr_t;
# endif
+
+/*
+ * Don't allow the linker to optimize away autostatic.obj in static builds.
+ */
+#if defined(PTW32_STATIC_LIB)
+void pthread_win32_autostatic_anchor(void);
+# if defined(__MINGW64__) || defined(__MINGW32__)
+__attribute__((unused, used))
+# endif
+static void (*local_autostatic_anchor)(void) = pthread_win32_autostatic_anchor;
#endif
typedef enum
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2012-07-27 20:26 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-27 20:26 [PATCH] autostatic.c Daniel Richard G.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).