This is the mail archive of the pthreads-win32@sources.redhat.com mailing list for the pthreas-win32 project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[mingw/cygwin]: gthr-win32.h: remove pollution of STL namespace by win32api


The inline functions in gthr-win32.h pollute the STL namespace with
names from the win32 API.  This has raised several bug reports on the
mingw user list. Introducing win32api names into the namespace is
especially bad for code which makes no other use of the win32 api.

The following patch allows users to hide the win32api by calling 
functions defined in an extern file.  The patch puts the file in
libgcc.a, using the LIB2FUNCS_EXTRA machinery.

I have named the new function by simply replacing the __gthread prefix
with __gthr_win32.

I realize that this patch creates a  backward compatability issue:
libs built with new GCC would contain references to functions that
are not available in libgcc.a in  GCC 3.0  or 3.1.  However, the
new functions are referenced only if the user defines
__GTHREAD_HIDE_WIN32API, so the default behaviour is to _not_
introduce new dependencies.

I have another patch that I will submit independently to provide Dwarf2
EH for mingw.  This will break backwards compatability even more, since
3.0.x and 3.1 releases only worked on mingw with sjlj exceptions. So
if that patch is acceptable, the backwards compatability issue introduced
here may be moot. 

Chris, I have put the LIB2FUNCS_EXTRA definition in t-cygwin, because
the default thread model for cygwin is still win32.  It could just as
well go into t-mingw32 if cygwin changes to pthread model as default.


This has been bootstrapped and tested on:

Reading specs from D:/MINGW/BIN/../lib/gcc-lib/mingw32/3.2/specs
Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as
--host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls
--enable-languages=c,c++,f77,objc --disable-win32-registry --disable-shared
Thread model: win32
gcc version 3.2 20020526 (experimental)

I have also tested on 3.1 branch on mingw32 by rebuilding libgcc.a and
libstdc++.a

ChangeLog

2002-05-28  Danny Smith  <dannysmith@users.sourforge.net>

	* gthr-win32.h: Wrap all functions in extern "C".
	(__gthread_key_t): Typedef as unsigned long,
	not win32 DWORD.
	(__GTHREAD_ONCE_INIT): Use 0, not win32 FALSE.
	(__gthread_mutex_t): Typedef as void*, not win32 HANDLE.
	(__gthr_win32_once, __gthr_win32_key_create,
	__gthr_win32_key_delete, __gthr_win32_getspecific,
	__gthr_win32_setspecific, __gthr_win32_mutex_init_function,
	__gthr_win32_mutex_lock,__gthr_win32_mutex_trylock,
	__gthr_win32_mutex_unlock): Declare, if #defined
	__GTHREAD_HIDE_WIN32API.
	(__gthread_once,__gthread_key_create,
	__gthread_key_delete, __gthread_getspecific,
	__gthread_setspecific, __gthread_mutex_init_function,
	__gthread_mutex_lock,__gthread_mutex_trylock,
	__gthread_mutex_unlock): Call corresponding
	__gthr_win32_* extern implementations if #defined
	__GTHREAD_HIDE_WIN32API.
	* config/i386/t-cygwin (LIB2FUNCS_EXTRA): Set to
	$(srcdir)/config/i386/gthr-win32.c 
	* config/i386/gthr-win32.c: New implementation file.
	(__gthr_win32_once, __gthr_win32_key_create,
	__gthr_win32_key_delete, __gthr_win32_getspecific,
	__gthr_win32_setspecific, __gthr_win32_mutex_init_function,
	__gthr_win32_mutex_lock,__gthr_win32_mutex_trylock,
	__gthr_win32_mutex_unlock): New functions, based on
	static inlines in gthr-win32.h.

Patch attached:



