Permalink
Browse files

*** empty log message ***

  • Loading branch information...
1 parent 743c828 commit 46b13ac2aa0acfd949a7abeff8ea7091ff706091 rpj committed Mar 9, 2011
Showing with 37 additions and 47 deletions.
  1. +9 −1 BUGS
  2. +8 −0 README
  3. +1 −1 global.c
  4. +1 −25 implement.h
  5. +2 −2 pthread_cond_wait.c
  6. +4 −4 pthread_once.c
  7. +2 −2 pthread_rwlock_timedwrlock.c
  8. +2 −2 pthread_rwlock_wrlock.c
  9. +0 −2 ptw32_threadStart.c
  10. +2 −2 sem_timedwait.c
  11. +2 −2 sem_wait.c
  12. +1 −1 tests/Bmakefile
  13. +1 −1 tests/GNUmakefile
  14. +1 −1 tests/Makefile
  15. +1 −1 tests/Wmakefile
View
10 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
View
8 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
--------------
View
@@ -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;
/*
View
@@ -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; \
View
@@ -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
View
@@ -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,15 +63,15 @@ 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
pthread_cleanup_push(ptw32_once_on_init_cancel, (void *)&node);
(*init_routine)();
pthread_cleanup_pop(0);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && _MSC_VER < 800
#pragma inline_depth()
#endif
@@ -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
View
@@ -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
View
@@ -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;
}
}
View
@@ -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
View
@@ -139,15 +139,15 @@ 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 */
pthread_cleanup_push(ptw32_sem_wait_cleanup, (void *) s);
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
}
View
@@ -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
View
@@ -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)
View
@@ -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
View
@@ -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)

0 comments on commit 46b13ac

Please sign in to comment.