3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
14 #define is_cw_cancel (mask & cw_cancel)
15 #define is_cw_cancel_self (mask & cw_cancel_self)
16 #define is_cw_sig (mask & cw_sig)
17 #define is_cw_sig_eintr (mask & cw_sig_eintr)
18 #define is_cw_sig_cont (mask & cw_sig_cont)
19 #define is_cw_sig_restart (mask & cw_sig_restart)
21 #define is_cw_sig_handle (mask & (cw_sig | cw_sig_eintr \
22 | cw_sig_cont | cw_sig_restart))
24 LARGE_INTEGER cw_nowait_storage
;
27 cygwait (HANDLE object
, PLARGE_INTEGER timeout
, unsigned mask
)
31 HANDLE wait_objects
[4];
32 pthread_t thread
= pthread::self ();
34 /* Do not change the wait order.
35 The object must have higher priority than the cancel event,
36 because WaitForMultipleObjects will return the smallest index
37 if both objects are signaled. */
39 wait_objects
[num
++] = object
;
41 wait_signal_arrived
thread_waiting (is_cw_sig_handle
, wait_objects
[num
]);
42 debug_only_printf ("object %p, thread waiting %d, signal_arrived %p",
43 object
, (int) thread_waiting
, _my_tls
.signal_arrived
);
46 sig_n
= WAIT_TIMEOUT
+ 1;
48 sig_n
= WAIT_OBJECT_0
+ num
++;
51 if (!is_cw_cancel
|| !pthread::is_good_object (&thread
) ||
52 thread
->cancelstate
== PTHREAD_CANCEL_DISABLE
)
53 cancel_n
= WAIT_TIMEOUT
+ 1;
56 cancel_n
= WAIT_OBJECT_0
+ num
++;
57 wait_objects
[cancel_n
] = thread
->cancel_event
;
62 timeout_n
= WAIT_TIMEOUT
+ 1;
65 timeout_n
= WAIT_OBJECT_0
+ num
++;
66 if (!_my_tls
.locals
.cw_timer
)
67 NtCreateTimer (&_my_tls
.locals
.cw_timer
, TIMER_ALL_ACCESS
, NULL
,
69 NtSetTimer (_my_tls
.locals
.cw_timer
, timeout
, NULL
, NULL
, FALSE
, 0, NULL
);
70 wait_objects
[timeout_n
] = _my_tls
.locals
.cw_timer
;
75 res
= WaitForMultipleObjects (num
, wait_objects
, FALSE
, INFINITE
);
76 debug_only_printf ("res %d", res
);
79 else if (res
== timeout_n
)
81 else if (res
!= sig_n
)
85 int sig
= _my_tls
.current_sig
;
86 if (is_cw_sig_cont
&& sig
== SIGCONT
)
87 _my_tls
.current_sig
= 0;
90 if (is_cw_sig_eintr
|| (is_cw_sig_cont
&& sig
== SIGCONT
))
92 else if (_my_tls
.call_signal_handler () || is_cw_sig_restart
)
94 res
= WAIT_SIGNALED
; /* caller will deal with signals */
101 TIMER_BASIC_INFORMATION tbi
;
103 NtQueryTimer (_my_tls
.locals
.cw_timer
, TimerBasicInformation
, &tbi
,
105 /* if timer expired, TimeRemaining is negative and represents the
106 system uptime when signalled */
107 if (timeout
->QuadPart
< 0LL) {
108 timeout
->QuadPart
= tbi
.SignalState
|| tbi
.TimeRemaining
.QuadPart
< 0LL
109 ? 0LL : tbi
.TimeRemaining
.QuadPart
;
111 NtCancelTimer (_my_tls
.locals
.cw_timer
, NULL
);
114 if (res
== WAIT_CANCELED
&& is_cw_cancel_self
)
115 pthread::static_cancel_self ();