http://travel.yahoo.com.au - Yahoo! Travel
- Plan and book your dream holiday online!
Index: gcc/gcc/gthr-win32.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gthr-win32.h,v
retrieving revision 1.15
diff -c -3 -p -r1.15 gthr-win32.h
*** gcc/gcc/gthr-win32.h	5 Mar 2002 22:08:23 -0000	1.15
--- gcc/gcc/gthr-win32.h	27 May 2002 21:27:02 -0000
*************** __gthread_objc_condition_signal(objc_con
*** 328,364 ****
  
  #else /* _LIBOBJC */
  
! #include <windows.h>
  
! typedef DWORD __gthread_key_t;
  
  typedef struct {
    int done;
    long started;
  } __gthread_once_t;
  
! typedef HANDLE __gthread_mutex_t;
  
! #define __GTHREAD_ONCE_INIT {FALSE, -1}
  #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
  #define __GTHREAD_MUTEX_INIT_DEFAULT 0
  
  #if __MINGW32_MAJOR_VERSION >= 1 || \
    (__MINGW32_MAJOR_VERSION == 0 && __MINGW32_MINOR_VERSION > 2)
  #define MINGW32_SUPPORTS_MT_EH 1
- #ifdef __cplusplus
- extern "C" {
- #endif
- extern int __mingwthr_key_dtor (DWORD, void (*) (void *));
- #ifdef __cplusplus
- }
- #endif
- 
  /* 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 (void)
--- 328,359 ----
  
  #else /* _LIBOBJC */
  
! #ifdef __cplusplus
! extern "C" {
! #endif
  
! typedef unsigned long __gthread_key_t;
  
  typedef struct {
    int done;
    long started;
  } __gthread_once_t;
  
! typedef void* __gthread_mutex_t;
  
! #define __GTHREAD_ONCE_INIT {0, -1}
  #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
  #define __GTHREAD_MUTEX_INIT_DEFAULT 0
  
  #if __MINGW32_MAJOR_VERSION >= 1 || \
    (__MINGW32_MAJOR_VERSION == 0 && __MINGW32_MINOR_VERSION > 2)
  #define MINGW32_SUPPORTS_MT_EH 1
  /* 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;
! extern int __mingwthr_key_dtor (unsigned long, void (*) (void *));
! #endif /* __MINGW32__ version */
  
  static inline int
  __gthread_active_p (void)
*************** __gthread_active_p (void)
*** 370,375 ****
--- 365,464 ----
  #endif
  }
  
+ #ifdef __GTHREAD_HIDE_WIN32API
+ 
+ /* The implementations are in config/i386/gthr-win32.c in libgcc.a.
+    Only stubs are exposed to avoid polluting the C++ namespace with
+    windows api definitions.  */
+ 
+ extern int __gthr_win32_once (__gthread_once_t *, void (*) (void));
+ extern int __gthr_win32_key_create (__gthread_key_t *, void (*) (void*));
+ extern int __gthr_win32_key_delete (__gthread_key_t);
+ extern void * __gthr_win32_getspecific (__gthread_key_t);
+ extern int __gthr_win32_setspecific (__gthread_key_t, const void *);
+ extern void __gthr_win32_mutex_init_function (__gthread_mutex_t *);
+ extern int __gthr_win32_mutex_lock (__gthread_mutex_t *);
+ extern int __gthr_win32_mutex_trylock (__gthread_mutex_t *);
+ extern int __gthr_win32_mutex_unlock (__gthread_mutex_t *);
+ 
+ static inline int
+ __gthread_once (__gthread_once_t *once, void (*func) (void))
+ {
+   if ( __gthread_active_p ())
+     return __gthr_win32_once (once, func);
+   else
+     return -1;	
+ }
+ 
+ static inline int
+ __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
+ {
+   return __gthr_win32_key_create (key, dtor);
+ }
+ 
+ static inline int
+ __gthread_key_dtor (__gthread_key_t key, void *ptr)
+ {
+   /* Nothing needed.  */
+   return 0;
+ }
+   
+  static inline int
+ __gthread_key_delete (__gthread_key_t key)
+ {
+    return __gthr_win32_key_delete (key);
+ }
+ 
+ static inline void *
+ __gthread_getspecific (__gthread_key_t key)
+ {
+   return __gthr_win32_getspecific (key);
+ }
+ 
+ static inline int
+ __gthread_setspecific (__gthread_key_t key, const void *ptr)
+ {
+   return __gthr_win32_setspecific (key, ptr);
+ }
+ 
+ static inline void
+ __gthread_mutex_init_function (__gthread_mutex_t *mutex)
+ {
+   __gthr_win32_mutex_init_function (mutex);
+ }
+ 
+ static inline int
+ __gthread_mutex_lock (__gthread_mutex_t *mutex)
+ {
+   if (__gthread_active_p ())
+     return __gthr_win32_mutex_lock (mutex);
+   else
+     return 0;
+ }
+ 
+ static inline int
+ __gthread_mutex_trylock (__gthread_mutex_t *mutex)
+ {
+   if (__gthread_active_p ())
+     return __gthr_win32_mutex_trylock (mutex);
+   else
+     return 0;	
+ }
+ 
+ static inline int
+ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
+ {
+   if (__gthread_active_p ())
+     return __gthr_win32_mutex_unlock (mutex);
+   else
+     return 0;	
+ }
+ 
+ #else /* ! __GTHREAD_HIDE_WIN32API */
+ 
+ #include <windows.h>
+ #include <errno.h>
+ 
  static inline int
  __gthread_once (__gthread_once_t *once, void (*func) (void))
  {
*************** __gthread_mutex_unlock (__gthread_mutex_
*** 504,510 ****
      return 0;
  }
  
  #endif /* _LIBOBJC */
  
  #endif /* ! GCC_GTHR_WIN32_H */
- 
--- 593,604 ----
      return 0;
  }
  
+ #endif /*  __GTHREAD_HIDE_WIN32API */
+ 
+ #ifdef __cplusplus
+ }
+ #endif
+ 
  #endif /* _LIBOBJC */
  
  #endif /* ! GCC_GTHR_WIN32_H */
