Change pthread::cancelable_wait to just cancelable_wait, throughout.

* thread.h (cw_sig_wait): New enum.
(fast_mutex::lock): Use cancelable_wait with resumable signal.
(cancelable_wait): Change fourth argument to cw_sig_wait enum.
* thread.cc (cancelable_wait): Ditto.  Loop on signal detection if fourth
argument == cw_sig_resume.
This commit is contained in:
Christopher Faylor 2005-06-09 05:11:51 +00:00
parent a63c42932e
commit ed364fa9fb
6 changed files with 70 additions and 48 deletions

View File

@ -1,3 +1,12 @@
2005-06-09 Christopher Faylor <cgf@timesys.com>
Change pthread::cancelable_wait to just cancelable_wait, throughout.
* thread.h (cw_sig_wait): New enum.
(fast_mutex::lock): Use cancelable_wait with resumable signal.
(cancelable_wait): Change fourth argument to cw_sig_wait enum.
* thread.cc (cancelable_wait): Ditto. Loop on signal detection if
fourth argument == cw_sig_resume.
2005-06-08 Christopher Faylor <cgf@timesys.com> 2005-06-08 Christopher Faylor <cgf@timesys.com>
* cygwin.sc: Apparently nonloading sections need to go last. * cygwin.sc: Apparently nonloading sections need to go last.

View File

@ -574,7 +574,7 @@ handle_sigsuspend (sigset_t tempmask)
sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask); sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask);
pthread_testcancel (); pthread_testcancel ();
pthread::cancelable_wait (signal_arrived, INFINITE); cancelable_wait (signal_arrived, INFINITE);
set_sig_errno (EINTR); // Per POSIX set_sig_errno (EINTR); // Per POSIX

View File

@ -88,7 +88,7 @@ nanosleep (const struct timespec *rqtp, struct timespec *rmtp)
DWORD end_time = gtod.dmsecs () + req; DWORD end_time = gtod.dmsecs () + req;
syscall_printf ("nanosleep (%ld)", req); syscall_printf ("nanosleep (%ld)", req);
int rc = pthread::cancelable_wait (signal_arrived, req); int rc = cancelable_wait (signal_arrived, req);
DWORD rem; DWORD rem;
if ((rem = end_time - gtod.dmsecs ()) > HIRES_DELAY_MAX) if ((rem = end_time - gtod.dmsecs ()) > HIRES_DELAY_MAX)
rem = 0; rem = 0;

View File

