public inbox for pthreads-win32@sourceware.org
 help / color / mirror / Atom feed
* Static Library Initialization (again?)
@ 2008-06-17 23:28 Brian Cole
  2008-06-18  1:25 ` Ross Johnson
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Brian Cole @ 2008-06-17 23:28 UTC (permalink / raw)
  To: pthreads-win32

It looks like I'm running into the same problem as others. I need to
distribute a static library with pthreads-win32 included without
requiring end-users of our library to call any pthreads-win32 specific
attach or detach code. Based on previous posts to the mailing list it
looks like the boost library has dealt with this before:
http://sourceware.org/ml/pthreads-win32/2008/msg00022.html

I also found this bit of code inside the Google performance tools:
#ifdef _MSC_VER

// 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;
#pragma data_seg(".CRT$XTU")
static int (*p_process_term)(void) = on_process_term;
#pragma data_seg(pop, old_seg)

#else  // #ifdef _MSC_VER  [probably msys/mingw]

// We have to try the DllMain solution here, because we can't use the
// msvc-specific pragmas.
<snipped for brevity>

#endif  // #ifdef _MSC_VER

Any reason pthreads-win32 can't use these same mechanisms to initialize itself?

Why can't DllMain be used for this? MSDN seems to imply that DllMain
is called for static libraries
(http://msdn.microsoft.com/en-us/library/ms682583.aspx):
"The lpReserved parameter indicates whether the DLL is being loaded
statically or dynamically."

I just looked through boost and found their implementation
(boost-trunk/libs/thread/src/win32/tss_pe.cpp). Any objection to me
creating a patch based on this code for pthreads-win32?

-Brian

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Static Library Initialization (again?)
  2008-06-17 23:28 Static Library Initialization (again?) Brian Cole
@ 2008-06-18  1:25 ` Ross Johnson
  2008-06-18 14:09 ` John E. Bossom
  2009-05-22  0:08 ` Ramiro Polla
  2 siblings, 0 replies; 6+ messages in thread
From: Ross Johnson @ 2008-06-18  1:25 UTC (permalink / raw)
  To: Brian Cole; +Cc: pthreads-win32

