Apply pthread_cancel_patch

This commit is contained in:
Thomas Pfaff 2003-01-09 20:57:54 +00:00
parent 72fcbc3ee6
commit 09cbb9d6b7
3 changed files with 71 additions and 13 deletions

View File

@ -1,3 +1,13 @@
2003-01-09 Thomas Pfaff <tpfaff@gmx.net>
* thread.h (WAIT_CANCELED): New define.
(pthread::cancelable_wait): New static method.
* thread.cc (pthread::cancelable_wait): Implement.
(semaphore::Wait): Wait on semaphore and thread cancellation.
(pthread::join): Wait on joined thread and thread cancellation.
(semaphore::wait): Add testcancel to check for thread
cancellation even if the semaphore is available.
2003-01-09 Thomas Pfaff <tpfaff@gmx.net> 2003-01-09 Thomas Pfaff <tpfaff@gmx.net>
* include/pthread.h: Add define for errorchecking mutexes. * include/pthread.h: Add define for errorchecking mutexes.

View File

@ -471,7 +471,7 @@ pwrite ()
read () read ()
readv () readv ()
select () select ()
sem_wait () *sem_wait ()
sigpause () sigpause ()
sigsuspend () sigsuspend ()
sigtimedwait () sigtimedwait ()
@ -632,6 +632,28 @@ pthread::static_cancel_self (void)
} }
DWORD pthread::cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel)
{
DWORD res;
HANDLE wait_objects[2];
pthread_t thread = self ();
if (!isGoodObject (&thread) || thread->cancelstate == PTHREAD_CANCEL_DISABLE)
return WaitForSingleObject (object, timeout);
// Do not change the wait order
// The object must have higher priority than the cancel event,
// because WaitForMultipleObjects will return the smallest index
// if both objects are signaled
wait_objects[0] = object;
wait_objects[1] = thread->cancel_event;
res = WaitForMultipleObjects (2, wait_objects, FALSE, timeout);
if (do_cancel && res == WAIT_CANCELED)
pthread::static_cancel_self ();
return res;
}
int int
pthread::setcancelstate (int state, int *oldstate) pthread::setcancelstate (int state, int *oldstate)
{ {
@ -1390,8 +1412,15 @@ semaphore::TryWait ()
void void
semaphore::Wait () semaphore::Wait ()
{ {
WaitForSingleObject (win32_obj_id, INFINITE); switch (pthread::cancelable_wait (win32_obj_id, INFINITE))
currentvalue--; {
case WAIT_OBJECT_0:
currentvalue--;
break;
default:
debug_printf ("cancelable_wait failed. %E");
return;
}
} }
void void
@ -1850,14 +1879,15 @@ pthread::join (pthread_t *thread, void **return_val)
{ {
pthread_t joiner = self (); pthread_t joiner = self ();
if (!isGoodObject (&joiner)) joiner->testcancel ();
return EINVAL;
// Initialize return val with NULL // Initialize return val with NULL
if (return_val) if (return_val)
*return_val = NULL; *return_val = NULL;
/* FIXME: wait on the thread cancellation event as well - we are a cancellation point*/ if (!isGoodObject (&joiner))
return EINVAL;
if (!isGoodObject (thread)) if (!isGoodObject (thread))
return ESRCH; return ESRCH;
@ -1876,14 +1906,26 @@ pthread::join (pthread_t *thread, void **return_val)
(*thread)->joiner = joiner; (*thread)->joiner = joiner;
(*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
(*thread)->mutex.UnLock (); (*thread)->mutex.UnLock ();
WaitForSingleObject ((*thread)->win32_obj_id, INFINITE);
if (return_val)
*return_val = (*thread)->return_ptr;
// cleanup
delete (*thread);
} /* End if */
pthread_testcancel (); switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, false))
{
case WAIT_OBJECT_0:
if (return_val)
*return_val = (*thread)->return_ptr;
delete (*thread);
break;
case WAIT_CANCELED:
// set joined thread back to joinable since we got canceled
(*thread)->joiner = NULL;
(*thread)->attr.joinable = PTHREAD_CREATE_JOINABLE;
joiner->cancel_self ();
// never reached
break;
default:
// should never happen
return EINVAL;
}
}
return 0; return 0;
} }
@ -2629,6 +2671,8 @@ semaphore::destroy (sem_t *sem)
int int
semaphore::wait (sem_t *sem) semaphore::wait (sem_t *sem)
{ {
pthread_testcancel ();
if (!isGoodObject (sem)) if (!isGoodObject (sem))
{ {
set_errno (EINVAL); set_errno (EINVAL);

View File

@ -332,6 +332,8 @@ private:
static nativeMutex mutexInitializationLock; static nativeMutex mutexInitializationLock;
}; };
#define WAIT_CANCELED (WAIT_OBJECT_0 + 1)
class pthread:public verifyable_object class pthread:public verifyable_object
{ {
public: public:
@ -379,6 +381,8 @@ public:
virtual void testcancel (); virtual void testcancel ();
static void static_cancel_self (); static void static_cancel_self ();
static DWORD cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel = true);
virtual int setcancelstate (int state, int *oldstate); virtual int setcancelstate (int state, int *oldstate);
virtual int setcanceltype (int type, int *oldtype); virtual int setcanceltype (int type, int *oldtype);