diff options
author | Christopher Faylor <me@cgf.cx> | 2012-06-18 00:50:24 +0400 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2012-06-18 00:50:24 +0400 |
commit | 4ae63783821bd2114246166957d25b2acd26c875 (patch) | |
tree | 0b7972e9330fa3a3f863621afd18643e485a151f /winsup/cygwin/cygwait.cc | |
parent | d66ef282c2473d7df911e6d7d6ef1fc778777097 (diff) |
Add '#include "cygwait.h"' throughout, where appropriate.
* DevNotes: Add entry cgf-000012.
* Makefile.in (DLL_OFILES): Add cygwait.o.
* sigproc.h: Remove cygwait definitions.
* cygwait.h: New file. Define/declare Cygwin waitfor functions.
* cygwait.cc: Ditto.
* exceptions.cc: Include cygwait.h.
(handle_sigsuspend): Accommodate change in cancelable_wait arguments.
(sigpacket::process): Display thread tls in debugging output.
* fhandler.cc (fhandler_base_overlapped::wait_overlapped): Use symbolic names
for signal and cancel return.
* fhandler_console.cc (fhandler_console::read): Ditto.
(fhandler_dev_dsp::Audio_out::waitforspace): Ditto.
fhandler_dev_dsp::Audio_in::waitfordata): Ditto.
* fhandler_fifo.cc (fhandler_fifo::wait): Ditto.
* fhandler_serial.cc (fhandler_serial::raw_read): Ditto.
* fhandler_tty.cc (fhandler_pty_slave::read): Ditto.
* select.cc (cygwin_select): Ditto.
* wait.cc (wait4): Ditto.
* thread.cc (cancelable_wait): Move definition to cygwait.h.
(pthread_cond::wait): Accommodate change in cancelable_wait arguments.
(pthread_mutex::lock): Ditto.
(pthread_spinlock::lock): Ditto.
(pthread::join): Ditto.
(pthread::thread_init_wrapper): Display tls in debugging output.
(semaphore::_timedwait): Ditto.
* thread.h (cw_sig_wait): Move to cygwait.h.
(cw_cancel_action): Delete.
(cancelable_wait): Move declaration to cygwait.h.
Diffstat (limited to 'winsup/cygwin/cygwait.cc')
-rw-r--r-- | winsup/cygwin/cygwait.cc | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/winsup/cygwin/cygwait.cc b/winsup/cygwin/cygwait.cc new file mode 100644 index 000000000..6e0610da0 --- /dev/null +++ b/winsup/cygwin/cygwait.cc @@ -0,0 +1,108 @@ +/* cygwait.h + + Copyright 2011, 2012 Red Hat, Inc. + + This file is part of Cygwin. + + This software is a copyrighted work licensed under the terms of the + Cygwin license. Please consult the file "CYGWIN_LICENSE" for + details. */ + +#include "winsup.h" +#include "sigproc.h" +#include "cygwait.h" +#include "ntdll.h" + +#define is_cw_cancel (mask & cw_cancel) +#define is_cw_cancel_self (mask & cw_cancel_self) +#define is_cw_sig (mask & cw_sig) +#define is_cw_sig_eintr (mask & cw_sig_eintr) +#define is_cw_sig_return (mask & cw_sig_return) + +#define is_cw_sig_handle (mask & (is_cw_sig | is_cw_sig_eintr)) + +DWORD +cancelable_wait (HANDLE object, PLARGE_INTEGER timeout, unsigned mask) +{ + DWORD res; + DWORD num = 0; + HANDLE wait_objects[4]; + pthread_t thread = pthread::self (); + + /* 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. */ + if (object) + wait_objects[num++] = object; + + DWORD sig_n; + if (!is_cw_sig_handle) + sig_n = WAIT_TIMEOUT + 1; + else + { + sig_n = WAIT_OBJECT_0 + num++; + wait_objects[sig_n] = signal_arrived; + } + + DWORD cancel_n; + if (!is_cw_cancel || !pthread::is_good_object (&thread) || + thread->cancelstate == PTHREAD_CANCEL_DISABLE) + cancel_n = WAIT_TIMEOUT + 1; + else + { + cancel_n = WAIT_OBJECT_0 + num++; + wait_objects[cancel_n] = thread->cancel_event; + } + + 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, INFINITE); + if (res == cancel_n) + { + if (is_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 (is_cw_sig_eintr) + res = WAIT_SIGNALED; + else + { + _my_tls.call_signal_handler (); + continue; + } + break; + } + + if (timeout) + { + TIMER_BASIC_INFORMATION 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; +} |