Commit b25bb36a by Danny Smith Committed by Danny Smith

gthr-win32.h: Wrap all functions in extern "C".

	* 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.
	(__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-mingw32 (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.

From-SVN: r54484
parent a69c385e
2002-06-11 Danny Smith <dannysmith@users.sourforge.net>
* gthr-win32.h: Wrap 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.
(__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-mingw32 (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.
2002-06-10 Bob Wilson <bob.wilson@acm.org> 2002-06-10 Bob Wilson <bob.wilson@acm.org>
* config/xtensa/xtensa.c (override_options): Don't warn about * config/xtensa/xtensa.c (override_options): Don't warn about
......
/* 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;
}
...@@ -2,3 +2,6 @@ ...@@ -2,3 +2,6 @@
# collect2 doesn't work for i386-mingw32* yet. # collect2 doesn't work for i386-mingw32* yet.
# #
USE_COLLECT2= USE_COLLECT2=
# We hide calls to w32api needed for w32 thread support here:
LIB2FUNCS_EXTRA = $(srcdir)/config/i386/gthr-win32.c
...@@ -328,37 +328,32 @@ __gthread_objc_condition_signal(objc_condition_t condition) ...@@ -328,37 +328,32 @@ __gthread_objc_condition_signal(objc_condition_t condition)
#else /* _LIBOBJC */ #else /* _LIBOBJC */
#include <windows.h> #ifdef __cplusplus
extern "C" {
#endif
typedef DWORD __gthread_key_t; typedef unsigned long __gthread_key_t;
typedef struct { typedef struct {
int done; int done;
long started; long started;
} __gthread_once_t; } __gthread_once_t;
typedef HANDLE __gthread_mutex_t; typedef void* __gthread_mutex_t;
#define __GTHREAD_ONCE_INIT {FALSE, -1} #define __GTHREAD_ONCE_INIT {0, -1}
#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
#define __GTHREAD_MUTEX_INIT_DEFAULT 0 #define __GTHREAD_MUTEX_INIT_DEFAULT 0
#if __MINGW32_MAJOR_VERSION >= 1 || \ #if __MINGW32_MAJOR_VERSION >= 1 || \
(__MINGW32_MAJOR_VERSION == 0 && __MINGW32_MINOR_VERSION > 2) (__MINGW32_MAJOR_VERSION == 0 && __MINGW32_MINOR_VERSION > 2)
#define MINGW32_SUPPORTS_MT_EH 1 #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 /* 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 if -mthreads option was specified, or 0 otherwise. This is to get around
the lack of weak symbols in PE-COFF. */ the lack of weak symbols in PE-COFF. */
extern int _CRT_MT; extern int _CRT_MT;
#endif extern int __mingwthr_key_dtor (unsigned long, void (*) (void *));
#endif /* __MINGW32__ version */
static inline int static inline int
__gthread_active_p (void) __gthread_active_p (void)
...@@ -370,6 +365,100 @@ __gthread_active_p (void) ...@@ -370,6 +365,100 @@ __gthread_active_p (void)
#endif #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 static inline int
__gthread_once (__gthread_once_t *once, void (*func) (void)) __gthread_once (__gthread_once_t *once, void (*func) (void))
{ {
...@@ -504,7 +593,12 @@ __gthread_mutex_unlock (__gthread_mutex_t *mutex) ...@@ -504,7 +593,12 @@ __gthread_mutex_unlock (__gthread_mutex_t *mutex)
return 0; return 0;
} }
#endif /* __GTHREAD_HIDE_WIN32API */
#ifdef __cplusplus
}
#endif
#endif /* _LIBOBJC */ #endif /* _LIBOBJC */
#endif /* ! GCC_GTHR_WIN32_H */ #endif /* ! GCC_GTHR_WIN32_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment