This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
(1/8) ix86-win32 threading patch
- To: gcc-patches at gcc dot gnu dot org
- Subject: (1/8) ix86-win32 threading patch
- From: Mumit Khan <khan at nanotech dot wisc dot edu>
- Date: Sun, 12 Dec 1999 00:00:11 -0600
Mingw32 runtime provides special support that fixes the memory leak
from eh contexts. This patch also fixes a few errors in my original
submission.
Maintains backward compatibility with older Mingw runtimes, which we
can take out later on.
Sat Dec 11 16:36:49 1999 Mumit Khan <khan@xraylith.wisc.edu>
* gthr-win32.h (__gthread_active_p): Support Mingw MT runtime.
(__gthread_key_create): Likewise.
(__gthread_key_dtor): Likewise.
(__gthread_once): Fix logic.
(__gthread_key_delete): Cast away constness.
* i386/cygwin.h (SUBTARGET_SWITCHES): Add -mthreads option.
* invoke.texi: Document.
* i386/mingw32.h (CPP_SPEC): Use.
(LIBGCC_SPEC): Likewise.
* i386/crtdll.h (LIBGCC_SPEC): Likewise.
Index: gthr-win32.h
===================================================================
RCS file: /homes/khan/src/CVSROOT/gcc-dev/gcc/gthr-win32.h,v
retrieving revision 1.1.1.1
diff -u -3 -p -r1.1.1.1 gthr-win32.h
--- gthr-win32.h 1999/12/11 03:13:47 1.1.1.1
+++ gthr-win32.h 1999/12/11 22:16:12
@@ -34,23 +34,41 @@ Boston, MA 02111-1307, USA. */
does not map well into pthread-inspired gcc's threading model, and so
there are caveats one needs to be aware of.
- 1. The destructor supplied to __gthread_key_create is ignored. This
- will certainly cause memory leaks due to unreclaimed eh contexts
- (sizeof (eh_context) is at least 24 bytes for x86 currently).
+ 1. The destructor supplied to __gthread_key_create is ignored for
+ generic x86-win32 ports. This will certainly cause memory leaks
+ due to unreclaimed eh contexts (sizeof (eh_context) is at least
+ 24 bytes for x86 currently).
This memory leak may be significant for long-running applications
that make heavy use of C++ EH.
+ However, Mingw runtime (version 0.3 or newer) provides a mechanism
+ to emulate pthreads key dtors; the runtime provides a special DLL,
+ linked in if -mthreads option is specified, that runs the dtors in
+ the reverse order of registration when each thread exits. If
+ -mthreads option is not given, a stub is linked in instead of the
+ DLL, which results in memory leak. Other x86-win32 ports can use
+ the same technique of course to avoid the leak.
+
2. The error codes returned are non-POSIX like, and cast into ints.
This may cause incorrect error return due to truncation values on
hw where sizeof (DWORD) > sizeof (int).
+
+ 3. We might consider using Critical Sections instead of Windows32
+ mutexes for better performance, but emulating __gthread_mutex_trylock
+ interface becomes more complicated (Win9x does not support
+ TryEnterCriticalSectioni, while NT does).
- The basic framework should work well enough. */
+ The basic framework should work well enough. In the long term, GCC
+ needs to use Structured Exception Handling on Windows32. */
#define __GTHREADS 1
#include <windows.h>
#include <errno.h>
+#ifdef __MINGW32__
+#include <_mingw.h>
+#endif
typedef DWORD __gthread_key_t;
@@ -64,10 +82,24 @@ typedef HANDLE __gthread_mutex_t;
#define __GTHREAD_ONCE_INIT {FALSE, -1}
#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
+#if __MINGW32_MAJOR_VERSION >= 1 || \
+ (__MINGW32_MAJOR_VERSION == 0 && __MINGW32_MINOR_VERSION > 2)
+#define MINGW32_SUPPORTS_MT_EH 1
+extern int __mingwthr_key_dtor PROTO((DWORD, void (*) (void *)));
+/* Mingw runtime >= v0.3 provides a magic variable that is set to non-zero
+ if -mthreads option was specified, or 0 otherwise. This is to get around
+ the lack of weak symbols in PE-COFF. */
+extern int _CRT_MT;
+#endif
+
static inline int
__gthread_active_p ()
{
+#ifdef MINGW32_SUPPORTS_MT_EH
+ return _CRT_MT;
+#else
return 1;
+#endif
}
static inline int
@@ -85,48 +117,52 @@ __gthread_once (__gthread_once_t *once,
(*func) ();
once->done = TRUE;
}
- }
- else
- {
- /* Another thread is currently executing the code, so wait for it to
- finish; yield the CPU in the meantime. */
- while (! once->done)
- Sleep (0);
+ else
+ {
+ /* Another thread is currently executing the code, so wait for it
+ to finish; yield the CPU in the meantime. If performance
+ does become an issue, the solution is to use an Event that
+ we wait on here (and set above), but that implies a place to
+ create the event before this routine is called. */
+ while (! once->done)
+ Sleep (0);
+ }
}
return 0;
}
-/* Windows32 thread local keys don't support destructors; to avoid leaks,
- we will have to figure something out in the future. */
+/* Windows32 thread local keys don't support destructors; this leads to
+ leaks, especially in threaded applications making extensive use of
+ C++ EH. Mingw uses a thread-support DLL to work-around this problem. */
static inline int
-__gthread_key_create (__gthread_key_t *key,
- void (*dtor) (void *) __attribute__((__unused__)))
+__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
{
int status = 0;
DWORD tls_index = TlsAlloc ();
if (tls_index != 0xFFFFFFFF)
- *key = tls_index;
+ {
+ *key = tls_index;
+#ifdef MINGW32_SUPPORTS_MT_EH
+ /* Mingw runtime will run the dtors in reverse order for each thread
+ when the thread exits. */
+ status = __mingwthr_key_dtor (*key, dtor);
+#endif
+ }
else
status = (int) GetLastError ();
return status;
}
-/* Currently, this routine is never called since win32 keys don't support
- destructors. Hopefully we'll find a way in the future. */
+/* Currently, this routine is called only for Mingw runtime, and if
+ -mthreads option is chosen to link in the thread support DLL. */
static inline int
__gthread_key_dtor (__gthread_key_t key, void *ptr)
{
- int status = 0;
-
- /* Just reset the key value to zero. */
- if (ptr)
- status = (TlsSetValue (key, 0) != 0) ? 0 : (int) GetLastError ();
- return status;
+ /* Nothing needed. */
+ return 0;
}
-/* Currently, this routine is never called since win32 keys don't support
- destructors. Hopefully we'll find a way in the future. */
static inline int
__gthread_key_delete (__gthread_key_t key)
{
@@ -142,7 +178,7 @@ __gthread_getspecific (__gthread_key_t k
static inline int
__gthread_setspecific (__gthread_key_t key, const void *ptr)
{
- return (TlsSetValue (key, ptr) != 0) ? 0 : (int) GetLastError ();
+ return (TlsSetValue (key, (void*) ptr) != 0) ? 0 : (int) GetLastError ();
}
static inline void
Index: invoke.texi
===================================================================
RCS file: /homes/khan/src/CVSROOT/gcc-dev/gcc/invoke.texi,v
retrieving revision 1.1.1.1
diff -u -3 -p -r1.1.1.1 invoke.texi
--- invoke.texi 1999/12/11 03:13:44 1.1.1.1
+++ invoke.texi 1999/12/11 22:31:21
@@ -360,6 +360,7 @@ in the following sections.
-mreg-alloc=@var{list} -mregparm=@var{num}
-malign-jumps=@var{num} -malign-loops=@var{num}
-malign-functions=@var{num} -mpreferred-stack-boundary=@var{num}
+-mthreads
@emph{HPPA Options}
-march=@var{architecture type}
@@ -5938,6 +5939,14 @@ This extra alignment does consume extra
to stack space usage, such as embedded systems and operating system kernels,
may want to reduce the preferred alignment to
@samp{-mpreferred-stack-boundary=2}.
+
+@item -mthreads
+@kindex -mthreads
+Support thread-safe exception handling on @samp{Mingw32}. Code that relies
+on thread-safe exception handling must compile and link all code with the
+@samp{-mthreads} option. When compiling, @samp{-mthreads} defines
+@samp{-D_MT}; when linking, it links in a special thread helper library
+@samp{-lmingwthrd} which cleans up per thread exception handling data.
@end table
@node HPPA Options
Index: config/i386/crtdll.h
===================================================================
RCS file: /homes/khan/src/CVSROOT/gcc-dev/gcc/config/i386/crtdll.h,v
retrieving revision 1.1.1.1
diff -u -3 -p -r1.1.1.1 crtdll.h
--- crtdll.h 1999/12/11 03:13:58 1.1.1.1
+++ crtdll.h 1999/12/11 22:33:46
@@ -32,7 +32,8 @@ Boston, MA 02111-1307, USA. */
-Asystem(winnt) -Acpu(i386) -Amachine(i386)"
#undef LIBGCC_SPEC
-#define LIBGCC_SPEC "-lmingw32 -lgcc -lmoldname -lcrtdll"
+#define LIBGCC_SPEC \
+ "%{mthreads:-lmingwthrd} -lmingw32 -lgcc -lmoldname -lcrtdll"
/* Specify a different entry point when linking a DLL */
#undef STARTFILE_SPEC
Index: config/i386/cygwin.h
===================================================================
RCS file: /homes/khan/src/CVSROOT/gcc-dev/gcc/config/i386/cygwin.h,v
retrieving revision 1.1.1.1
diff -u -3 -p -r1.1.1.1 cygwin.h
--- cygwin.h 1999/12/11 03:13:58 1.1.1.1
+++ cygwin.h 1999/12/11 22:31:21
@@ -51,7 +51,8 @@ Boston, MA 02111-1307, USA. */
{ "console", -MASK_WINDOWS, "Create console application" }, \
{ "dll", MASK_DLL, "Generate code for a DLL" }, \
{ "nop-fun-dllimport", MASK_NOP_FUN_DLLIMPORT, "Ignore dllimport for functions" }, \
-{ "no-nop-fun-dllimport", -MASK_NOP_FUN_DLLIMPORT, "" },
+{ "no-nop-fun-dllimport", -MASK_NOP_FUN_DLLIMPORT, "" }, \
+{ "threads", 0, "Use Mingw-specific thread support" },
/* Support the __declspec keyword by turning them into attributes.
Index: config/i386/mingw32.h
===================================================================
RCS file: /homes/khan/src/CVSROOT/gcc-dev/gcc/config/i386/mingw32.h,v
retrieving revision 1.1.1.1
diff -u -3 -p -r1.1.1.1 mingw32.h
--- mingw32.h 1999/12/11 03:13:58 1.1.1.1
+++ mingw32.h 1999/12/11 22:34:36
@@ -45,7 +45,8 @@ Boston, MA 02111-1307, USA. */
#define STANDARD_INCLUDE_COMPONENT "MINGW32"
#undef CPP_SPEC
-#define CPP_SPEC "-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE}"
+#define CPP_SPEC \
+ "-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT}"
/* For Windows applications, include more libraries, but always include
kernel32. */
@@ -55,7 +56,8 @@ Boston, MA 02111-1307, USA. */
/* Include in the mingw32 libraries with libgcc */
#undef LIBGCC_SPEC
-#define LIBGCC_SPEC "-lmingw32 -lgcc -lmoldname -lmsvcrt"
+#define LIBGCC_SPEC \
+ "%{mthreads:-lmingwthrd} -lmingw32 -lgcc -lmoldname -lmsvcrt"
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{mdll:dllcrt2%O%s} %{!mdll:crt2%O%s}"