public inbox for pthreads-win32@sourceware.org
 help / color / mirror / Atom feed
* [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).