@ -604,13 +604,13 @@ pthread::static_cancel_self (void)
} }
DWORD DWORD
pthread::cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel, cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel,
const bool do_sig_wait) const enum cw_sig_wait sig_wait)
{ {
DWORD res; DWORD res;
DWORD num = 0; DWORD num = 0;
HANDLE wait_objects[3]; HANDLE wait_objects[3];
pthread_t thread = self (); pthread_t thread = pthread::self ();
/* Do not change the wait order. /* Do not change the wait order.
The object must have higher priority than the cancel event, The object must have higher priority than the cancel event,
@ -618,7 +618,7 @@ pthread::cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel,
if both objects are signaled. */ if both objects are signaled. */
wait_objects[num++] = object; wait_objects[num++] = object;
DWORD cancel_n; DWORD cancel_n;
if (!is_good_object (&thread) || if (!pthread::is_good_object (&thread) ||
thread->cancelstate == PTHREAD_CANCEL_DISABLE) thread->cancelstate == PTHREAD_CANCEL_DISABLE)
cancel_n = (DWORD) -1; cancel_n = (DWORD) -1;
else else
@ -628,7 +628,7 @@ pthread::cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel,
} }
DWORD sig_n; DWORD sig_n;
if (!do_sig_wait || &_my_tls != _main_tls) if (sig_wait == cw_sig_nosig || &_my_tls != _main_tls)
sig_n = (DWORD) -1; sig_n = (DWORD) -1;
else else
{ {
@ -636,14 +636,26 @@ pthread::cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel,
wait_objects[sig_n] = signal_arrived; wait_objects[sig_n] = signal_arrived;
} }
res = WaitForMultipleObjects (num, wait_objects, FALSE, timeout); while (1)
if (res == sig_n - WAIT_OBJECT_0)
res = WAIT_SIGNALED;
else if (res == cancel_n - WAIT_OBJECT_0)
{ {
if (do_cancel) res = WaitForMultipleObjects (num, wait_objects, FALSE, timeout);
pthread::static_cancel_self (); res -= WAIT_OBJECT_0;
res = WAIT_CANCELED; if (res == cancel_n)
{
if (do_cancel)
pthread::static_cancel_self ();
res = WAIT_CANCELED;
}
else if (res != sig_n)
/* all set */;
else if (sig_wait == cw_sig_eintr)
res = WAIT_SIGNALED;
else
{
_my_tls.call_signal_handler ();
continue;
}
break;
} }
return res; return res;
} }
@ -943,7 +955,7 @@ pthread_cond::wait (pthread_mutex_t mutex, DWORD dwMilliseconds)
++mutex->condwaits; ++mutex->condwaits;
mutex->unlock (); mutex->unlock ();
rv = pthread::cancelable_wait (sem_wait, dwMilliseconds, false, true); rv = cancelable_wait (sem_wait, dwMilliseconds, false, cw_sig_eintr);
mtx_out.lock (); mtx_out.lock ();
@ -1777,7 +1789,7 @@ semaphore::_timedwait (const struct timespec *abstime)
waitlength -= tv.tv_sec * 1000 + tv.tv_usec / 1000; waitlength -= tv.tv_sec * 1000 + tv.tv_usec / 1000;
if (waitlength < 0) if (waitlength < 0)
waitlength = 0; waitlength = 0;
switch (pthread::cancelable_wait (win32_obj_id, waitlength, true, true)) switch (cancelable_wait (win32_obj_id, waitlength, true, cw_sig_eintr))
{ {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
currentvalue--; currentvalue--;
@ -1799,7 +1811,7 @@ semaphore::_timedwait (const struct timespec *abstime)
int int
semaphore::_wait () semaphore::_wait ()
{ {
switch (pthread::cancelable_wait (win32_obj_id, INFINITE, true, true)) switch (cancelable_wait (win32_obj_id, INFINITE, true, cw_sig_eintr))
{ {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
currentvalue--; currentvalue--;
@ -2253,31 +2265,24 @@ pthread::join (pthread_t *thread, void **return_val)
(*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED;
(*thread)->mutex.unlock (); (*thread)->mutex.unlock ();
bool loop = false; switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, false, cw_sig_resume))
do {
switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, false, true)) case WAIT_OBJECT_0:
{ if (return_val)
case WAIT_OBJECT_0: *return_val = (*thread)->return_ptr;
if (return_val) delete (*thread);
*return_val = (*thread)->return_ptr; break;
delete (*thread); case WAIT_CANCELED:
break; // set joined thread back to joinable since we got canceled
case WAIT_SIGNALED: (*thread)->joiner = NULL;
_my_tls.call_signal_handler (); (*thread)->attr.joinable = PTHREAD_CREATE_JOINABLE;
loop = true; joiner->cancel_self ();
break; // never reached
case WAIT_CANCELED: break;
// set joined thread back to joinable since we got canceled default:
(*thread)->joiner = NULL; // should never happen
(*thread)->attr.joinable = PTHREAD_CREATE_JOINABLE; return EINVAL;
joiner->cancel_self (); }
// never reached
break;
default:
// should never happen
return EINVAL;
}
while (loop);
} }
return 0; return 0;

View File

@ -24,6 +24,13 @@ details. */
#include <security.h> #include <security.h>
#include <errno.h> #include <errno.h>
enum cw_sig_wait
{
cw_sig_nosig,
cw_sig_eintr,
cw_sig_resume
};
extern "C" extern "C"
{ {
void SetResourceLock (int, int, const char *) __attribute__ ((regparm (3))); void SetResourceLock (int, int, const char *) __attribute__ ((regparm (3)));
@ -31,6 +38,9 @@ void ReleaseResourceLock (int, int, const char *)
__attribute__ ((regparm (3))); __attribute__ ((regparm (3)));
} }
DWORD cancelable_wait (HANDLE, DWORD, const bool = true, const enum cw_sig_wait = cw_sig_nosig)
__attribute__ ((regparm (3)));
class fast_mutex class fast_mutex
{ {
public: public:
@ -59,13 +69,13 @@ public:
void lock () void lock ()
{ {
if (InterlockedIncrement ((long *)&lock_counter) != 1) if (InterlockedIncrement ((long *) &lock_counter) != 1)
WaitForSingleObject (win32_obj_id, INFINITE); cancelable_wait (win32_obj_id, INFINITE, false, cw_sig_resume);
} }
void unlock () void unlock ()
{ {
if (InterlockedDecrement ((long *)&lock_counter)) if (InterlockedDecrement ((long *) &lock_counter))
::ReleaseSemaphore (win32_obj_id, 1, NULL); ::ReleaseSemaphore (win32_obj_id, 1, NULL);
} }
@ -397,8 +407,6 @@ 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, const bool do_sig_wait = false);
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);

View File

@ -80,7 +80,7 @@ wait4 (int intpid, int *status, int options, struct rusage *r)
if ((waitfor = w->ev) == NULL) if ((waitfor = w->ev) == NULL)
goto nochildren; goto nochildren;
res = pthread::cancelable_wait (waitfor, INFINITE); res = cancelable_wait (waitfor, INFINITE);
sigproc_printf ("%d = WaitForSingleObject (...)", res); sigproc_printf ("%d = WaitForSingleObject (...)", res);