diff options
| -rw-r--r-- | BUGS | 10 | ||||
| -rw-r--r-- | README | 8 | ||||
| -rw-r--r-- | global.c | 2 | ||||
| -rw-r--r-- | implement.h | 26 | ||||
| -rw-r--r-- | pthread_cond_wait.c | 4 | ||||
| -rw-r--r-- | pthread_once.c | 8 | ||||
| -rw-r--r-- | pthread_rwlock_timedwrlock.c | 4 | ||||
| -rw-r--r-- | pthread_rwlock_wrlock.c | 4 | ||||
| -rw-r--r-- | ptw32_threadStart.c | 2 | ||||
| -rw-r--r-- | sem_timedwait.c | 4 | ||||
| -rw-r--r-- | sem_wait.c | 4 | ||||
| -rw-r--r-- | tests/Bmakefile | 2 | ||||
| -rw-r--r-- | tests/GNUmakefile | 2 | ||||
| -rw-r--r-- | tests/Makefile | 2 | ||||
| -rw-r--r-- | tests/Wmakefile | 2 | 
15 files changed, 37 insertions, 47 deletions
@@ -22,9 +22,17 @@ Known bugs     Workaround: avoid using pthread_exit() in C++ applications. Exit     threads by dropping through the end of the thread routine. -2. Cancellation problems in optimised code +2. Cancellation problems in C++ builds     - Milan Gardian +   [Note: It's not clear if this problem isn't simply due to the context +   switch in pthread_cancel() which occurs unless the QueueUserAPCEx +   library and driver are installed and used. Just like setjmp/longjmp, +   this is probably not going to work well in C++. In any case, unless for +   some very unusual reason you really must use the C++ build then please +   use the C build pthreadVC2.dll or pthreadGC2.dll, i.e. for C++ +   applications.] +     This is suspected to be a compiler bug in VC6.0, and also seen in     VC7.0 and VS .NET 2003. The GNU C++ compiler does not have a problem     with this, and it has been reported that the Intel C++ 8.1 compiler @@ -31,6 +31,10 @@ MSVC or GNU C (MinGW32 MSys development kit)  	To build from source.  QueueUserAPCEx by Panagiotis E. Hadjidoukas +	To support any thread cancelation in C++ library builds or +	to support cancelation of blocked threads in any build. +	This library is not required otherwise. +  	For true async cancelation of threads (including blocked threads).  	This is a DLL and Windows driver that provides pre-emptive APC  	by forcing threads into an alertable state when the APC is queued. @@ -47,6 +51,10 @@ QueueUserAPCEx by Panagiotis E. Hadjidoukas  	are runnable. The simulated async cancellation cannot cancel blocked  	threads. +	QueueUserAPCEx is required in C++ builds to avoid longjmp-style +	context switching in pthread_cancel(), which will otherwise affect +	exception handling and proper application behaviour. +  Library naming  -------------- @@ -49,7 +49,7 @@ pthread_cond_t ptw32_cond_list_tail = NULL;  int ptw32_concurrency = 0; -/* What features have been auto-detaected */ +/* What features have been auto-detected */  int ptw32_features = 0;  /*  diff --git a/implement.h b/implement.h index ef0943f..aaad665 100644 --- a/implement.h +++ b/implement.h @@ -229,7 +229,7 @@ struct pthread_mutexattr_t_   * In this implementation, when a spinlock is initialised,   * the number of cpus available to the process is checked.   * If there is only one cpu then "interlock" is set equal to - * PTW32_SPIN_USE_MUTEX and u.mutex is a initialised mutex. + * PTW32_SPIN_USE_MUTEX and u.mutex is an initialised mutex.   * If the number of cpus is greater than 1 then "interlock"   * is set equal to PTW32_SPIN_UNLOCKED and the number is   * stored in u.cpus. This arrangement allows the spinlock @@ -721,18 +721,6 @@ extern "C"          :"memory", "cc");                                                  \        _result;                                                             \      }) -/* - * Faster version of XCHG for uni-processor systems because - * it doesn't lock the bus. If an interrupt or context switch - * occurs between the movl and the cmpxchgl then the value in - * 'location' may have changed, in which case we will loop - * back to do the movl again. - * - * Tests show that this routine has almost identical timing - * to Win32's InterlockedExchange(), and is much faster than - * using an inlined 'xchg' instruction, so Win32 is probably - * doing something similar to this (on UP systems). - */  # define PTW32_INTERLOCKED_EXCHANGE(location, value)                       \      ({                                                                     \        __typeof (value) _result;                                            \ @@ -793,18 +781,6 @@ extern "C"          :"memory", "cc");                                                  \        _result;                                                             \      }) -/* - * Faster version of XCHG for uni-processor systems because - * it doesn't lock the bus. If an interrupt or context switch - * occurs between the movl and the cmpxchgl then the value in - * 'location' may have changed, in which case we will loop - * back to do the movl again. - * - * Tests show that this routine has almost identical timing - * to Win32's InterlockedExchange(), and is much faster than - * using an inlined 'xchg' instruction, so Win32 is probably - * doing something similar to this (on UP systems). - */  # define PTW32_INTERLOCKED_EXCHANGE64(location, value)                     \      ({                                                                     \        __typeof (value) _result;                                            \ diff --git a/pthread_cond_wait.c b/pthread_cond_wait.c index 5511c58..ddeb1a2 100644 --- a/pthread_cond_wait.c +++ b/pthread_cond_wait.c @@ -401,7 +401,7 @@ ptw32_cond_timedwait (pthread_cond_t * cond,    cleanup_args.cv = cv;    cleanup_args.resultPtr = &result; -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 800  #pragma inline_depth(0)  #endif    pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *) &cleanup_args); @@ -438,7 +438,7 @@ ptw32_cond_timedwait (pthread_cond_t * cond,     * Always cleanup     */    pthread_cleanup_pop (1); -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 800  #pragma inline_depth()  #endif diff --git a/pthread_once.c b/pthread_once.c index 79e4dbc..f5998fa 100644 --- a/pthread_once.c +++ b/pthread_once.c @@ -42,8 +42,8 @@ static void PTW32_CDECL  ptw32_once_on_init_cancel (void * arg)  {    /* when the initing thread is cancelled we have to release the lock */ -  ptw32_mcs_local_node_t *node = (ptw32_mcs_local_node_t *)arg; -  ptw32_mcs_lock_release(node); +  ptw32_mcs_local_node_t* nodePtr = (ptw32_mcs_local_node_t *)arg; +  ptw32_mcs_lock_release(nodePtr);  }  int @@ -63,7 +63,7 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void))        if (!once_control->done)  	{ -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 800  #pragma inline_depth(0)  #endif @@ -71,7 +71,7 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void))  	  (*init_routine)();  	  pthread_cleanup_pop(0); -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 800  #pragma inline_depth()  #endif diff --git a/pthread_rwlock_timedwrlock.c b/pthread_rwlock_timedwrlock.c index 5de1e48..36f7e41 100644 --- a/pthread_rwlock_timedwrlock.c +++ b/pthread_rwlock_timedwrlock.c @@ -104,7 +104,7 @@ pthread_rwlock_timedwrlock (pthread_rwlock_t * rwlock,  	   * This routine may be a cancelation point  	   * according to POSIX 1003.1j section 18.1.2.  	   */ -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 800  #pragma inline_depth(0)  #endif  	  pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl); @@ -119,7 +119,7 @@ pthread_rwlock_timedwrlock (pthread_rwlock_t * rwlock,  	  while (result == 0 && rwl->nCompletedSharedAccessCount < 0);  	  pthread_cleanup_pop ((result != 0) ? 1 : 0); -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 800  #pragma inline_depth()  #endif diff --git a/pthread_rwlock_wrlock.c b/pthread_rwlock_wrlock.c index 174fcbc..170ec1a 100644 --- a/pthread_rwlock_wrlock.c +++ b/pthread_rwlock_wrlock.c @@ -100,7 +100,7 @@ pthread_rwlock_wrlock (pthread_rwlock_t * rwlock)  	   * This routine may be a cancelation point  	   * according to POSIX 1003.1j section 18.1.2.  	   */ -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 800  #pragma inline_depth(0)  #endif  	  pthread_cleanup_push (ptw32_rwlock_cancelwrwait, (void *) rwl); @@ -113,7 +113,7 @@ pthread_rwlock_wrlock (pthread_rwlock_t * rwlock)  	  while (result == 0 && rwl->nCompletedSharedAccessCount < 0);  	  pthread_cleanup_pop ((result != 0) ? 1 : 0); -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 800  #pragma inline_depth()  #endif diff --git a/ptw32_threadStart.c b/ptw32_threadStart.c index 3bc7ede..c485d16 100644 --- a/ptw32_threadStart.c +++ b/ptw32_threadStart.c @@ -268,7 +268,6 @@ ptw32_threadStart (void *vthreadParms)         * ptw32_terminate() will be called if there is no user         * supplied function.         */ -        terminate_function  	term_func = set_terminate (0);        set_terminate (term_func); @@ -277,7 +276,6 @@ ptw32_threadStart (void *vthreadParms)  	{  	  term_func ();  	} -        throw;      }    } diff --git a/sem_timedwait.c b/sem_timedwait.c index 52146b4..1db6217 100644 --- a/sem_timedwait.c +++ b/sem_timedwait.c @@ -185,7 +185,7 @@ sem_timedwait (sem_t * sem, const struct timespec *abstime)  	      cleanup_args.sem = s;  	      cleanup_args.resultPtr = &result; -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 800  #pragma inline_depth(0)  #endif  	      /* Must wait */ @@ -195,7 +195,7 @@ sem_timedwait (sem_t * sem, const struct timespec *abstime)  #endif  	      result = pthreadCancelableTimedWait (s->sem, milliseconds);  	      pthread_cleanup_pop(result); -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 800  #pragma inline_depth()  #endif @@ -139,7 +139,7 @@ sem_wait (sem_t * sem)  	  if (v < 0)  	    { -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 800  #pragma inline_depth(0)  #endif  	      /* Must wait */ @@ -147,7 +147,7 @@ sem_wait (sem_t * sem)  	      result = pthreadCancelableWait (s->sem);  	      /* Cleanup if we're canceled or on any other error */  	      pthread_cleanup_pop(result); -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 800  #pragma inline_depth()  #endif  	    } diff --git a/tests/Bmakefile b/tests/Bmakefile index c6cbc41..27228ad 100644 --- a/tests/Bmakefile +++ b/tests/Bmakefile @@ -41,7 +41,7 @@ TOUCH	= echo Passed >  ECHO	= @echo  # The next path is relative to $BUILD_DIR -QAPC	= ..\QueueUserAPCEx\User\quserex.dll +QAPC	= # ..\QueueUserAPCEx\User\quserex.dll  CPHDR	= pthread.h semaphore.h sched.h diff --git a/tests/GNUmakefile b/tests/GNUmakefile index 159e376..d90fe79 100644 --- a/tests/GNUmakefile +++ b/tests/GNUmakefile @@ -77,7 +77,7 @@ HDR	= pthread.h semaphore.h sched.h  LIB	= libpthread$(GCX).a  DLL	= pthread$(GCX).dll  # The next path is relative to $BUILD_DIR -QAPC	= ../QueueUserAPCEx/User/quserex.dll +QAPC	=  # ../QueueUserAPCEx/User/quserex.dll  COPYFILES	= $(HDR) $(LIB) $(DLL) $(QAPC) diff --git a/tests/Makefile b/tests/Makefile index aef83c2..606f1d4 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -41,7 +41,7 @@ TOUCH	= echo Passed >  ECHO	= @echo  # The next path is relative to $BUILD_DIR -QAPC	= ..\QueueUserAPCEx\User\quserex.dll +QAPC	= # ..\QueueUserAPCEx\User\quserex.dll  CPHDR	= pthread.h semaphore.h sched.h diff --git a/tests/Wmakefile b/tests/Wmakefile index a4b64a3..fb988e3 100644 --- a/tests/Wmakefile +++ b/tests/Wmakefile @@ -69,7 +69,7 @@ INCLUDES= -i=.  BUILD_DIR=..  # The next path is relative to $BUILD_DIR -QAPC	= ..\QueueUserAPCEx\User\quserex.dll +QAPC	= # ..\QueueUserAPCEx\User\quserex.dll  COPYFILES	= $(CPHDR) $(CPLIB) $(CPDLL) $(QAPC)  | 
