diff options
author | rpj <rpj> | 2000-08-18 08:02:29 +0000 |
---|---|---|
committer | rpj <rpj> | 2000-08-18 08:02:29 +0000 |
commit | 11eb4dfd2d42417327fc205c649ea32ee623cf92 (patch) | |
tree | 79b7a28890e779a4cc8d77e9289dba919d371bdd | |
parent | 88de1621e4371cd118e1a98c9c08ff23c46e6899 (diff) |
2000-08-18 Ross Johnson <rpj@setup1.ise.canberra.edu.au>
* Several: Fix typos from scripted edit session
yesterday.
* nonportable.c (pthread_mutexattr_setforcecs_np):
Moved this function from mutex.c.
(pthread_getw32threadhandle_np): New function to
return the win32 thread handle that the POSIX
thread is using.
* mutex.c (pthread_mutexattr_setforcecs_np):
Moved to new file "nonportable.c".
* pthread.h (PTW32_BUILD): Only redefine __except
and catch compiler keywords if we aren't building
the library (ie. PTW32_BUILD is not defined) -
this is safer than defining and then undefining
if not building the library.
* implement.h: Remove __except and catch undefines.
* Makefile (CFLAGS): Define PTW32_BUILD.
* GNUmakefile (CFLAGS): Define PTW32_BUILD.
* All appropriate: Change Pthread_exception* to
ptw32_exception* to be consistent with internal
identifier naming.
* private.c (ptw32_throw): New function to provide
a generic exception throw for all internal
exceptions and EH schemes.
(ptw32_threadStart): pthread_exit() value is now
returned via the thread structure exitStatus
element.
* exit.c (pthread_exit): pthread_exit() value is now
returned via the thread structure exitStatus
element.
* cancel.c (ptw32_cancel_self): Now uses ptw32_throw.
(pthread_setcancelstate): Ditto.
(pthread_setcanceltype): Ditto.
(pthread_testcancel): Ditto.
(pthread_cancel): Ditto.
* misc.c (CancelableWait): Ditto.
* exit.c (pthread_exit): Ditto.
* All applicable: Change PTW32_ prefix to
PTW32_ prefix to remove leading underscores
from private library identifiers.
-rw-r--r-- | ANNOUNCE | 32 | ||||
-rw-r--r-- | ChangeLog | 110 | ||||
-rw-r--r-- | GNUmakefile | 8 | ||||
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | README | 42 | ||||
-rw-r--r-- | attr.c | 4 | ||||
-rw-r--r-- | cancel.c | 58 | ||||
-rw-r--r-- | cleanup.c | 4 | ||||
-rw-r--r-- | condvar.c | 14 | ||||
-rw-r--r-- | dll.c | 2 | ||||
-rw-r--r-- | exit.c | 42 | ||||
-rw-r--r-- | global.c | 2 | ||||
-rw-r--r-- | implement.h | 50 | ||||
-rw-r--r-- | misc.c | 27 | ||||
-rw-r--r-- | mutex.c | 30 | ||||
-rw-r--r-- | private.c | 69 | ||||
-rw-r--r-- | pthread.def | 3 | ||||
-rw-r--r-- | pthread.h | 55 | ||||
-rw-r--r-- | rwlock.c | 18 | ||||
-rw-r--r-- | sched.c | 2 | ||||
-rw-r--r-- | tsd.c | 2 |
21 files changed, 294 insertions, 283 deletions
@@ -26,19 +26,14 @@ Change Summary (since the last snapshot) (See the ChangeLog file for details.)
New:
-- Renamed DLL and LIB files:
- pthreadVSE.dll (MS VC++/Structured EH)
- pthreadVSE.lib
- pthreadVCE.dll (MS VC++/C++ EH)
- pthreadVCE.lib
- pthreadGCE.dll (GNU G++/C++ EH)
- libpthreadw32.a
-
- Both your application and the pthread dll should use the
- same exception handling scheme.
+- New non-portable function (see the README file):
+ pthread_getw32threadhandle_np
Bugs fixed:
-- MSVC++ C++ exception handling.
+- TSD key creation race condition;
+- Other potential race conditions
+ associated with initialising various
+ pthreads objects.
Some new tests have been added.
@@ -46,15 +41,18 @@ Some new tests have been added. Known bugs in this snapshot
---------------------------
-1. Running the test "join1.c" with the library built with Mingw32
+1. Asynchronous cancelation only works on Intel X86 machines.
+
+2. Running the test "join1.c" with the library built with Mingw32
and the GNUmakefile included, the test fails with a segmentation (invalid
page access) exception. The fault appears to be in the assembler code
emmitted by the compiler [to handle exception contexts] at the
end of the try block in ptw32_threadStart().
-2. There are problems using the libpthreadw32.a stub archive derived
+3. There are problems using the libpthreadw32.a stub archive derived
from either of pthreadVSE.dll or pthreadVCE.dll. The cleanup1.c test
-fails.
+fails. This is now an expected result of having different EH and cleanup
+handler schemes in the library and application.
Caveats
@@ -208,6 +206,12 @@ The following functions are implemented: pthread_sigmask
---------------------------
+ Non-portable routines (see the README file for usage)
+ ---------------------------
+ pthread_mutexattr_setforcecs_np
+ pthread_getw32threadhandle_np
+
+ ---------------------------
Static Initializers (macros)
---------------------------
PTHREAD_ONCE_INIT
@@ -1,3 +1,49 @@ +2000-08-18 Ross Johnson <rpj@setup1.ise.canberra.edu.au> + + * Several: Fix typos from scripted edit session + yesterday. + + * nonportable.c (pthread_mutexattr_setforcecs_np): + Moved this function from mutex.c. + (pthread_getw32threadhandle_np): New function to + return the win32 thread handle that the POSIX + thread is using. + * mutex.c (pthread_mutexattr_setforcecs_np): + Moved to new file "nonportable.c". + + * pthread.h (PTW32_BUILD): Only redefine __except + and catch compiler keywords if we aren't building + the library (ie. PTW32_BUILD is not defined) - + this is safer than defining and then undefining + if not building the library. + * implement.h: Remove __except and catch undefines. + * Makefile (CFLAGS): Define PTW32_BUILD. + * GNUmakefile (CFLAGS): Define PTW32_BUILD. + + * All appropriate: Change Pthread_exception* to + ptw32_exception* to be consistent with internal + identifier naming. + + * private.c (ptw32_throw): New function to provide + a generic exception throw for all internal + exceptions and EH schemes. + (ptw32_threadStart): pthread_exit() value is now + returned via the thread structure exitStatus + element. + * exit.c (pthread_exit): pthread_exit() value is now + returned via the thread structure exitStatus + element. + * cancel.c (ptw32_cancel_self): Now uses ptw32_throw. + (pthread_setcancelstate): Ditto. + (pthread_setcanceltype): Ditto. + (pthread_testcancel): Ditto. + (pthread_cancel): Ditto. + * misc.c (CancelableWait): Ditto. + * exit.c (pthread_exit): Ditto. + * All applicable: Change PTW32_ prefix to + PTW32_ prefix to remove leading underscores + from private library identifiers. + 2000-08-17 Ross Johnson <rpj@special.ise.canberra.edu.au> * All applicable: Change _pthread_ prefix to @@ -116,7 +162,7 @@ 2000-08-03 Ross Johnson <rpj@special.ise.canberra.edu.au> - * pthread.h: Add a base class Pthread_exception for + * pthread.h: Add a base class ptw32_exception for library internal exceptions and change the "catch" re-define macro to use it. @@ -254,13 +300,13 @@ 2000-01-04 Ross Johnson <rpj@special.ise.canberra.edu.au> * private.c (ptw32_get_exception_services_code): New; returns - value of EXCEPTION_PTHREAD_SERVICES. + value of EXCEPTION_PTW32_SERVICES. (ptw32_processInitialize): Remove initialisation of ptw32_exception_services which is no longer needed. * pthread.h (ptw32_exception_services): Remove extern. (ptw32_get_exception_services_code): Add function prototype; - use this to return EXCEPTION_PTHREAD_SERVICES value instead of + use this to return EXCEPTION_PTW32_SERVICES value instead of using the ptw32_exception_services variable which I had trouble exporting through pthread.def. @@ -524,15 +570,15 @@ Tue Aug 17 20:00:08 1999 Mumit Khan <khan@xraylith.wisc.edu> (general): Define and rename exceptions. - * misc.c (CancelableWait): _PTHREAD_EPS_CANCEL (SEH) and - Pthread_exception_cancel (C++) used to identify the exception. + * misc.c (CancelableWait): PTW32_EPS_CANCEL (SEH) and + ptw32_exception_cancel (C++) used to identify the exception. - * cancel.c (pthread_testcancel): _PTHREAD_EPS_CANCEL (SEH) and - Pthread_exception_cancel (C++) used to identify the exception. + * cancel.c (pthread_testcancel): PTW32_EPS_CANCEL (SEH) and + ptw32_exception_cancel (C++) used to identify the exception. * exit.c (pthread_exit): throw/raise an exception to return to - ptw32_threadStart() to exit the thread. _PTHREAD_EPS_EXIT (SEH) - and Pthread_exception_exit (C++) used to identify the exception. + ptw32_threadStart() to exit the thread. PTW32_EPS_EXIT (SEH) + and ptw32_exception_exit (C++) used to identify the exception. * private.c (ptw32_threadStart): Add pthread_exit exception trap; clean up and exit the thread directly rather than via pthread_exit(). @@ -822,7 +868,7 @@ Fri Feb 5 13:42:30 1999 Ross Johnson <rpj@swan.canberra.edu.au> Thu Feb 4 10:07:28 1999 Ross Johnson <rpj@ixobrychus.canberra.edu.au> - * global.c: Remove Pthread_exception instantiation. + * global.c: Remove ptw32_exception instantiation. * cancel.c (pthread_testcancel): Change C++ exception throw. @@ -858,7 +904,7 @@ Tue Feb 2 18:07:43 1999 Ross Johnson <rpj@swan.canberra.edu.au> Reverse LHS/RHS bitwise assignments. * pthread.h: Remove #include <semaphore.h>. - (_PTHREAD_ATTR_VALID): Add cast. + (PTW32_ATTR_VALID): Add cast. (struct pthread_t_): Add sigmask element. * dll.c: Add "extern C" for DLLMain. @@ -950,7 +996,7 @@ Fri Jan 22 14:31:59 1999 Ross Johnson <rpj@swan.canberra.edu.au> * cancel.c (pthread_testcancel): Ditto. - * implement.h (class pthread_exception): Define for C++. + * implement.h (class ptw32_exception): Define for C++. * pthread.h: Fix C, C++, and Win32 SEH condition compilation mayhem around pthread_cleanup_* defines. C++ version now uses John @@ -1400,7 +1446,7 @@ Sat Oct 24 18:34:59 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> Fri Oct 23 00:08:09 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> - * implement.h (_PTHREAD_TSD_KEY_REUSE): Add enum. + * implement.h (PTW32_TSD_KEY_REUSE): Add enum. * private.c (ptw32_delete_thread): Add call to ptw32_destructor_run_all() to clean up the threads keys. @@ -1486,8 +1532,8 @@ Mon Oct 12 00:00:44 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> * implement.h (ptw32_destructor_push): Remove. (ptw32_destructor_pop): Remove. (ptw32_destructor_run_all): Rename from ptw32_destructor_pop_all. - (_PTHREAD_TSD_KEY_DELETED): Add enum. - (_PTHREAD_TSD_KEY_INUSE): Add enum. + (PTW32_TSD_KEY_DELETED): Add enum. + (PTW32_TSD_KEY_INUSE): Add enum. * cleanup.c (ptw32_destructor_push): Remove. (ptw32_destructor_pop): Remove. @@ -1693,7 +1739,7 @@ Thu Aug 6 15:19:22 1998 Ross Johnson <rpj@swan.canberra.edu.au> * private.c (ptw32_new_thread): Typecast (HANDLE) NULL. (ptw32_delete_thread): Ditto. - * implement.h: (_PTHREAD_MAX_THREADS): Add define. This keeps + * implement.h: (PTW32_MAX_THREADS): Add define. This keeps changing in an attempt to make thread administration data types opaque and cleanup DLL startup. @@ -1704,7 +1750,7 @@ Thu Aug 6 15:19:22 1998 Ross Johnson <rpj@swan.canberra.edu.au> (ptw32_threads_mutex_table): Ditto. * global.c (_POSIX_THREAD_THREADS_MAX): Initialise with - _PTHREAD_MAX_THREADS. + PTW32_MAX_THREADS. (ptw32_virgins): Ditto. (ptw32_reuse): Ditto. (ptw32_win32handle_map): Ditto. @@ -1839,9 +1885,9 @@ Mon Aug 3 21:19:57 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> member initialisation - cancelstate, canceltype, cancel_pending. (is_attr): Make arg "attr" a const. - * implement.h (_PTHREAD_HANDLER_POP_LIFO): Remove definition. - (_PTHREAD_HANDLER_POP_FIFO): Ditto. - (_PTHREAD_VALID): Add missing newline escape (\). + * implement.h (PTW32_HANDLER_POP_LIFO): Remove definition. + (PTW32_HANDLER_POP_FIFO): Ditto. + (PTW32_VALID): Add missing newline escape (\). (ptw32_handler_node): Make element "next" a pointer. 1998-08-02 Ben Elliston <bje@cygnus.com> @@ -1903,8 +1949,8 @@ Fri Jul 31 00:05:45 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> * condvar.c (windows.h): Add include. - * implement.h (_PTHREAD_THIS): Remove - no longer required. - (_PTHREAD_STACK): Use pthread_self() instead of _PTHREAD_THIS. + * implement.h (PTW32_THIS): Remove - no longer required. + (PTW32_STACK): Use pthread_self() instead of PTW32_THIS. Thu Jul 30 23:12:45 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> @@ -1921,7 +1967,7 @@ Thu Jul 30 23:12:45 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> local storage. * implement.h: Add ptw32_threadID_TlsIndex. - Add ()s around _PTHREAD_VALID expression. + Add ()s around PTW32_VALID expression. * misc.c (pthread_self): Re-implement using Win32 TLS to store the threads own ID. @@ -1940,7 +1986,7 @@ Wed Jul 29 11:39:03 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> Tue Jul 28 14:04:29 1998 Ross Johnson <rpj@swan.canberra.edu.au> - * implement.h: Add _PTHREAD_VALID macro. + * implement.h: Add PTW32_VALID macro. * sync.c (pthread_join): Modify to use the new thread type and ptw32_delete_thread(). Rename "target" to "thread". @@ -1956,14 +2002,14 @@ Tue Jul 28 14:04:29 1998 Ross Johnson <rpj@swan.canberra.edu.au> * private.c (ptw32_find_thread): Fix return type and arg. - * implement.h: Remove _PTHREAD_YES and _PTHREAD_NO. + * implement.h: Remove PTW32_YES and PTW32_NO. (ptw32_new_thread): Add prototype. (ptw32_find_thread): Ditto. (ptw32_delete_thread): Ditto. (ptw32_new_thread_entry): Remove prototype. (ptw32_find_thread_entry): Ditto. (ptw32_delete_thread_entry): Ditto. - ( _PTHREAD_NEW, _PTHREAD_INUSE, _PTHREAD_EXITED, _PTHREAD_REUSE): + ( PTW32_NEW, PTW32_INUSE, PTW32_EXITED, PTW32_REUSE): Add. @@ -2146,7 +2192,7 @@ Sat Jul 25 00:00:13 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> * exit.c (pthread_exit): Fix indirection mistake. - * implement.h (_PTHREAD_THREADS_TABLE_INDEX): Add. + * implement.h (PTW32_THREADS_TABLE_INDEX): Add. * exit.c (ptw32_vacuum): Fix incorrect args to ptw32_handler_pop_all() calls. @@ -2154,7 +2200,7 @@ Sat Jul 25 00:00:13 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> * sync.c (pthread_join): Add multiple join and async detach handling. - * implement.h (_PTHREAD_THREADS_TABLE_INDEX): Add. + * implement.h (PTW32_THREADS_TABLE_INDEX): Add. * global.c (ptw32_threads_mutex_table): Add. @@ -2192,8 +2238,8 @@ Fri Jul 24 21:13:55 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> * exit.c (pthread_exit): Add comment explaining the longjmp(). * implement.h (ptw32_threads_thread_t): New member cancelthread. - (_PTHREAD_YES): Define. - (_PTHREAD_NO): Define. + (PTW32_YES): Define. + (PTW32_NO): Define. (RND_SIZEOF): Remove. * create.c (pthread_create): Rename cancelability to cancelstate. @@ -2309,7 +2355,7 @@ Fri Jul 24 00:21:21 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> (pthread_attr_getdetachstate): Implement. (pthread_attr_setdetachstate): Likewise. - * implement.h (_PTHREAD_CANCEL_DEFAULTS): Remove. Bit fields + * implement.h (PTW32_CANCEL_DEFAULTS): Remove. Bit fields proved to be too cumbersome. Set the defaults in attr.c using the public PTHREAD_CANCEL_* constants. @@ -2495,7 +2541,7 @@ Mon Jul 20 02:31:05 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> non-sharable static data within the pthread DLL. * implement.h: Add ptw32_cleanup_stack_t, ptw32_cleanup_node_t - and _PTHREAD_HASH_INDEX. + and PTW32_HASH_INDEX. * exit.c (pthread_exit): Begin work on cleanup and de-allocate thread-private storage. diff --git a/GNUmakefile b/GNUmakefile index c91a782..85dd95b 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -33,14 +33,14 @@ LD = gcc -mdll OPT = -g -O0 -x $(GLANG) ## Mingw32 -CFLAGS = $(OPT) -I. -mthreads -DHAVE_CONFIG_H -Wall +CFLAGS = $(OPT) -I. -mthreads -DHAVE_CONFIG_H -DPTW32_BUILD -Wall ## Cygwin G++ -#CFLAGS = $(OPT) -fhandle-exceptions -I. -DHAVE_CONFIG_H -Wall +#CFLAGS = $(OPT) -fhandle-exceptions -I. -DHAVE_CONFIG_H -DPTW32_BUILD -Wall OBJS = attr.o cancel.o cleanup.o condvar.o create.o dll.o errno.o \ - exit.o fork.o global.o misc.o mutex.o private.o rwlock.o \ - sched.o semaphore.o signal.o sync.o tsd.o + exit.o fork.o global.o misc.o mutex.o nonportable.o \ + private.o rwlock.o sched.o semaphore.o signal.o sync.o tsd.o INCL = implement.h semaphore.h pthread.h windows.h @@ -18,7 +18,7 @@ VCEFLAGS = /GX /TP /DPtW32NoCatchWarn #Structured Exceptions
VSEFLAGS =
-CFLAGS = /W3 /MT /nologo /Yd /Zi /I. /D_WIN32_WINNT=0x400
+CFLAGS = /W3 /MT /nologo /Yd /Zi /I. /D_WIN32_WINNT=0x400 /DPTW32_BUILD
OBJ=attr.obj \
cancel.obj \
@@ -32,6 +32,7 @@ OBJ=attr.obj \ global.obj \
misc.obj \
mutex.obj \
+ nonportable.obj \
private.obj \
rwlock.obj \
sched.obj \
@@ -52,15 +52,18 @@ The GNU library archive file name has changed to: Known bugs in this snapshot
---------------------------
-1. Running the test "join1.c" with the library built with Mingw32
+1. Asynchronous cancelation only works on Intel X86 machines.
+
+2. Running the test "join1.c" with the library built with Mingw32
and the GNUmakefile included, the test fails with a segmentation (invalid
page access) exception. The fault appears to be in the assembler code
emmitted by the compiler [to handle exception contexts] at the
end of the try block in ptw32_threadStart().
-2. There are problems using the libpthreadw32.a stub archive derived
+3. There are problems using the libpthreadw32.a stub archive derived
from either of pthreadVSE.dll or pthreadVCE.dll. The cleanup1.c test
-fails.
+fails. This is now an expected result of having different EH and cleanup
+handler schemes in the library and application.
Caveats
@@ -85,6 +88,39 @@ Otherwise neither pthreads cancelation nor pthread_exit() will work reliably.
+Non-portable functions included in the library
+----------------------------------------------
+
+void
+pthread_mutexattr_setforcecs_np(pthread_mutexattr_t *attr,
+ int forcecs);
+
+ Allows an application to force the library to use
+ critical sections rather than win32 mutexes as
+ the basis for any mutex that uses "attr".
+ Critical sections are significantly faster than
+ mutexes.
+
+ Values for "forcecs" are:
+ PTHREAD_MUTEX_AUTO_CS_NP
+ - allow the library to decide based on
+ availability of tryEnterCriticalSection()
+ PTHREAD_MUTEX_FORCE_CS_NP
+ - force use of critical sections, but you'd
+ better not try to use pthread_mutex_trylock()
+ on that mutex if you want your application
+ to work on all versions of Windows.
+
+HANDLE
+pthread_getw32threadhandle_np(pthread_t thread);
+
+ Returns the win32 thread handle that the POSIX
+ thread "thread" is running as.
+
+ Applications can use the win32 handle to set
+ win32 specific attributes of the thread.
+
+
Building under VC++ using either C++ EH or Structured EH
--------------------------------------------------------
@@ -35,7 +35,7 @@ is_attr(const pthread_attr_t *attr) return (attr == NULL || *attr == NULL || - (*attr)->valid != _PTHREAD_ATTR_VALID); + (*attr)->valid != PTW32_ATTR_VALID); } @@ -346,7 +346,7 @@ pthread_attr_init(pthread_attr_t *attr) /* Priority uses Win32 priority values. */ attr_result->priority = THREAD_PRIORITY_NORMAL; - attr_result->valid = _PTHREAD_ATTR_VALID; + attr_result->valid = PTW32_ATTR_VALID; *attr = attr_result; @@ -30,29 +30,7 @@ static void ptw32_cancel_self(void) { -#if defined(_MSC_VER) && !defined(__cplusplus) - - DWORD exceptionInformation[3]; - - exceptionInformation[0] = (DWORD) (_PTHREAD_EPS_CANCEL); - exceptionInformation[1] = (DWORD) (0); - exceptionInformation[2] = (DWORD) (0); - - RaiseException ( - EXCEPTION_PTHREAD_SERVICES, - 0, - 3, - exceptionInformation); - -#else /* _MSC_VER && ! __cplusplus */ - -# ifdef __cplusplus - - throw Pthread_exception_cancel(); - -# endif /* __cplusplus */ - -#endif /* _MSC_VER && ! __cplusplus */ + ptw32_throw(PTW32_EPS_CANCEL); /* Never reached */ } @@ -62,7 +40,7 @@ ptw32_cancel_self(void) * ptw32_cancel_thread implements asynchronous cancellation. */ static void -ptw32_ancel_thread(pthread_t thread) +ptw32_cancel_thread(pthread_t thread) { HANDLE threadH = thread->threadH; @@ -158,7 +136,7 @@ pthread_setcancelstate (int state, int *oldstate) { ResetEvent(self->cancelEvent); (void) pthread_mutex_unlock(&self->cancelLock); - ptw32_cancel_self(); + ptw32_throw(PTW32_EPS_CANCEL); /* Never reached */ } @@ -242,7 +220,7 @@ pthread_setcanceltype (int type, int *oldtype) { ResetEvent(self->cancelEvent); (void) pthread_mutex_unlock(&self->cancelLock); - ptw32_cancel_self(); + ptw32_throw(PTW32_EPS_CANCEL); /* Never reached */ } @@ -293,31 +271,7 @@ pthread_testcancel (void) /* * Canceling! */ - -#if defined(_MSC_VER) && !defined(__cplusplus) - - DWORD exceptionInformation[3]; - - exceptionInformation[0] = (DWORD) (_PTHREAD_EPS_CANCEL); - exceptionInformation[1] = (DWORD) (0); - exceptionInformation[2] = (DWORD) (0); - - RaiseException ( - EXCEPTION_PTHREAD_SERVICES, - 0, - 3, - exceptionInformation); - -#else /* _MSC_VER && ! __cplusplus */ - -#ifdef __cplusplus - - throw Pthread_exception_cancel(); - -#endif /* __cplusplus */ - -#endif /* _MSC_VER && ! __cplusplus */ - + ptw32_throw(PTW32_EPS_CANCEL); } } /* pthread_testcancel */ @@ -384,7 +338,7 @@ pthread_cancel (pthread_t thread) if (cancel_self) { (void) pthread_mutex_unlock(&self->cancelLock); - ptw32_cancel_self(); + ptw32_throw(PTW32_EPS_CANCEL); /* Never reached */ } @@ -69,7 +69,7 @@ pthread_pop_cleanup (int execute) { ptw32_cleanup_t *cleanup = NULL; - cleanup = (ptw32_leanup_t *) pthread_getspecific (ptw32_leanupKey); + cleanup = (ptw32_cleanup_t *) pthread_getspecific (ptw32_cleanupKey); if (cleanup != NULL) { @@ -105,7 +105,7 @@ pthread_pop_cleanup (int execute) */ (*cleanup->routine) (cleanup->arg); } - catch(...) + catch(...) { /* * A system unexpected exception had occurred @@ -61,7 +61,7 @@ _cond_check_need_init(pthread_cond_t *cond) * re-initialise it only by calling pthread_cond_init() * explicitly. */ - if (*cond == (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*cond == (pthread_cond_t) PTW32_OBJECT_AUTO_INIT) { result = pthread_cond_init(cond, NULL); } @@ -464,7 +464,7 @@ pthread_cond_destroy (pthread_cond_t * cond) return EINVAL; } - if (*cond != (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*cond != (pthread_cond_t) PTW32_OBJECT_AUTO_INIT) { cv = *cond; @@ -492,12 +492,12 @@ pthread_cond_destroy (pthread_cond_t * cond) /* * See notes in _cond_check_need_init() above also. */ - EnterCriticalSection(&ptw32_ond_test_init_lock); + EnterCriticalSection(&ptw32_cond_test_init_lock); /* * Check again. */ - if (*cond == (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*cond == (pthread_cond_t) PTW32_OBJECT_AUTO_INIT) { /* * This is all we need to do to destroy a statically @@ -604,7 +604,7 @@ cond_timedwait (pthread_cond_t * cond, * again inside the guarded section of _cond_check_need_init() * to avoid race conditions. */ - if (*cond == (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*cond == (pthread_cond_t) PTW32_OBJECT_AUTO_INIT) { result = _cond_check_need_init(cond); } @@ -855,7 +855,7 @@ pthread_cond_signal (pthread_cond_t * cond) * No-op if the CV is static and hasn't been initialised yet. * Assuming that race conditions are harmless. */ - if (cv == (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT) + if (cv == (pthread_cond_t) PTW32_OBJECT_AUTO_INIT) { return 0; } @@ -926,7 +926,7 @@ pthread_cond_broadcast (pthread_cond_t * cond) * No-op if the CV is static and hasn't been initialised yet. * Assuming that any race condition is harmless. */ - if (cv == (pthread_cond_t) _PTHREAD_OBJECT_AUTO_INIT) + if (cv == (pthread_cond_t) PTW32_OBJECT_AUTO_INIT) { return 0; } @@ -82,7 +82,7 @@ DllMain ( /* * The DLL is being mapped into the process's address space */ - result = ptw32_rocessInitialize (); + result = ptw32_processInitialize (); /* Load KERNEL32 and try to get address of TryEnterCriticalSection */ ptw32_h_kernel32 = LoadLibrary(TEXT("KERNEL32.DLL")); @@ -53,12 +53,6 @@ pthread_exit (void *value_ptr) { pthread_t self; -#if defined(_MSC_VER) && !defined(__cplusplus) - - DWORD exceptionInformation[3]; - -#endif - /* If the current thread is implicit it was not started through pthread_create(), therefore we cleanup and end the thread here. Otherwise we raise an exception to unwind the exception @@ -70,7 +64,7 @@ pthread_exit (void *value_ptr) if (self == NULL || self->implicit) { - ptw32_allUserDestroyRoutines(self); + ptw32_callUserDestroyRoutines(self); #if ! defined (__MINGW32__) || defined (__MSVCRT__) _endthreadex ((unsigned) value_ptr); @@ -83,39 +77,7 @@ pthread_exit (void *value_ptr) self->exitStatus = value_ptr; -#if defined(_MSC_VER) && !defined(__cplusplus) - - exceptionInformation[0] = (DWORD) (_PTHREAD_EPS_EXIT); - exceptionInformation[1] = (DWORD) (value_ptr); - exceptionInformation[2] = (DWORD) (0); - - RaiseException ( - EXCEPTION_PTHREAD_SERVICES, - 0, - 3, - exceptionInformation); - -#else /* ! _MSC_VER */ - -#ifdef __cplusplus - - throw Pthread_exception_exit(); - -#else /* ! __cplusplus */ - - (void) pthread_pop_cleanup( 1 ); - - ptw32_callUserDestroyRoutines(self); - -#if ! defined (__MINGW32__) || defined (__MSVCRT__) - _endthreadex ((unsigned) value_ptr); -#else - _endthread (); -#endif - -#endif /* __cplusplus */ - -#endif /* _MSC_VER */ + ptw32_throw(PTW32_EPS_EXIT); /* Never reached. */ @@ -30,7 +30,7 @@ int ptw32_processInitialized = FALSE; pthread_key_t ptw32_selfThreadKey = NULL; -pthread_key_t ptw32_leanupKey = NULL; +pthread_key_t ptw32_cleanupKey = NULL; /* * Global lock for testing internal state of PTHREAD_MUTEX_INITIALIZER diff --git a/implement.h b/implement.h index 6cfcc75..4172618 100644 --- a/implement.h +++ b/implement.h @@ -96,7 +96,7 @@ struct pthread_t_ { /* * Special value to mark attribute objects as valid. */ -#define _PTHREAD_ATTR_VALID ((unsigned long) 0xC4C0FFEE) +#define PTW32_ATTR_VALID ((unsigned long) 0xC4C0FFEE) struct pthread_attr_t_ { unsigned long valid; @@ -118,8 +118,8 @@ struct pthread_attr_t_ { * ==================== */ -#define _PTHREAD_OBJECT_AUTO_INIT ((void *) -1) -#define _PTHREAD_OBJECT_INVALID NULL +#define PTW32_OBJECT_AUTO_INIT ((void *) -1) +#define PTW32_OBJECT_INVALID NULL struct pthread_mutex_t_ { HANDLE mutex; @@ -282,51 +282,29 @@ struct ThreadKeyAssoc { * We store our actual component and error code within * the optional information array. */ -#define EXCEPTION_PTHREAD_SERVICES \ +#define EXCEPTION_PTW32_SERVICES \ MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \ - _PTHREAD_SERVICES_FACILITY, \ - _PTHREAD_SERVICES_ERROR ) + PTW32_SERVICES_FACILITY, \ + PTW32_SERVICES_ERROR ) -#define _PTHREAD_SERVICES_FACILITY 0xBAD -#define _PTHREAD_SERVICES_ERROR 0xDEED +#define PTW32_SERVICES_FACILITY 0xBAD +#define PTW32_SERVICES_ERROR 0xDEED /* - * Services available through EXCEPTION_PTHREAD_SERVICES + * Services available through EXCEPTION_PTW32_SERVICES */ -#define _PTHREAD_EPS_CANCEL 0 -#define _PTHREAD_EPS_EXIT 1 - -/* - * '__except' was redefined in pthread.h. We use the real one internally. - */ -#ifdef __except -#undef __except -#endif - -#else - -#ifdef __cplusplus -/* - * 'catch' was redefined in pthread.h. We use the real one internally. - */ -#ifdef catch -#undef catch -#endif - -#else /* __cplusplus */ - -#warning File __FILE__, Line __LINE__: Cancellation not supported if library compiled as C. - -#endif /* __cplusplus */ +#define PTW32_EPS_CANCEL 0 +#define PTW32_EPS_EXIT 1 #endif /* _MSC_VER */ + /* Function pointer to TryEnterCriticalSection if it exists; otherwise NULL */ extern BOOL (WINAPI *ptw32_try_enter_critical_section)(LPCRITICAL_SECTION); /* Declared in global.c */ extern int ptw32_processInitialized; -extern pthread_key_t ptw32_elfThreadKey; +extern pthread_key_t ptw32_selfThreadKey; extern pthread_key_t ptw32_cleanupKey; extern CRITICAL_SECTION ptw32_mutex_test_init_lock; extern CRITICAL_SECTION ptw32_cond_test_init_lock; @@ -338,6 +316,8 @@ extern CRITICAL_SECTION ptw32_rwlock_test_init_lock; void *ptw32_calloc(size_t n, size_t s); #endif +/* Declared in private.c */ +void ptw32_throw(DWORD exception); #ifdef __cplusplus extern "C" { @@ -195,7 +195,7 @@ pthread_self (void) #endif } - pthread_setspecific (ptw32_elfThreadKey, self); + pthread_setspecific (ptw32_selfThreadKey, self); } return (self); @@ -327,30 +327,7 @@ CancelableWait (HANDLE waitHandle, DWORD timeout) /* * Thread started with pthread_create */ - -#if defined(_MSC_VER) && !defined(__cplusplus) - - DWORD exceptionInformation[3]; - - exceptionInformation[0] = (DWORD) (_PTHREAD_EPS_CANCEL); - exceptionInformation[1] = (DWORD) (0); - exceptionInformation[2] = (DWORD) (0); - - RaiseException ( - EXCEPTION_PTHREAD_SERVICES, - 0, - 3, - exceptionInformation); - -#else /* _MSC_VER */ - -#ifdef __cplusplus - - throw Pthread_exception_cancel(); - -#endif /* __cplusplus */ - -#endif /* _MSC_VER */ + ptw32_throw(PTW32_EPS_CANCEL); } /* Should never get to here. */ @@ -66,7 +66,7 @@ _mutex_check_need_init(pthread_mutex_t *mutex) * re-initialise it only by calling pthread_mutex_init() * explicitly. */ - if (*mutex == (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*mutex == (pthread_mutex_t) PTW32_OBJECT_AUTO_INIT) { result = pthread_mutex_init(mutex, NULL); } @@ -140,7 +140,7 @@ pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) } else { - if (ptw32_ry_enter_critical_section != NULL + if (ptw32_try_enter_critical_section != NULL || (attr != NULL && *attr != NULL && (*attr)->forcecs == 1) @@ -209,7 +209,7 @@ pthread_mutex_destroy(pthread_mutex_t *mutex) /* * Check to see if we have something to delete. */ - if (*mutex != (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*mutex != (pthread_mutex_t) PTW32_OBJECT_AUTO_INIT) { mx = *mutex; @@ -239,7 +239,7 @@ pthread_mutex_destroy(pthread_mutex_t *mutex) /* * Check again. */ - if (*mutex == (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*mutex == (pthread_mutex_t) PTW32_OBJECT_AUTO_INIT) { /* * This is all we need to do to destroy a statically @@ -355,22 +355,6 @@ pthread_mutexattr_destroy (pthread_mutexattr_t * attr) int -pthread_mutexattr_setforcecs_np(pthread_mutexattr_t *attr, - int forcecs) -{ - if (attr == NULL || *attr == NULL) - { - /* This is disallowed. */ - return EINVAL; - } - - (*attr)->forcecs = forcecs; - - return 0; -} - - -int pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr, int *pshared) /* @@ -528,7 +512,7 @@ pthread_mutex_lock(pthread_mutex_t *mutex) * again inside the guarded section of _mutex_check_need_init() * to avoid race conditions. */ - if (*mutex == (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*mutex == (pthread_mutex_t) PTW32_OBJECT_AUTO_INIT) { result = _mutex_check_need_init(mutex); } @@ -571,7 +555,7 @@ pthread_mutex_unlock(pthread_mutex_t *mutex) * race condition. If another thread holds the * lock then we shouldn't be in here. */ - if (mx != (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT) + if (mx != (pthread_mutex_t) PTW32_OBJECT_AUTO_INIT) { if (mx->mutex == 0) { @@ -607,7 +591,7 @@ pthread_mutex_trylock(pthread_mutex_t *mutex) * again inside the guarded section of _mutex_check_need_init() * to avoid race conditions. */ - if (*mutex == (pthread_mutex_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*mutex == (pthread_mutex_t) PTW32_OBJECT_AUTO_INIT) { result = _mutex_check_need_init(mutex); } @@ -62,7 +62,7 @@ ptw32_processInitialize (void) * ------------------------------------------------------ */ { - if (ptw32_rocessInitialized) { + if (ptw32_processInitialized) { /* * ignore if already initialized. this is useful for * programs that uses a non-dll pthread @@ -184,6 +184,7 @@ ptw32_threadStart (ThreadParms * threadParms) pthread_t self; void *(*start) (void *); void *arg; + #ifdef _MSC_VER DWORD ei[] = {0,0,0}; #endif @@ -221,21 +222,21 @@ ptw32_threadStart (ThreadParms * threadParms) /* * Run the caller's routine; */ - status = (*start) (arg); + status = self->exitStatus = (*start) (arg); } __except (ExceptionFilter(GetExceptionInformation(), ei)) { DWORD ec = GetExceptionCode(); - if (ec == EXCEPTION_PTHREAD_SERVICES) + if (ec == EXCEPTION_PTW32_SERVICES) { switch (ei[0]) { - case _PTHREAD_EPS_CANCEL: + case PTW32_EPS_CANCEL: status = PTHREAD_CANCELED; break; - case _PTHREAD_EPS_EXIT: - status = (void *) ei[1]; + case PTW32_EPS_EXIT: + status = self->exitStatus; break; default: status = PTHREAD_CANCELED; @@ -247,7 +248,7 @@ ptw32_threadStart (ThreadParms * threadParms) /* * A system unexpected exception had occurred running the user's * routine. We get control back within this block because - * we can't allow the exception out of thread scope. + * we can't allow the exception to pass out of thread scope. */ status = PTHREAD_CANCELED; } @@ -264,14 +265,14 @@ ptw32_threadStart (ThreadParms * threadParms) */ status = self->exitStatus = (*start) (arg); } - catch (Pthread_exception_cancel) + catch (ptw32_exception_cancel) { /* * Thread was cancelled. */ status = self->exitStatus = PTHREAD_CANCELED; } - catch (Pthread_exception_exit) + catch (ptw32_exception_exit) { /* * Thread was exited via pthread_exit(). @@ -294,7 +295,7 @@ ptw32_threadStart (ThreadParms * threadParms) * Run the caller's routine; no cancelation or other exceptions will * be honoured. */ - status = (*start) (arg); + status = self->exitStatus = (*start) (arg); #endif /* __cplusplus */ @@ -800,7 +801,7 @@ ptw32_get_exception_services_code(void) { #if defined(_MSC_VER) && !defined(__cplusplus) - return EXCEPTION_PTHREAD_SERVICES; + return EXCEPTION_PTW32_SERVICES; #else @@ -808,3 +809,49 @@ ptw32_get_exception_services_code(void) #endif } + + +void +ptw32_throw(DWORD exception) +{ + if (exception != PTW32_EPS_CANCEL || + exception != PTW32_EPS_EXIT) + { + /* Should never enter here */ + exit(1); + } + +#if defined(_MSC_VER) && !defined(__cplusplus) + + DWORD exceptionInformation[3]; + + exceptionInformation[0] = (DWORD) (exception); + exceptionInformation[1] = (DWORD) (0); + exceptionInformation[2] = (DWORD) (0); + + RaiseException ( + EXCEPTION_PTW32_SERVICES, + 0, + 3, + exceptionInformation); + +#else /* _MSC_VER && ! __cplusplus */ + +# ifdef __cplusplus + + switch (exception) + { + case PTW32_EPS_CANCEL: + throw ptw32_exception_cancel(); + break; + case PTW32_EPS_EXIT: + throw ptw32_exception_exit(); + break; + } + +# endif /* __cplusplus */ + +#endif /* _MSC_VER && ! __cplusplus */ + + /* Never reached */ +} diff --git a/pthread.def b/pthread.def index 9ddf1a5..395f156 100644 --- a/pthread.def +++ b/pthread.def @@ -1,5 +1,5 @@ ; pthread.def
-; Last updated: $Date: 2000/08/17 10:18:36 $
+; Last updated: $Date: 2000/08/18 08:02:29 $
; Currently unimplemented functions are commented out.
@@ -102,6 +102,7 @@ pthread_rwlock_unlock ; Non-portable but useful
;
pthread_mutexattr_setforcecs_np
+pthread_getw32threadhandle_np
pthreadCancelableWait
pthreadCancelableTimedWait
;
@@ -821,9 +821,6 @@ int pthread_mutexattr_getpshared (const pthread_mutexattr_t int pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, int pshared); -int pthread_mutexattr_setforcecs_np(pthread_mutexattr_t *attr, - int forcecs); - /* * Mutex Functions */ @@ -873,7 +870,6 @@ int pthread_cond_broadcast (pthread_cond_t * cond); /* * Scheduling */ - int pthread_setschedparam (pthread_t thread, int policy, const struct sched_param *param); @@ -891,7 +887,6 @@ int pthread_attr_setschedparam (pthread_attr_t *attr, /* * Read-Write Lock Functions */ - int pthread_rwlock_init(pthread_rwlock_t *lock, const pthread_rwlockattr_t *attr); @@ -908,6 +903,15 @@ int pthread_rwlock_wrlock(pthread_rwlock_t *lock); int pthread_rwlock_unlock(pthread_rwlock_t *lock); /* + * Non-portable functions + */ +int pthread_mutexattr_setforcecs_np(pthread_mutexattr_t *attr, + int forcecs); + +HANDLE pthread_getw32threadhandle_np(pthread_t thread); + + +/* * Protected Methods * * This function blocks until the given WIN32 handle @@ -966,8 +970,21 @@ int * _errno( void ); rand() -/* FIXME: This is only required if the library was built using SEH */ +#ifdef __cplusplus + /* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +#ifndef PTW32_BUILD + +/* FIXME: This is only required if the library was built using SEH */ + * * Get internal SEH tag */ DWORD ptw32_get_exception_services_code(void); @@ -987,13 +1004,6 @@ DWORD ptw32_get_exception_services_code(void); #ifdef __cplusplus /* - * Internal exceptions - */ -class Pthread_exception {}; -class Pthread_exception_cancel : public Pthread_exception {}; -class Pthread_exception_exit : public Pthread_exception {}; - -/* * Redefine the C++ catch keyword to ensure that applications * propagate our internal exceptions up to the library's internal handlers. */ @@ -1002,21 +1012,30 @@ class Pthread_exception_exit : public Pthread_exception {}; * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' * if you want Pthread-Win32 cancelation and pthread_exit to work. */ + #ifndef PtW32NoCatchWarn + #pragma message("When compiling applications with MSVC++ and C++ exception handling:") #pragma message(" Replace any 'catch( ... )' with 'PtW32CatchAll' in POSIX threads") #pragma message(" if you want POSIX thread cancelation and pthread_exit to work.") + #endif + #define PtW32CatchAll \ - catch( Pthread_exception & ) { throw; } \ + catch( ptw32_exception & ) { throw; } \ catch( ... ) -#else + +#else /* _MSC_VER */ + #define catch( E ) \ - catch( Pthread_exception & ) { throw; } \ + catch( ptw32_exception & ) { throw; } \ catch( E ) -#endif -#endif +#endif /* _MSC_VER */ + +#endif /* __cplusplus */ + +#endif /* ! PTW32_BUILD */ #ifdef __cplusplus } /* End of extern "C" */ @@ -64,7 +64,7 @@ _rwlock_check_need_init(pthread_rwlock_t *rwlock) * re-initialise it only by calling pthread_rwlock_init() * explicitly. */ - if (*rwlock == (pthread_rwlock_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*rwlock == (pthread_rwlock_t) PTW32_OBJECT_AUTO_INIT) { result = pthread_rwlock_init(rwlock, NULL); } @@ -158,7 +158,7 @@ pthread_rwlock_destroy(pthread_rwlock_t *rwlock) return(EINVAL); } - if (*rwlock != (pthread_rwlock_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*rwlock != (pthread_rwlock_t) PTW32_OBJECT_AUTO_INIT) { rw = *rwlock; @@ -197,12 +197,12 @@ pthread_rwlock_destroy(pthread_rwlock_t *rwlock) /* * See notes in _rwlock_check_need_init() above also. */ - EnterCriticalSection(&ptw32_wlock_test_init_lock); + EnterCriticalSection(&ptw32_rwlock_test_init_lock); /* * Check again. */ - if (*rwlock == (pthread_rwlock_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*rwlock == (pthread_rwlock_t) PTW32_OBJECT_AUTO_INIT) { /* * This is all we need to do to destroy a statically @@ -254,7 +254,7 @@ pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) * again inside the guarded section of _rwlock_check_need_init() * to avoid race conditions. */ - if (*rwlock == (pthread_rwlock_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*rwlock == (pthread_rwlock_t) PTW32_OBJECT_AUTO_INIT) { result = _rwlock_check_need_init(rwlock); @@ -332,7 +332,7 @@ pthread_rwlock_wrlock(pthread_rwlock_t * rwlock) * again inside the guarded section of _rwlock_check_need_init() * to avoid race conditions. */ - if (*rwlock == (pthread_rwlock_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*rwlock == (pthread_rwlock_t) PTW32_OBJECT_AUTO_INIT) { result = _rwlock_check_need_init(rwlock); @@ -389,7 +389,7 @@ pthread_rwlock_unlock(pthread_rwlock_t * rwlock) return(EINVAL); } - if (*rwlock == (pthread_rwlock_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*rwlock == (pthread_rwlock_t) PTW32_OBJECT_AUTO_INIT) { /* * Assume any race condition here is harmless. @@ -463,7 +463,7 @@ pthread_rwlock_tryrdlock(pthread_rwlock_t * rwlock) * again inside the guarded section of _rwlock_check_need_init() * to avoid race conditions. */ - if (*rwlock == (pthread_rwlock_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*rwlock == (pthread_rwlock_t) PTW32_OBJECT_AUTO_INIT) { result = _rwlock_check_need_init(rwlock); @@ -518,7 +518,7 @@ pthread_rwlock_trywrlock(pthread_rwlock_t * rwlock) * again inside the guarded section of _rwlock_check_need_init() * to avoid race conditions. */ - if (*rwlock == (pthread_rwlock_t) _PTHREAD_OBJECT_AUTO_INIT) + if (*rwlock == (pthread_rwlock_t) PTW32_OBJECT_AUTO_INIT) { result = _rwlock_check_need_init(rwlock); @@ -34,7 +34,7 @@ is_attr(const pthread_attr_t *attr) { return (attr == NULL || *attr == NULL || - (*attr)->valid != _PTHREAD_ATTR_VALID) ? 1 : 0; + (*attr)->valid != PTW32_ATTR_VALID) ? 1 : 0; } int @@ -233,7 +233,7 @@ pthread_setspecific (pthread_key_t key, const void *value) * Resolve catch-22 of registering thread with threadSelf * key */ - self = (pthread_t) pthread_getspecific (ptw32_elfThreadKey); + self = (pthread_t) pthread_getspecific (ptw32_selfThreadKey); if (self == NULL) { self = (pthread_t) value; |