Index: gcc/gcc/config/i386/t-cygwin
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/t-cygwin,v
retrieving revision 1.9
diff -c -3 -p -r1.9 t-cygwin
*** gcc/gcc/config/i386/t-cygwin	15 Nov 2001 13:05:53 -0000	1.9
--- gcc/gcc/config/i386/t-cygwin	27 May 2002 21:16:53 -0000
*************** winnt.o: $(srcdir)/config/i386/winnt.c $
*** 19,21 ****
--- 19,24 ----
  
  # Don't run fixproto
  STMP_FIXPROTO =
+ 
+ # We hide calls to w32api needed for w32 thread support here:
+ LIB2FUNCS_EXTRA = $(srcdir)/config/i386/gthr-win32.c
*** /dev/null	Tue May 28 09:29:47 2002
--- gcc/gcc/config/i386/gthr-win32.c	Mon May 27 13:44:26 2002
***************
*** 0 ****
--- 1,174 ----
+ /* Implementation of W32-specific threads compatibility routines for
+    libgcc2.   */ 
+ 
+ /* Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
+    Contributed by Mumit Khan <khan@xraylith.wisc.edu>.
+    Modified and moved to separate file by Danny Smith
+    <dannysmith@users.sourceforge.net>.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+ 
+ GCC 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 General Public License
+ for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING.  If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.  */
+ 
+ /* As a special exception, if you link this library with other files,
+    some of which are compiled with GCC, to produce an executable,
+    this library does not by itself cause the resulting executable
+    to be covered by the GNU General Public License.
+    This exception does not however invalidate any other reasons why
+    the executable file might be covered by the GNU General Public License.  */
+ 
+ 
+ #ifndef __GTHREAD_HIDE_WIN32API
+ # define __GTHREAD_HIDE_WIN32API
+ #endif
+ #include <gthr-win32.h>
+ #include <windows.h>
+ 
+ /* Windows32 threads specific definitions. The windows32 threading model
+    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 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. In the long term, GCC
+    needs to use Structured Exception Handling on Windows32.  */
+ 
+ int
+ __gthr_win32_once (__gthread_once_t *once, void (*func) (void))
+ {
+   if (once == NULL || func == NULL)
+     return EINVAL;
+ 
+   if (! once->done)
+     {
+       if (InterlockedIncrement (&(once->started)) == 0)
+         {
+ 	  (*func) ();
+ 	  once->done = TRUE;
+ 	}
+       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; 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.  */
+ 
+ int
+ __gthr_win32_key_create (__gthread_key_t *key, void (*dtor) (void *))
+ {
+   int status = 0;
+   DWORD tls_index = TlsAlloc ();
+   if (tls_index != 0xFFFFFFFF)
+     {
+       *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;
+ }
+ 
+ int
+ __gthr_win32_key_delete (__gthread_key_t key)
+ {
+   return (TlsFree (key) != 0) ? 0 : (int) GetLastError ();
+ }
+ 
+ void *
+ __gthr_win32_getspecific (__gthread_key_t key)
+ {
+   DWORD lasterror;
+   void *ptr;
+   lasterror = GetLastError();
+   ptr = TlsGetValue(key);
+   SetLastError( lasterror );
+   return ptr;
+ }
+ 
+ int
+ __gthr_win32_setspecific (__gthread_key_t key, const void *ptr)
+ {
+   return (TlsSetValue (key, (void*) ptr) != 0) ? 0 : (int) GetLastError ();
+ }
+ 
+ void
+ __gthr_win32_mutex_init_function (__gthread_mutex_t *mutex)
+ {
+   /* Create unnamed mutex with default security attr and no initial owner.  */ 
+   *mutex = CreateMutex (NULL, 0, NULL);
+ }
+ 
+ int
+ __gthr_win32_mutex_lock (__gthread_mutex_t *mutex)
+ {
+   if (WaitForSingleObject (*mutex, INFINITE) == WAIT_OBJECT_0)
+     return 0;
+   else
+     return 1;
+ }
+ 
+ int
+ __gthr_win32_mutex_trylock (__gthread_mutex_t *mutex)
+ {
+   if (WaitForSingleObject (*mutex, 0) == WAIT_OBJECT_0)
+     return 0;
+   else
+     return 1;
+ }
+ 
+ int
+ __gthr_win32_mutex_unlock (__gthread_mutex_t *mutex)
+ {
+     return (ReleaseMutex (*mutex) != 0) ? 0 : 1;
+ }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]