diff options
author | Yaakov Selkowitz <yselkowi@redhat.com> | 2011-08-03 20:40:48 +0400 |
---|---|---|
committer | Yaakov Selkowitz <yselkowi@redhat.com> | 2011-08-03 20:40:48 +0400 |
commit | f0968c1e7eda1e949a938be187c631ff5ae868db (patch) | |
tree | c13d8c0da29e5db75a29e6a6b86de6e0e9fb6ed7 /winsup/cygwin/thread.cc | |
parent | 529aa781b65f8020f93551fc4989147f489395ba (diff) |
* cygtls.h (struct _local_storage): Add cw_timer member.
* cygtls.cc (_cygtls::init_thread): Initialize locals.cw_timer.
(_cygtls::fixup_after_fork): Ditto.
* tlsoffsets.h: Regenerate.
* ntdll.h (enum _TIMER_INFORMATION_CLASS): Define.
(struct _TIMER_BASIC_INFORMATION): Define.
(NtQueryTimer): Declare function.
* thread.h (cancelable_wait): Change timeout argument to
PLARGE_INTEGER and provide NULL default.
(fast_mutex::lock): Adjust accordingly.
(pthread_cond::wait): Change timeout argument to PLARGE_INTEGER
and default to NULL.
* thread.cc (cancelable_wait): Change timeout argument to
PLARGE_INTEGER. Initialize _cygtls.locals.cw_timer if needed.
Use NT waitable timers for handling timeout. Return remaining time
to timeout argument if timeout was relative.
(pthread_cond::wait): Change timeout argument to PLARGE_INTEGER.
Adjust to change in cancelable_wait.
(pthread_mutex::lock): Adjust to change in cancelable_wait.
(pthread_spinlock::lock): Ditto.
(pthread::join): Ditto.
(__pthread_cond_dowait): Change waitlength argument to PLARGE_INTEGER.
Adjust to changes in cancelable_wait and pthread_cond::wait.
(pthread_cond_timedwait): Adjust to change in __pthread_cond_dowait.
(pthread_cond_wait): Ditto.
(semaphore::_timedwait): Adjust to change in cancelable_wait.
(semaphore::_wait): Ditto.
* exceptions.cc (handle_sigsuspend): Ditto.
* signal.cc (nanosleep): Ditto.
* wait.cc (wait4): Ditto. Fix copyright dates.
* times.cc (FACTOR, NSPERSEC): Move from here...
* hires.h (FACTOR, NSPERSEC): ...to here.
Diffstat (limited to 'winsup/cygwin/thread.cc')
-rw-r--r-- | winsup/cygwin/thread.cc | 96 |
1 files changed, 69 insertions, 27 deletions
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 40dd5e4d1..40526e6f8 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -906,13 +906,13 @@ pthread::static_cancel_self () } DWORD -cancelable_wait (HANDLE object, DWORD timeout, +cancelable_wait (HANDLE object, PLARGE_INTEGER timeout, const cw_cancel_action cancel_action, const enum cw_sig_wait sig_wait) { DWORD res; DWORD num = 0; - HANDLE wait_objects[3]; + HANDLE wait_objects[4]; pthread_t thread = pthread::self (); /* Do not change the wait order. @@ -939,15 +939,30 @@ cancelable_wait (HANDLE object, DWORD timeout, wait_objects[sig_n] = signal_arrived; } + DWORD timeout_n; + if (!timeout) + timeout_n = WAIT_TIMEOUT + 1; + else + { + timeout_n = WAIT_OBJECT_0 + num++; + if (!_my_tls.locals.cw_timer) + NtCreateTimer (&_my_tls.locals.cw_timer, TIMER_ALL_ACCESS, NULL, + NotificationTimer); + NtSetTimer (_my_tls.locals.cw_timer, timeout, NULL, NULL, FALSE, 0, NULL); + wait_objects[timeout_n] = _my_tls.locals.cw_timer; + } + while (1) { - res = WaitForMultipleObjects (num, wait_objects, FALSE, timeout); + res = WaitForMultipleObjects (num, wait_objects, FALSE, INFINITE); if (res == cancel_n) { if (cancel_action == cw_cancel_self) pthread::static_cancel_self (); res = WAIT_CANCELED; } + else if (res == timeout_n) + res = WAIT_TIMEOUT; else if (res != sig_n) /* all set */; else if (sig_wait == cw_sig_eintr) @@ -959,6 +974,21 @@ cancelable_wait (HANDLE object, DWORD timeout, } break; } + + if (timeout) + { + const size_t sizeof_tbi = sizeof (TIMER_BASIC_INFORMATION); + PTIMER_BASIC_INFORMATION tbi = (PTIMER_BASIC_INFORMATION) malloc (sizeof_tbi); + + NtQueryTimer (_my_tls.locals.cw_timer, TimerBasicInformation, tbi, + sizeof_tbi, NULL); + /* if timer expired, TimeRemaining is negative and represents the + system uptime when signalled */ + if (timeout->QuadPart < 0LL) + timeout->QuadPart = tbi->SignalState ? 0LL : tbi->TimeRemaining.QuadPart; + NtCancelTimer (_my_tls.locals.cw_timer, NULL); + } + return res; } @@ -1228,7 +1258,7 @@ pthread_cond::unblock (const bool all) } int -pthread_cond::wait (pthread_mutex_t mutex, DWORD dwMilliseconds) +pthread_cond::wait (pthread_mutex_t mutex, PLARGE_INTEGER timeout) { DWORD rv; @@ -1249,7 +1279,7 @@ pthread_cond::wait (pthread_mutex_t mutex, DWORD dwMilliseconds) ++mutex->condwaits; mutex->unlock (); - rv = cancelable_wait (sem_wait, dwMilliseconds, cw_no_cancel_self, cw_sig_eintr); + rv = cancelable_wait (sem_wait, timeout, cw_no_cancel_self, cw_sig_eintr); mtx_out.lock (); @@ -1764,7 +1794,7 @@ pthread_mutex::lock () else if (type == PTHREAD_MUTEX_NORMAL /* potentially causes deadlock */ || !pthread::equal (owner, self)) { - cancelable_wait (win32_obj_id, INFINITE, cw_no_cancel, cw_sig_resume); + cancelable_wait (win32_obj_id, NULL, cw_no_cancel, cw_sig_resume); set_owner (self); } else @@ -1899,8 +1929,13 @@ pthread_spinlock::lock () } else if (pthread::equal (owner, self)) result = EDEADLK; - else /* Minimal timeout to minimize CPU usage while still spinning. */ - cancelable_wait (win32_obj_id, 1L, cw_no_cancel, cw_sig_resume); + else + { + /* Minimal timeout to minimize CPU usage while still spinning. */ + LARGE_INTEGER timeout; + timeout.QuadPart = -10000LL; + cancelable_wait (win32_obj_id, &timeout, cw_no_cancel, cw_sig_resume); + } } while (result == -1); pthread_printf ("spinlock %p, self %p, owner %p", this, self, owner); @@ -2377,7 +2412,7 @@ pthread::join (pthread_t *thread, void **return_val) (*thread)->attr.joinable = PTHREAD_CREATE_DETACHED; (*thread)->mutex.unlock (); - switch (cancelable_wait ((*thread)->win32_obj_id, INFINITE, cw_no_cancel_self, cw_sig_resume)) + switch (cancelable_wait ((*thread)->win32_obj_id, NULL, cw_no_cancel_self, cw_sig_resume)) { case WAIT_OBJECT_0: if (return_val) @@ -2702,7 +2737,7 @@ pthread_cond_signal (pthread_cond_t *cond) static int __pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex, - DWORD waitlength) + PLARGE_INTEGER waitlength) { if (!pthread_mutex::is_good_object (mutex)) return EINVAL; @@ -2722,7 +2757,7 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { struct timespec tp; - DWORD waitlength; + LARGE_INTEGER timeout; myfault efault; if (efault.faulted ()) @@ -2738,17 +2773,27 @@ pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, clock_gettime ((*cond)->clock_id, &tp); - /* Check for immediate timeout before converting to microseconds, since - the resulting value can easily overflow long. This also allows to - evaluate microseconds directly in DWORD. */ + /* Check for immediate timeout before converting */ if (tp.tv_sec > abstime->tv_sec || (tp.tv_sec == abstime->tv_sec && tp.tv_nsec > abstime->tv_nsec)) return ETIMEDOUT; - waitlength = (abstime->tv_sec - tp.tv_sec) * 1000; - waitlength += (abstime->tv_nsec - tp.tv_nsec) / 1000000; - return __pthread_cond_dowait (cond, mutex, waitlength); + timeout.QuadPart = abstime->tv_sec * NSPERSEC + + (abstime->tv_nsec + 99LL) / 100LL; + + switch ((*cond)->clock_id) + { + case CLOCK_REALTIME: + timeout.QuadPart += FACTOR; + break; + default: + /* other clocks must be handled as relative timeout */ + timeout.QuadPart -= tp.tv_sec * NSPERSEC + tp.tv_nsec / 100LL; + timeout.QuadPart *= -1LL; + break; + } + return __pthread_cond_dowait (cond, mutex, &timeout); } extern "C" int @@ -2756,7 +2801,7 @@ pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) { pthread_testcancel (); - return __pthread_cond_dowait (cond, mutex, INFINITE); + return __pthread_cond_dowait (cond, mutex, NULL); } extern "C" int @@ -3439,8 +3484,7 @@ semaphore::_trywait () int semaphore::_timedwait (const struct timespec *abstime) { - struct timeval tv; - long waitlength; + LARGE_INTEGER timeout; myfault efault; if (efault.faulted ()) @@ -3453,12 +3497,10 @@ semaphore::_timedwait (const struct timespec *abstime) return -1; } - gettimeofday (&tv, NULL); - waitlength = abstime->tv_sec * 1000 + abstime->tv_nsec / (1000 * 1000); - waitlength -= tv.tv_sec * 1000 + tv.tv_usec / 1000; - if (waitlength < 0) - waitlength = 0; - switch (cancelable_wait (win32_obj_id, waitlength, cw_cancel_self, cw_sig_eintr)) + timeout.QuadPart = abstime->tv_sec * NSPERSEC + + (abstime->tv_nsec + 99) / 100 + FACTOR; + + switch (cancelable_wait (win32_obj_id, &timeout, cw_cancel_self, cw_sig_eintr)) { case WAIT_OBJECT_0: currentvalue--; @@ -3480,7 +3522,7 @@ semaphore::_timedwait (const struct timespec *abstime) int semaphore::_wait () { - switch (cancelable_wait (win32_obj_id, INFINITE, cw_cancel_self, cw_sig_eintr)) + switch (cancelable_wait (win32_obj_id, NULL, cw_cancel_self, cw_sig_eintr)) { case WAIT_OBJECT_0: currentvalue--; |