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) |