16
16
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
17
17
│ PERFORMANCE OF THIS SOFTWARE. │
18
18
╚─────────────────────────────────────────────────────────────────────────────*/
19
- #include "libc/assert.h"
20
- #include "libc/calls/calls.h"
21
19
#include "libc/calls/internal.h"
22
- #include "libc/calls/sig.internal.h"
23
20
#include "libc/calls/state.internal.h"
24
- #include "libc/calls/struct/sigaction .h"
21
+ #include "libc/calls/struct/sigset .h"
25
22
#include "libc/calls/struct/sigset.internal.h"
26
23
#include "libc/calls/struct/timespec.h"
27
24
#include "libc/calls/syscall_support-nt.internal.h"
28
- #include "libc/dce.h"
29
- #include "libc/errno.h"
30
25
#include "libc/intrin/atomic.h"
31
26
#include "libc/intrin/fds.h"
32
- #include "libc/intrin/strace.h"
33
- #include "libc/intrin/weaken.h"
34
27
#include "libc/macros.h"
35
- #include "libc/mem/mem.h"
36
28
#include "libc/nt/console.h"
37
29
#include "libc/nt/enum/filetype.h"
38
30
#include "libc/nt/enum/wait.h"
42
34
#include "libc/nt/runtime.h"
43
35
#include "libc/nt/struct/pollfd.h"
44
36
#include "libc/nt/synchronization.h"
45
- #include "libc/nt/thread.h"
46
- #include "libc/nt/thunk/msabi.h"
47
37
#include "libc/nt/time.h"
48
38
#include "libc/nt/winsock.h"
49
- #include "libc/runtime/runtime.h"
50
39
#include "libc/sock/internal.h"
51
40
#include "libc/sock/struct/pollfd.h"
52
- #include "libc/sock/struct/pollfd.internal.h"
53
- #include "libc/stdio/sysparam.h"
54
41
#include "libc/sysv/consts/o.h"
55
- #include "libc/sysv/consts/poll.h"
56
- #include "libc/sysv/consts/sicode.h"
57
- #include "libc/sysv/consts/sig.h"
58
42
#include "libc/sysv/errfuns.h"
59
43
#include "libc/thread/posixthread.internal.h"
60
- #include "libc/thread/tls.h"
61
44
#ifdef __x86_64__
62
45
63
46
#define POLL_INTERVAL_MS 10
75
58
#define POLLPRI_ 0x0400 // MSDN unsupported
76
59
// </sync libc/sysv/consts.sh>
77
60
78
- textwindows static dontinline struct timespec sys_poll_nt_now (void ) {
61
+ textwindows dontinline static struct timespec sys_poll_nt_now (void ) {
79
62
uint64_t hectons ;
80
63
QueryUnbiasedInterruptTimePrecise (& hectons );
81
64
return timespec_fromnanos (hectons * 100 );
82
65
}
83
66
84
- textwindows static int sys_poll_nt_sigcheck (sigset_t sigmask ) {
85
- int sig , handler_was_called ;
86
- if (_check_cancel () == -1 )
87
- return -1 ;
88
- if (_weaken (__sig_get ) && (sig = _weaken (__sig_get )(sigmask ))) {
89
- handler_was_called = _weaken (__sig_relay )(sig , SI_KERNEL , sigmask );
90
- if (_check_cancel () == -1 )
91
- return -1 ;
92
- if (handler_was_called )
93
- return eintr ();
67
+ textwindows static uint32_t sys_poll_nt_waitms (struct timespec deadline ) {
68
+ struct timespec now = sys_poll_nt_now ();
69
+ if (timespec_cmp (now , deadline ) < 0 ) {
70
+ struct timespec remain = timespec_sub (deadline , now );
71
+ int64_t millis = timespec_tomillis (remain );
72
+ uint32_t waitfor = MIN (millis , 0xffffffffu );
73
+ return MIN (waitfor , POLL_INTERVAL_MS );
74
+ } else {
75
+ return 0 ; // we timed out
94
76
}
95
- return 0 ;
96
77
}
97
78
98
79
// Polls on the New Technology.
99
80
//
100
81
// This function is used to implement poll() and select(). You may poll
101
82
// on sockets, files and the console at the same time. We also poll for
102
83
// both signals and posix thread cancelation, while the poll is polling
103
- textwindows static int sys_poll_nt_impl (struct pollfd * fds , uint64_t nfds ,
104
- uint32_t * ms , sigset_t sigmask ) {
105
- bool ok ;
106
- uint64_t millis ;
84
+ textwindows static int sys_poll_nt_actual (struct pollfd * fds , uint64_t nfds ,
85
+ struct timespec deadline ,
86
+ sigset_t waitmask ) {
107
87
int fileindices [64 ];
108
88
int sockindices [64 ];
109
89
int64_t filehands [64 ];
110
90
struct PosixThread * pt ;
111
91
int i , rc , ev , kind , gotsocks ;
112
92
struct sys_pollfd_nt sockfds [64 ];
113
- struct timespec deadline , remain , now ;
114
93
uint32_t cm , fi , wi , sn , pn , avail , waitfor , already_slept ;
115
94
116
- waitfor = ms ? * ms : -1u ;
117
- deadline = timespec_add (sys_poll_nt_now (), timespec_frommillis (waitfor ));
118
-
119
95
// ensure revents is cleared
120
96
for (i = 0 ; i < nfds ; ++ i )
121
97
fds [i ].revents = 0 ;
@@ -171,7 +147,7 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
171
147
rc += !!fds [i ].revents ;
172
148
}
173
149
__fds_unlock ();
174
- if (rc )
150
+ if (rc == -1 )
175
151
return rc ;
176
152
177
153
// perform poll operation
@@ -191,10 +167,7 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
191
167
if ((ev & POLLWRNORM_ ) && !(ev & POLLRDNORM_ )) {
192
168
fds [fi ].revents = fds [fi ].events & (POLLRDNORM_ | POLLWRNORM_ );
193
169
} else if (GetFileType (filehands [i ]) == kNtFileTypePipe ) {
194
- ok = PeekNamedPipe (filehands [i ], 0 , 0 , 0 , & avail , 0 );
195
- POLLTRACE ("PeekNamedPipe(%ld, 0, 0, 0, [%'u], 0) → {%hhhd, %d}" ,
196
- filehands [i ], avail , ok , GetLastError ());
197
- if (ok ) {
170
+ if (PeekNamedPipe (filehands [i ], 0 , 0 , 0 , & avail , 0 )) {
198
171
if (avail )
199
172
fds [fi ].revents = POLLRDNORM_ ;
200
173
} else if (GetLastError () == kNtErrorHandleEof ||
@@ -222,23 +195,15 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
222
195
}
223
196
224
197
// determine how long to wait
225
- now = sys_poll_nt_now ();
226
- if (timespec_cmp (now , deadline ) < 0 ) {
227
- remain = timespec_sub (deadline , now );
228
- millis = timespec_tomillis (remain );
229
- waitfor = MIN (millis , 0xffffffffu );
230
- waitfor = MIN (waitfor , POLL_INTERVAL_MS );
231
- } else {
232
- waitfor = 0 ; // we timed out
233
- }
198
+ waitfor = sys_poll_nt_waitms (deadline );
234
199
235
200
// check for events and/or readiness on sockets
236
201
// we always do this due to issues with POLLOUT
237
202
if (sn ) {
238
203
// if we need to wait, then we prefer to wait inside WSAPoll()
239
204
// this ensures network events are received in ~10µs not ~10ms
240
205
if (!rc && waitfor ) {
241
- if (sys_poll_nt_sigcheck ( sigmask ))
206
+ if (__sigcheck ( waitmask , false ))
242
207
return -1 ;
243
208
already_slept = waitfor ;
244
209
} else {
@@ -253,7 +218,7 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
253
218
++ rc ;
254
219
}
255
220
} else if (already_slept ) {
256
- if (sys_poll_nt_sigcheck ( sigmask ))
221
+ if (__sigcheck ( waitmask , false ))
257
222
return -1 ;
258
223
}
259
224
} else {
@@ -269,7 +234,7 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
269
234
// this ensures low latency for apps like emacs which with no sock
270
235
// here we shall actually report that something can be written too
271
236
if (!already_slept ) {
272
- if (sys_poll_nt_sigcheck ( sigmask ))
237
+ if (__sigcheck ( waitmask , false ))
273
238
return -1 ;
274
239
pt = _pthread_self ();
275
240
filehands [pn ] = pt -> pt_semaphore = CreateSemaphore (0 , 0 , 1 , 0 );
@@ -283,7 +248,7 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
283
248
return __winerr ();
284
249
} else if (wi == pn ) {
285
250
// our semaphore was signalled
286
- if (sys_poll_nt_sigcheck ( sigmask ))
251
+ if (__sigcheck ( waitmask , false ))
287
252
return -1 ;
288
253
} else if ((wi ^ kNtWaitAbandoned ) < pn ) {
289
254
// this is possibly because a process or thread was killed
@@ -328,7 +293,7 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
328
293
} else {
329
294
// should only be possible on kNtWaitTimeout or semaphore abandoned
330
295
// keep looping for events and we'll catch timeout when appropriate
331
- if (sys_poll_nt_sigcheck ( sigmask ))
296
+ if (__sigcheck ( waitmask , false ))
332
297
return -1 ;
333
298
}
334
299
}
@@ -341,11 +306,44 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
341
306
return rc ;
342
307
}
343
308
309
+ textwindows static int sys_poll_nt_impl (struct pollfd * fds , uint64_t nfds ,
310
+ struct timespec deadline ,
311
+ const sigset_t waitmask ) {
312
+ uint32_t waitms ;
313
+ int i , n , rc , got = 0 ;
314
+
315
+ // fast path
316
+ if (nfds <= 63 )
317
+ return sys_poll_nt_actual (fds , nfds , deadline , waitmask );
318
+
319
+ // clumsy path
320
+ for (;;) {
321
+ for (i = 0 ; i < nfds ; i += 64 ) {
322
+ n = nfds - i ;
323
+ n = n > 64 ? 64 : n ;
324
+ rc = sys_poll_nt_actual (fds + i , n , timespec_zero , waitmask );
325
+ if (rc == -1 )
326
+ return -1 ;
327
+ got += rc ;
328
+ }
329
+ if (got )
330
+ return got ;
331
+ if (!(waitms = sys_poll_nt_waitms (deadline )))
332
+ return 0 ;
333
+ if (_park_norestart (waitms , waitmask ) == -1 )
334
+ return -1 ;
335
+ }
336
+ }
337
+
344
338
textwindows int sys_poll_nt (struct pollfd * fds , uint64_t nfds , uint32_t * ms ,
345
339
const sigset_t * sigmask ) {
346
340
int rc ;
341
+ struct timespec now , timeout , deadline ;
347
342
BLOCK_SIGNALS ;
348
- rc = sys_poll_nt_impl (fds , nfds , ms , sigmask ? * sigmask : 0 );
343
+ now = ms ? sys_poll_nt_now () : timespec_zero ;
344
+ timeout = ms ? timespec_frommillis (* ms ) : timespec_max ;
345
+ deadline = timespec_add (now , timeout );
346
+ rc = sys_poll_nt_impl (fds , nfds , deadline , sigmask ? * sigmask : _SigMask );
349
347
ALLOW_SIGNALS ;
350
348
return rc ;
351
349
}
0 commit comments