summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrpj <rpj>2011-03-09 06:51:54 +0000
committerrpj <rpj>2011-03-09 06:51:54 +0000
commiteb28d5aa00690b67cc27e4bd93d2c4c251987c85 (patch)
tree5db601315a671a52c816006733846008e7d3981c
parent2c51bb3337275e134e8c40db6dd4eea9407c8bca (diff)
*** empty log message ***
-rw-r--r--BUGS10
-rw-r--r--README8
-rw-r--r--global.c2
-rw-r--r--implement.h26
-rw-r--r--pthread_cond_wait.c4
-rw-r--r--pthread_once.c8
-rw-r--r--pthread_rwlock_timedwrlock.c4
-rw-r--r--pthread_rwlock_wrlock.c4
-rw-r--r--ptw32_threadStart.c2
-rw-r--r--sem_timedwait.c4
-rw-r--r--sem_wait.c4
-rw-r--r--tests/Bmakefile2
-rw-r--r--tests/GNUmakefile2
-rw-r--r--tests/Makefile2
-rw-r--r--tests/Wmakefile2
15 files changed, 37 insertions, 47 deletions
diff --git a/BUGS b/BUGS
index 29cee00..285ba4e 100644
--- a/BUGS
+++ b/BUGS
@@ -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
diff --git a/README b/README
index 5649333..553ec71 100644
--- a/README
+++ b/README
@@ -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
--------------
diff --git a/global.c b/global.c
index f423377..420b8e4 100644
--- a/global.c
+++ b/global.c
@@ -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
diff --git a/sem_wait.c b/sem_wait.c
index d39d2b4..eeaae95 100644
--- a/sem_wait.c
+++ b/sem_wait.c
@@ -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)