diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f7c908c5a..6b0a04d2c 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,12 @@ +2005-06-09 Christopher Faylor + + 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 * cygwin.sc: Apparently nonloading sections need to go last. diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index b886e3460..6e44b5b21 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -574,7 +574,7 @@ handle_sigsuspend (sigset_t tempmask) sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask); pthread_testcancel (); - pthread::cancelable_wait (signal_arrived, INFINITE); + cancelable_wait (signal_arrived, INFINITE); set_sig_errno (EINTR); // Per POSIX diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc index 1808b2428..935083ce1 100644 --- a/winsup/cygwin/signal.cc +++ b/winsup/cygwin/signal.cc @@ -88,7 +88,7 @@ nanosleep (const struct timespec *rqtp, struct timespec *rmtp) DWORD end_time = gtod.dmsecs () + req; syscall_printf ("nanosleep (%ld)", req); - int rc = pthread::cancelable_wait (signal_arrived, req); + int rc = cancelable_wait (signal_arrived, req); DWORD rem; if ((rem = end_time - gtod.dmsecs ()) > HIRES_DELAY_MAX) rem = 0; diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index e2ffe8e12..9a3c7af48 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -604,13 +604,13 @@ pthread::static_cancel_self (void) } DWORD -pthread::cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel, - const bool do_sig_wait) +cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel, + const enum cw_sig_wait sig_wait) { DWORD res; DWORD num = 0; HANDLE wait_objects[3]; - pthread_t thread = self (); + pthread_t thread = pthread::self (); /* Do not change the wait order. 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. */ wait_objects[num++] = object; DWORD cancel_n; - if (!is_good_object (&thread) || + if (!pthread::is_good_object (&thread) || thread->cancelstate == PTHREAD_CANCEL_DISABLE) cancel_n = (DWORD) -1; else @@ -628,7 +628,7 @@ pthread::cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel, } 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; else { @@ -636,14 +636,26 @@ pthread::cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel, wait_objects[sig_n] = signal_arrived; } - res = WaitForMultipleObjects (num, wait_objects, FALSE, timeout); - if (res == sig_n - WAIT_OBJECT_0) - res = WAIT_SIGNALED; - else if (res == cancel_n - WAIT_OBJECT_0) + while (1) { - if (do_cancel) - pthread::static_cancel_self (); - res = WAIT_CANCELED; + res = WaitForMultipleObjects (num, wait_objects, FALSE, timeout); + res -= WAIT_OBJECT_0; + 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; } @@ -943,7 +955,7 @@ pthread_cond::wait (pthread_mutex_t mutex, DWORD dwMilliseconds) ++mutex->condwaits; mutex->unlock (); - rv = pthread::cancelable_wait (sem_wait, dwMilliseconds, false, true); + rv = cancelable_wait (sem_wait, dwMilliseconds, false, cw_sig_eintr); mtx_out.lock (); @@ -1777,7 +1789,7 @@ semaphore::_timedwait (const struct timespec *abstime) waitlength -= tv.tv_sec * 1000 + tv.tv_usec / 1000; if (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: currentvalue--; @@ -1799,7 +1811,7 @@ semaphore::_timedwait (const struct timespec *abstime) int 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: currentvalue--; @@ -2253,31 +2265,24 @@ pthread::join (pthread_t *thread, void **return_val) (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; (*thread)->mutex.unlock (); - bool loop = false; - do - switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, false, true)) - { - case WAIT_OBJECT_0: - if (return_val) - *return_val = (*thread)->return_ptr; - delete (*thread); - break; - case WAIT_SIGNALED: - _my_tls.call_signal_handler (); - loop = true; - 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; - } - while (loop); + switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, false, cw_sig_resume)) + { + 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; diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index 8bd8b2557..6cce1fa4a 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -24,6 +24,13 @@ details. */ #include #include +enum cw_sig_wait +{ + cw_sig_nosig, + cw_sig_eintr, + cw_sig_resume +}; + extern "C" { void SetResourceLock (int, int, const char *) __attribute__ ((regparm (3))); @@ -31,6 +38,9 @@ void ReleaseResourceLock (int, int, const char *) __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 { public: @@ -59,13 +69,13 @@ public: void lock () { - if (InterlockedIncrement ((long *)&lock_counter) != 1) - WaitForSingleObject (win32_obj_id, INFINITE); + if (InterlockedIncrement ((long *) &lock_counter) != 1) + cancelable_wait (win32_obj_id, INFINITE, false, cw_sig_resume); } void unlock () { - if (InterlockedDecrement ((long *)&lock_counter)) + if (InterlockedDecrement ((long *) &lock_counter)) ::ReleaseSemaphore (win32_obj_id, 1, NULL); } @@ -397,8 +407,6 @@ public: virtual void testcancel (); 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 setcanceltype (int type, int *oldtype); diff --git a/winsup/cygwin/wait.cc b/winsup/cygwin/wait.cc index 70febf06d..2a7a94d37 100644 --- a/winsup/cygwin/wait.cc +++ b/winsup/cygwin/wait.cc @@ -80,7 +80,7 @@ wait4 (int intpid, int *status, int options, struct rusage *r) if ((waitfor = w->ev) == NULL) goto nochildren; - res = pthread::cancelable_wait (waitfor, INFINITE); + res = cancelable_wait (waitfor, INFINITE); sigproc_printf ("%d = WaitForSingleObject (...)", res);