From 11eb4dfd2d42417327fc205c649ea32ee623cf92 Mon Sep 17 00:00:00 2001 From: rpj Date: Fri, 18 Aug 2000 08:02:29 +0000 Subject: 2000-08-18 Ross Johnson * 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. --- ANNOUNCE | 32 ++++++++++-------- ChangeLog | 110 ++++++++++++++++++++++++++++++++++++++++++------------------ GNUmakefile | 8 ++--- Makefile | 3 +- README | 42 +++++++++++++++++++++-- attr.c | 4 +-- cancel.c | 58 ++++---------------------------- cleanup.c | 4 +-- condvar.c | 14 ++++---- dll.c | 2 +- exit.c | 42 ++--------------------- global.c | 2 +- implement.h | 50 +++++++++------------------ misc.c | 27 ++------------- mutex.c | 30 ++++------------- private.c | 69 ++++++++++++++++++++++++++++++++------ pthread.def | 3 +- pthread.h | 55 ++++++++++++++++++++---------- rwlock.c | 18 +++++----- sched.c | 2 +- tsd.c | 2 +- 21 files changed, 294 insertions(+), 283 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index a7e61c3..9607dd4 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -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 @@ -207,6 +205,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) --------------------------- diff --git a/ChangeLog b/ChangeLog index 22393ab..433a835 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +2000-08-18 Ross Johnson + + * 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 * All applicable: Change _pthread_ prefix to @@ -116,7 +162,7 @@ 2000-08-03 Ross Johnson - * 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 * 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 (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 Thu Feb 4 10:07:28 1999 Ross Johnson - * 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 Reverse LHS/RHS bitwise assignments. * pthread.h: Remove #include . - (_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 * 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 Fri Oct 23 00:08:09 1998 Ross Johnson - * 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 * 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 * 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 (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 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 @@ -1903,8 +1949,8 @@ Fri Jul 31 00:05:45 1998 Ross Johnson * 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 @@ -1921,7 +1967,7 @@ Thu Jul 30 23:12:45 1998 Ross Johnson 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 Tue Jul 28 14:04:29 1998 Ross Johnson - * 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 * 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 * 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 * 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 * 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 (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 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 diff --git a/Makefile b/Makefile index f8d0b00..976d9f2 100644 --- a/Makefile +++ b/Makefile @@ -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 \ diff --git a/README b/README index 794ba7d..3ad70f9 100644 --- a/README +++ b/README @@ -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 -------------------------------------------------------- diff --git a/attr.c b/attr.c index 84c35a5..9489e70 100644 --- a/attr.c +++ b/attr.c @@ -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; diff --git a/cancel.c b/cancel.c index 3273299..9e5b789 100644 --- a/cancel.c +++ b/cancel.c @@ -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 */ } diff --git a/cleanup.c b/cleanup.c index 971828f..3ba4193 100644 --- a/cleanup.c +++ b/cleanup.c @@ -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 diff --git a/condvar.c b/condvar.c index 0f74c9f..87e62d8 100644 --- a/condvar.c +++ b/condvar.c @@ -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; } diff --git a/dll.c b/dll.c index 7b0253f..15c1bda 100644 --- a/dll.c +++ b/dll.c @@ -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")); diff --git a/exit.c b/exit.c index 146bf7a..2e55e7a 100644 --- a/exit.c +++ b/exit.c @@ -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. */ diff --git a/global.c b/global.c index e55fc5b..a094459 100644 --- a/global.c +++ b/global.c @@ -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" { diff --git a/misc.c b/misc.c index ea38845..08de967 100644 --- a/misc.c +++ b/misc.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. */ diff --git a/mutex.c b/mutex.c index 1ea7aab..3e0e484 100644 --- a/mutex.c +++ b/mutex.c @@ -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 @@ -354,22 +354,6 @@ pthread_mutexattr_destroy (pthread_mutexattr_t * attr) } /* pthread_mutexattr_destroy */ -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); } diff --git a/private.c b/private.c index 2cdccac..0f8a175 100644 --- a/private.c +++ b/private.c @@ -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 ; diff --git a/pthread.h b/pthread.h index a853191..ead9424 100644 --- a/pthread.h +++ b/pthread.h @@ -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); @@ -907,6 +902,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 * @@ -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); @@ -986,13 +1003,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" */ diff --git a/rwlock.c b/rwlock.c index f476b8a..d02461c 100644 --- a/rwlock.c +++ b/rwlock.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); diff --git a/sched.c b/sched.c index a4451ce..0f83a43 100644 --- a/sched.c +++ b/sched.c @@ -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 diff --git a/tsd.c b/tsd.c index 3c06782..491769f 100644 --- a/tsd.c +++ b/tsd.c @@ -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; -- cgit v1.2.3