Brian Cole wrote:
> It looks like I'm running into the same problem as others. I need to
> distribute a static library with pthreads-win32 included without
> requiring end-users of our library to call any pthreads-win32 specific
> attach or detach code. Based on previous posts to the mailing list it
> looks like the boost library has dealt with this before:
> http://sourceware.org/ml/pthreads-win32/2008/msg00022.html
>
> I also found this bit of code inside the Google performance tools:
> #ifdef _MSC_VER
>
> // 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;
> #pragma data_seg(".CRT$XTU")
> static int (*p_process_term)(void) = on_process_term;
> #pragma data_seg(pop, old_seg)
>
> #else  // #ifdef _MSC_VER  [probably msys/mingw]
>
> // We have to try the DllMain solution here, because we can't use the
> // msvc-specific pragmas.
> <snipped for brevity>
>
> #endif  // #ifdef _MSC_VER
>
> Any reason pthreads-win32 can't use these same mechanisms to initialize itself?
>
> Why can't DllMain be used for this? MSDN seems to imply that DllMain
> is called for static libraries
> (http://msdn.microsoft.com/en-us/library/ms682583.aspx):
> "The lpReserved parameter indicates whether the DLL is being loaded
> statically or dynamically."
>
> I just looked through boost and found their implementation
> (boost-trunk/libs/thread/src/win32/tss_pe.cpp). Any objection to me
> creating a patch based on this code for pthreads-win32?
>   
A patch based on the Boost solution would be very welcome. It looks to 
me like both Google and Boost are using the same technique but the Boost 
version appears to include a version for Mingw32.

I'm not familiar with this enough to tell - does this solution work for 
dynamic loading as well, or just static? I ask because there are a 
couple of calls in DllMain that are forbidden according to the Microsoft 
doco, such as calling LoadLibrary, but work anyway.

> -Brian
>   

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Static Library Initialization (again?)
  2008-06-17 23:28 Static Library Initialization (again?) Brian Cole
  2008-06-18  1:25 ` Ross Johnson
@ 2008-06-18 14:09 ` John E. Bossom
  2009-05-22  0:08 ` Ramiro Polla
  2 siblings, 0 replies; 6+ messages in thread
From: John E. Bossom @ 2008-06-18 14:09 UTC (permalink / raw)
  To: pthreads-win32

Quoting Brian Cole <coleb2@gmail.com>:

> Why can't DllMain be used for this? MSDN seems to imply that DllMain
> is called for static libraries
> (http://msdn.microsoft.com/en-us/library/ms682583.aspx):
> "The lpReserved parameter indicates whether the DLL is being loaded
> statically or dynamically."

You can statically link against the implib of a DLL or dynamically load
the DLL at run time. Regardless a DLL is a DLL is a DLL. That is
what they mean in MSDN... DllMain only exists for DLLs not static libraries.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Static Library Initialization (again?)
  2008-06-17 23:28 Static Library Initialization (again?) Brian Cole
  2008-06-18  1:25 ` Ross Johnson
  2008-06-18 14:09 ` John E. Bossom
@ 2009-05-22  0:08 ` Ramiro Polla
  2009-05-22  2:36   ` John E. Bossom
  2009-06-07 23:39   ` Ramiro Polla
  2 siblings, 2 replies; 6+ messages in thread
From: Ramiro Polla @ 2009-05-22  0:08 UTC (permalink / raw)
  To: pthreads-win32

[-- Attachment #1: Type: text/plain, Size: 2153 bytes --]

Hi,

On Tue, Jun 17, 2008 at 8:27 PM, Brian Cole <coleb2@gmail.com> wrote:
> It looks like I'm running into the same problem as others. I need to
> distribute a static library with pthreads-win32 included without
> requiring end-users of our library to call any pthreads-win32 specific
> attach or detach code. Based on previous posts to the mailing list it
> looks like the boost library has dealt with this before:
> http://sourceware.org/ml/pthreads-win32/2008/msg00022.html
>
> I also found this bit of code inside the Google performance tools:
> #ifdef _MSC_VER
>
> // 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;
> #pragma data_seg(".CRT$XTU")
> static int (*p_process_term)(void) = on_process_term;
> #pragma data_seg(pop, old_seg)
>
> #else  // #ifdef _MSC_VER  [probably msys/mingw]
>
> // We have to try the DllMain solution here, because we can't use the
> // msvc-specific pragmas.
> <snipped for brevity>
>
> #endif  // #ifdef _MSC_VER
>
> Any reason pthreads-win32 can't use these same mechanisms to initialize itself?
>
> Why can't DllMain be used for this? MSDN seems to imply that DllMain
> is called for static libraries
> (http://msdn.microsoft.com/en-us/library/ms682583.aspx):
> "The lpReserved parameter indicates whether the DLL is being loaded
> statically or dynamically."
>
> I just looked through boost and found their implementation
> (boost-trunk/libs/thread/src/win32/tss_pe.cpp). Any objection to me
> creating a patch based on this code for pthreads-win32?

I attached an ugly but working patch for this. I haven't tested
building pthreads with MSVC but the initialization code worked on a
standalone test app.

I added a new make clean GC-autostatic to build the library.

make clean GC-static tests pass. I also tested a bit with FFmpeg (but
not extensively).

I'm sure it can be dramatically improved (comments, documentation,
stress test, etc), but as a start it's good enough.

Ramiro Polla

[-- Attachment #2: static_library_initialization.diff --]
[-- Type: application/octet-stream, Size: 5485 bytes --]

diff -ur pthreads.orig/GNUmakefile pthreads/GNUmakefile
--- pthreads.orig/GNUmakefile	Thu May 21 20:13:16 2009
+++ pthreads/GNUmakefile	Thu May 21 20:31:09 2009
@@ -455,6 +455,7 @@
 	@ echo "make clean GC-inlined    (to build the GNU C inlined dll with C cleanup code)"
 	@ echo "make clean GCE-inlined   (to build the GNU C inlined dll with C++ exception handling)"
 	@ echo "make clean GC-static     (to build the GNU C inlined static lib with C cleanup code)"
+	@ echo "make clean GC-autostatic (to build the GNU C inlined static lib with C cleanup code and automatic library initialization)"
 	@ echo "make clean GC-debug      (to build the GNU C debug dll with C cleanup code)"
 	@ echo "make clean GCE-debug     (to build the GNU C debug dll with C++ exception handling)"
 	@ echo "make clean GC-inlined-debug    (to build the GNU C inlined debug dll with C cleanup code)"
@@ -491,6 +492,9 @@
 
 GC-static:
 		$(MAKE) XOPT="-DPTW32_BUILD_INLINED -DPTW32_STATIC_LIB" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GC_STATIC_STAMP)
+
+GC-autostatic:
+		$(MAKE) XOPT="-DPTW32_BUILD_INLINED -DPTW32_AUTOSTATIC -DPTW32_STATIC_LIB" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" $(GC_STATIC_STAMP)
 
 GC-static-debug:
 		$(MAKE) XOPT="-DPTW32_BUILD_INLINED -DPTW32_STATIC_LIB" CLEANUP=-D__CLEANUP_C XC_FLAGS="$(GC_CFLAGS)" OBJ="$(DLL_INLINED_OBJS)" DLL_VER=$(DLL_VERD) OPT="$(DOPT)" $(GCD_STATIC_STAMP)
diff -ur pthreads.orig/autostatic.c pthreads/autostatic.c
--- pthreads.orig/autostatic.c	Thu May 21 20:55:22 2009
+++ pthreads/autostatic.c	Thu May 21 20:27:26 2009
@@ -0,0 +1,109 @@
+/*
+ * autostatic.c
+ *
+ * Description:
+ * This translation unit implements static library initialisation.
+ *
+ * --------------------------------------------------------------------------
+ *
+ *      Pthreads-win32 - POSIX Threads Library for Win32
+ *      Copyright(C) 1998 John E. Bossom
+ *      Copyright(C) 1999,2005 Pthreads-win32 contributors
+ * 
+ *      Contact Email: rpj@callisto.canberra.edu.au
+ * 
+ *      The current list of contributors is contained
+ *      in the file CONTRIBUTORS included with the source
+ *      code distribution. The list can also be seen at the
+ *      following World Wide Web location:
+ *      http://sources.redhat.com/pthreads-win32/contributors.html
+ * 
+ *      This library is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU Lesser General Public
+ *      License as published by the Free Software Foundation; either
+ *      version 2 of the License, or (at your option) any later version.
+ * 
+ *      This library is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *      Lesser General Public License for more details.
+ * 
+ *      You should have received a copy of the GNU Lesser General Public
+ *      License along with this library in the file COPYING.LIB;
+ *      if not, write to the Free Software Foundation, Inc.,
+ *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef PTW32_AUTOSTATIC
+
+#include "pthread.h"
+#include "implement.h"
+
+static void on_process_init(void)
+{
+    pthread_win32_process_attach_np ();
+}
+
+static void on_process_exit(void)
+{
+    pthread_win32_thread_detach_np  ();
+    pthread_win32_process_detach_np ();
+}
+
+static void NTAPI on_tls_callback(HINSTANCE h, DWORD dwReason, PVOID pv)
+{
+    switch (dwReason) {
+    case DLL_THREAD_ATTACH:
+        pthread_win32_thread_attach_np();
+        break;
+    case DLL_THREAD_DETACH:
+        pthread_win32_thread_detach_np();
+        break;
+    }
+}
+
+#if defined(__MINGW32__)
+ULONG __tls_index__ = 0;
+char __tls_end__   __attribute__((section(".tls$zzz"))) = 0;
+char __tls_start__ __attribute__((section(".tls")))     = 0;
+
+void *__crt_xla __attribute__ ((section(".CRT$XLA"))) = 0;
+void *__crt_xlb __attribute__ ((section(".CRT$XLB"))) = on_tls_callback;
+void *__crt_xlz __attribute__ ((section(".CRT$XLZ"))) = 0;
+
+const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata$T"))) =
+{
+        (DWORD) &__tls_start__,
+        (DWORD) &__tls_end__,
+        (DWORD) &__tls_index__,
+        (DWORD) (&__crt_xla+1),
+        (DWORD) 0,
+        (DWORD) 0
+};
+
+void *__ctors __attribute__((section(".ctors")))     = on_process_init;
+void *__dtors __attribute__((section(".dtors.zzz"))) = on_process_exit;
+
+#elif  defined(_MSC_VER)
+
+extern DWORD _tls_used;
+
+static int on_tls_prepare(void)
+{
+    DWORD volatile dw = _tls_used;
+
+    return 0;
+}
+
+#pragma section(".CRT$XLC",long,read)
+__declspec(allocate(".CRT$XLC")) void *__crt_xlc = on_tls_callback;
+#pragma section(".CRT$XIU",long,read)
+__declspec(allocate(".CRT$XIU")) void *__crt_xiu = on_tls_prepare;
+
+#pragma section(".CRT$XCU",long,read)
+__declspec(allocate(".CRT$XCU")) void *__crt_xcu = on_process_init;
+#pragma section(".CRT$XPU",long,read)
+__declspec(allocate(".CRT$XPU")) void *__crt_xtu = on_process_exit;
+#endif
+
+#endif /* PTW32_STATIC_LIB */
diff -ur pthreads.orig/pthread.c pthreads/pthread.c
--- pthreads.orig/pthread.c	Thu May 21 20:13:16 2009
+++ pthreads/pthread.c	Thu May 21 20:16:55 2009
@@ -49,6 +49,7 @@
 #include "condvar.c"
 #include "create.c"
 #include "dll.c"
+#include "autostatic.c"
 #include "errno.c"
 #include "exit.c"
 #include "fork.c"

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Static Library Initialization (again?)
  2009-05-22  0:08 ` Ramiro Polla
@ 2009-05-22  2:36   ` John E. Bossom
  2009-06-07 23:39   ` Ramiro Polla
  1 sibling, 0 replies; 6+ messages in thread
From: John E. Bossom @ 2009-05-22  2:36 UTC (permalink / raw)
  To: pthreads-win32

>> Why can't DllMain be used for this? MSDN seems to imply that DllMain
>> is called for static libraries
>> (http://msdn.microsoft.com/en-us/library/ms682583.aspx):
>> "The lpReserved parameter indicates whether the DLL is being loaded
>> statically or dynamically."

There are two ways you can use a "dynamic library" (i.e. DLL)...
Statically link against it's implib and let the loader load it's DLL,
or programmatically by name.
This has nothing to do with an actual "static library" which is what this
topic is about.

Second, please beware that simply taking solutions from other open  
source components has the potential to taint the intellectual property  
rights of this open source component. open source doesn't mean free to  
copy... both Google and Boost are released under license and use of  
their code is subject to their respective license terms.
pthreads-win32 had chosen to release under the LGPL in order to permit  
use by commercial software in addition to open source projects.  
However, commercial companies can come under fire for using open  
source components with questionable lineage. Some commercial companies  
will not touch an open source component if the maintainer does not  
maintain a list of all contributors and can prove the code base is not  
tainted.

Respectfully,

John E. Bossom



Quoting Ramiro Polla <ramiro.polla@gmail.com>:

> Hi,
>
> On Tue, Jun 17, 2008 at 8:27 PM, Brian Cole <coleb2@gmail.com> wrote:
>> It looks like I'm running into the same problem as others. I need to
>> distribute a static library with pthreads-win32 included without
>> requiring end-users of our library to call any pthreads-win32 specific
>> attach or detach code. Based on previous posts to the mailing list it
>> looks like the boost library has dealt with this before:
>> http://sourceware.org/ml/pthreads-win32/2008/msg00022.html
>>
>> I also found this bit of code inside the Google performance tools:
>> #ifdef _MSC_VER
>>
>> // 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;
>> #pragma data_seg(".CRT$XTU")
>> static int (*p_process_term)(void) = on_process_term;
>> #pragma data_seg(pop, old_seg)
>>
>> #else  // #ifdef _MSC_VER  [probably msys/mingw]
>>
>> // We have to try the DllMain solution here, because we can't use the
>> // msvc-specific pragmas.
>> <snipped for brevity>
>>
>> #endif  // #ifdef _MSC_VER
>>
>> Any reason pthreads-win32 can't use these same mechanisms to   
>> initialize itself?
>>
>> Why can't DllMain be used for this? MSDN seems to imply that DllMain
>> is called for static libraries
>> (http://msdn.microsoft.com/en-us/library/ms682583.aspx):
>> "The lpReserved parameter indicates whether the DLL is being loaded
>> statically or dynamically."
>>
>> I just looked through boost and found their implementation
>> (boost-trunk/libs/thread/src/win32/tss_pe.cpp). Any objection to me
>> creating a patch based on this code for pthreads-win32?
>
> I attached an ugly but working patch for this. I haven't tested
> building pthreads with MSVC but the initialization code worked on a
> standalone test app.
>
> I added a new make clean GC-autostatic to build the library.
>
> make clean GC-static tests pass. I also tested a bit with FFmpeg (but
> not extensively).
>
> I'm sure it can be dramatically improved (comments, documentation,
> stress test, etc), but as a start it's good enough.
>
> Ramiro Polla
>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Static Library Initialization (again?)
  2009-05-22  0:08 ` Ramiro Polla
  2009-05-22  2:36   ` John E. Bossom
@ 2009-06-07 23:39   ` Ramiro Polla
  1 sibling, 0 replies; 6+ messages in thread
From: Ramiro Polla @ 2009-06-07 23:39 UTC (permalink / raw)
  To: pthreads-win32

Hi,

On Thu, May 21, 2009 at 9:08 PM, Ramiro Polla<ramiro.polla@gmail.com> wrote:
> On Tue, Jun 17, 2008 at 8:27 PM, Brian Cole <coleb2@gmail.com> wrote:
>> It looks like I'm running into the same problem as others. I need to
>> distribute a static library with pthreads-win32 included without
>> requiring end-users of our library to call any pthreads-win32 specific
>> attach or detach code. Based on previous posts to the mailing list it
>> looks like the boost library has dealt with this before:
>> http://sourceware.org/ml/pthreads-win32/2008/msg00022.html
>>
>> I also found this bit of code inside the Google performance tools:
>> #ifdef _MSC_VER
>>
>> // 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;
>> #pragma data_seg(".CRT$XTU")
>> static int (*p_process_term)(void) = on_process_term;
>> #pragma data_seg(pop, old_seg)
>>
>> #else  // #ifdef _MSC_VER  [probably msys/mingw]
>>
>> // We have to try the DllMain solution here, because we can't use the
>> // msvc-specific pragmas.
>> <snipped for brevity>
>>
>> #endif  // #ifdef _MSC_VER
>>
>> Any reason pthreads-win32 can't use these same mechanisms to initialize itself?
>>
>> Why can't DllMain be used for this? MSDN seems to imply that DllMain
>> is called for static libraries
>> (http://msdn.microsoft.com/en-us/library/ms682583.aspx):
>> "The lpReserved parameter indicates whether the DLL is being loaded
>> statically or dynamically."
>>
>> I just looked through boost and found their implementation
>> (boost-trunk/libs/thread/src/win32/tss_pe.cpp). Any objection to me
>> creating a patch based on this code for pthreads-win32?
>
> I attached an ugly but working patch for this. I haven't tested
> building pthreads with MSVC but the initialization code worked on a
> standalone test app.
>
> I added a new make clean GC-autostatic to build the library.
>
> make clean GC-static tests pass. I also tested a bit with FFmpeg (but
> not extensively).
>
> I'm sure it can be dramatically improved (comments, documentation,
> stress test, etc), but as a start it's good enough.

For some reason I didn't get John E. Bossom's reply in my inbox, so
I'm quoting it here:

> Second, please beware that simply taking solutions from other open
> source components has the potential to taint the intellectual property
> rights of this open source component. open source doesn't mean free to
> copy... both Google and Boost are released under license and use of
> their code is subject to their respective license terms.
> pthreads-win32 had chosen to release under the LGPL in order to permit
> use by commercial software in addition to open source projects.
> However, commercial companies can come under fire for using open
> source components with questionable lineage. Some commercial companies
> will not touch an open source component if the maintainer does not
> maintain a list of all contributors and can prove the code base is not
> tainted.

I used boost as a reference:
https://svn.boost.org/trac/boost/browser/trunk/libs/thread/src/win32/tss_pe.cpp

The header reads:
// (C) Copyright Aaron W. LaFramboise, Roland Schwarz, Michael Glassford 2004.
// (C) Copyright 2007 Roland Schwarz
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2007 David Deakins
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

The FSF affirms the boost license is GPL compatible, and from my
interpretation of the boost license, it is also LGPL compatible.

Whatever code is mine in that patch I license it as wtfpl <
http://sam.zoy.org/wtfpl/ >.

Ramiro Polla

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2009-06-07 23:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-06-17 23:28 Static Library Initialization (again?) Brian Cole
2008-06-18  1:25 ` Ross Johnson
2008-06-18 14:09 ` John E. Bossom
2009-05-22  0:08 ` Ramiro Polla
2009-05-22  2:36   ` John E. Bossom
2009-06-07 23:39   ` Ramiro Polla

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).