]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/cygwait.cc
* DevNotes: Add entry cgf-000013.
[newlib-cygwin.git] / winsup / cygwin / cygwait.cc
CommitLineData
4ae63783
CF
1/* cygwait.h
2
3 Copyright 2011, 2012 Red Hat, Inc.
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11#include "winsup.h"
12#include "sigproc.h"
13#include "cygwait.h"
14#include "ntdll.h"
15
16#define is_cw_cancel (mask & cw_cancel)
17#define is_cw_cancel_self (mask & cw_cancel_self)
18#define is_cw_sig (mask & cw_sig)
19#define is_cw_sig_eintr (mask & cw_sig_eintr)
20#define is_cw_sig_return (mask & cw_sig_return)
21
22#define is_cw_sig_handle (mask & (is_cw_sig | is_cw_sig_eintr))
23
962f9a2c
CF
24LARGE_INTEGER cw_nowait_storage;
25
4ae63783
CF
26DWORD
27cancelable_wait (HANDLE object, PLARGE_INTEGER timeout, unsigned mask)
28{
29 DWORD res;
30 DWORD num = 0;
31 HANDLE wait_objects[4];
32 pthread_t thread = pthread::self ();
33
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. */
38 if (object)
39 wait_objects[num++] = object;
40
962f9a2c
CF
41 set_thread_waiting thread_waiting (is_cw_sig_handle, wait_objects[num]);
42debug_printf ("thread waiting %d, signal_arrived %p", (int) thread_waiting, _my_tls.signal_arrived);
4ae63783 43 DWORD sig_n;
962f9a2c 44 if (!thread_waiting)
4ae63783
CF
45 sig_n = WAIT_TIMEOUT + 1;
46 else
962f9a2c 47 sig_n = WAIT_OBJECT_0 + num++;
4ae63783
CF
48
49 DWORD cancel_n;
50 if (!is_cw_cancel || !pthread::is_good_object (&thread) ||
51 thread->cancelstate == PTHREAD_CANCEL_DISABLE)
52 cancel_n = WAIT_TIMEOUT + 1;
53 else
54 {
55 cancel_n = WAIT_OBJECT_0 + num++;
56 wait_objects[cancel_n] = thread->cancel_event;
57 }
58
59 DWORD timeout_n;
60 if (!timeout)
61 timeout_n = WAIT_TIMEOUT + 1;
62 else
63 {
64 timeout_n = WAIT_OBJECT_0 + num++;
65 if (!_my_tls.locals.cw_timer)
66 NtCreateTimer (&_my_tls.locals.cw_timer, TIMER_ALL_ACCESS, NULL,
67 NotificationTimer);
68 NtSetTimer (_my_tls.locals.cw_timer, timeout, NULL, NULL, FALSE, 0, NULL);
69 wait_objects[timeout_n] = _my_tls.locals.cw_timer;
70 }
71
72 while (1)
73 {
74 res = WaitForMultipleObjects (num, wait_objects, FALSE, INFINITE);
75 if (res == cancel_n)
6ec05d23 76 res = WAIT_CANCELED;
4ae63783
CF
77 else if (res == timeout_n)
78 res = WAIT_TIMEOUT;
79 else if (res != sig_n)
80 /* all set */;
81 else if (is_cw_sig_eintr)
6ec05d23 82 res = WAIT_SIGNALED; /* caller will deal with signals */
962f9a2c 83 else if (_my_tls.call_signal_handler ())
2addde8c 84 continue;
4ae63783
CF
85 break;
86 }
87
88 if (timeout)
89 {
90 TIMER_BASIC_INFORMATION tbi;
91
92 NtQueryTimer (_my_tls.locals.cw_timer, TimerBasicInformation, &tbi,
93 sizeof tbi, NULL);
94 /* if timer expired, TimeRemaining is negative and represents the
95 system uptime when signalled */
96 if (timeout->QuadPart < 0LL)
97 timeout->QuadPart = tbi.SignalState ? 0LL : tbi.TimeRemaining.QuadPart;
98 NtCancelTimer (_my_tls.locals.cw_timer, NULL);
99 }
100
6ec05d23
CF
101 if (res == WAIT_CANCELED && is_cw_cancel_self)
102 pthread::static_cancel_self ();
103
4ae63783
CF
104 return res;
105}
This page took 0.033863 seconds and 5 git commands to generate.