Skip to content

Commit 518eaba

Browse files
committed
Further optimize poll() on Windows
1 parent 556a294 commit 518eaba

File tree

6 files changed

+44
-64
lines changed

6 files changed

+44
-64
lines changed

libc/calls/park.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ textwindows static int _park_thread(uint32_t msdelay, sigset_t waitmask,
5757
CloseHandle(sigev);
5858

5959
// recursion is now safe
60-
if (ws == -1)
60+
if (ws == -1u)
6161
return __winerr();
6262
int handler_was_called = 0;
6363
if (sig)

libc/calls/poll-nt.c

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
│ PERFORMANCE OF THIS SOFTWARE. │
1818
╚─────────────────────────────────────────────────────────────────────────────*/
1919
#include "libc/calls/internal.h"
20+
#include "libc/calls/sig.internal.h"
2021
#include "libc/calls/state.internal.h"
2122
#include "libc/calls/struct/sigset.h"
2223
#include "libc/calls/struct/sigset.internal.h"
@@ -25,6 +26,7 @@
2526
#include "libc/calls/syscall_support-nt.internal.h"
2627
#include "libc/intrin/atomic.h"
2728
#include "libc/intrin/fds.h"
29+
#include "libc/intrin/weaken.h"
2830
#include "libc/macros.h"
2931
#include "libc/nt/console.h"
3032
#include "libc/nt/enum/filetype.h"
@@ -41,6 +43,7 @@
4143
#include "libc/sock/internal.h"
4244
#include "libc/sock/struct/pollfd.h"
4345
#include "libc/sysv/consts/o.h"
46+
#include "libc/sysv/consts/sicode.h"
4447
#include "libc/sysv/errfuns.h"
4548
#include "libc/thread/posixthread.internal.h"
4649
#ifdef __x86_64__
@@ -84,7 +87,7 @@ textwindows static int sys_poll_nt_actual(struct pollfd *fds, uint64_t nfds,
8487
struct PosixThread *pt;
8588
int i, rc, ev, kind, gotsocks;
8689
struct sys_pollfd_nt sockfds[64];
87-
uint32_t cm, fi, wi, sn, pn, avail, waitfor, already_slept;
90+
uint32_t cm, fi, sn, pn, avail, waitfor, already_slept;
8891

8992
// ensure revents is cleared
9093
for (i = 0; i < nfds; ++i)
@@ -228,22 +231,36 @@ textwindows static int sys_poll_nt_actual(struct pollfd *fds, uint64_t nfds,
228231
// this ensures low latency for apps like emacs which with no sock
229232
// here we shall actually report that something can be written too
230233
if (!already_slept) {
231-
if (__sigcheck(waitmask, false))
232-
return -1;
234+
intptr_t sigev;
235+
if (!(sigev = CreateEvent(0, 0, 0, 0)))
236+
return __winerr();
237+
filehands[pn] = sigev;
233238
pt = _pthread_self();
234-
filehands[pn] = pt->pt_event = CreateEvent(0, 0, 0, 0);
239+
pt->pt_event = sigev;
240+
pt->pt_blkmask = waitmask;
235241
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_EVENT,
236242
memory_order_release);
237-
wi = WaitForMultipleObjects(pn + 1, filehands, 0, waitfor);
243+
//!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!//
244+
int sig = 0;
245+
uint32_t wi = pn;
246+
if (!_is_canceled() &&
247+
!(_weaken(__sig_get) && (sig = _weaken(__sig_get)(waitmask))))
248+
wi = WaitForMultipleObjects(pn + 1, filehands, 0, waitfor);
249+
//!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!/!//
238250
atomic_store_explicit(&pt->pt_blocker, 0, memory_order_release);
239-
CloseHandle(filehands[pn]);
240-
if (wi == -1u) {
251+
CloseHandle(sigev);
252+
if (wi == -1u)
241253
// win32 wait failure
242254
return __winerr();
243-
} else if (wi == pn) {
255+
if (wi == pn) {
244256
// our signal event was signalled
245-
if (__sigcheck(waitmask, false))
257+
int handler_was_called = 0;
258+
if (sig)
259+
handler_was_called = _weaken(__sig_relay)(sig, SI_KERNEL, waitmask);
260+
if (_check_cancel() == -1)
246261
return -1;
262+
if (handler_was_called)
263+
return eintr();
247264
} else if ((wi ^ kNtWaitAbandoned) < pn) {
248265
// this is possibly because a process or thread was killed
249266
fds[fileindices[wi ^ kNtWaitAbandoned]].revents = POLLERR_;
@@ -287,8 +304,6 @@ textwindows static int sys_poll_nt_actual(struct pollfd *fds, uint64_t nfds,
287304
} else {
288305
// should only be possible on kNtWaitTimeout or semaphore abandoned
289306
// keep looping for events and we'll catch timeout when appropriate
290-
if (__sigcheck(waitmask, false))
291-
return -1;
292307
}
293308
}
294309

@@ -306,6 +321,13 @@ textwindows static int sys_poll_nt_impl(struct pollfd *fds, uint64_t nfds,
306321
uint32_t waitms;
307322
int i, n, rc, got = 0;
308323

324+
// we normally don't check for signals until we decide to wait, since
325+
// it's nice to have functions like write() be unlikely to EINTR, but
326+
// ppoll is a function where users are surely thinking about signals,
327+
// since ppoll actually allows them to block signals everywhere else.
328+
if (__sigcheck(waitmask, false))
329+
return -1;
330+
309331
// fast path
310332
if (nfds <= 63)
311333
return sys_poll_nt_actual(fds, nfds, deadline, waitmask);

libc/calls/pselect.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,11 @@ int pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
124124
END_CANCELATION_POINT;
125125

126126
STRACE("pselect(%d, %s → [%s], %s → [%s], %s → [%s], %s, %s) → %d% m", nfds,
127-
DescribeFdSet(rc, nfds, old_readfds_ptr),
127+
DescribeFdSet(0, nfds, old_readfds_ptr),
128128
DescribeFdSet(rc, nfds, readfds),
129-
DescribeFdSet(rc, nfds, old_writefds_ptr),
129+
DescribeFdSet(0, nfds, old_writefds_ptr),
130130
DescribeFdSet(rc, nfds, writefds),
131-
DescribeFdSet(rc, nfds, old_exceptfds_ptr),
131+
DescribeFdSet(0, nfds, old_exceptfds_ptr),
132132
DescribeFdSet(rc, nfds, exceptfds), //
133133
DescribeTimespec(0, timeout), //
134134
DescribeSigset(0, sigmask), rc);

libc/intrin/describefdset.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ const char *_DescribeFdSet(char buf[N], ssize_t rc, int nfds, fd_set *fds) {
3131

3232
if (!fds)
3333
return "NULL";
34+
if (rc == -1)
35+
return "n/a";
3436
if (kisdangerous(fds)) {
3537
ksnprintf(buf, N, "%p", fds);
3638
return buf;

libc/proc/proc.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,14 @@ textwindows int __proc_harvest(struct Proc *pr, bool iswait4) {
102102
pr->handle = status & 0x00FFFFFF;
103103
} else {
104104
// handle child _Exit()
105-
if (status == 0xc9af3d51u) {
105+
if (status == 0xc9af3d51u)
106106
status = kNtStillActive;
107-
}
108107
pr->wstatus = status;
109108
if (!iswait4 && !pr->waiters && !__proc.waiters &&
110109
(__sighandrvas[SIGCHLD] == (uintptr_t)SIG_IGN ||
111110
(__sighandflags[SIGCHLD] & SA_NOCLDWAIT))) {
112111
// perform automatic zombie reaping
112+
STRACE("automatically reaping zombie");
113113
dll_remove(&__proc.list, &pr->elem);
114114
dll_make_first(&__proc.free, &pr->elem);
115115
CloseHandle(pr->handle);
@@ -192,9 +192,8 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) {
192192
continue;
193193
if (j == i)
194194
continue;
195-
if (!--objects[j]->waiters && objects[j]->status == PROC_UNDEAD) {
195+
if (!--objects[j]->waiters && objects[j]->status == PROC_UNDEAD)
196196
__proc_free(objects[j]);
197-
}
198197
}
199198

200199
// check if we need to churn due to >64 processes
@@ -219,9 +218,8 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) {
219218
case PROC_ZOMBIE:
220219
break;
221220
case PROC_UNDEAD:
222-
if (!objects[i]->waiters) {
221+
if (!objects[i]->waiters)
223222
__proc_free(objects[i]);
224-
}
225223
break;
226224
default:
227225
__builtin_unreachable();
@@ -233,9 +231,8 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) {
233231
// 1. wait4() is being used
234232
// 2. SIGCHLD has SIG_IGN handler
235233
// 3. SIGCHLD has SA_NOCLDWAIT flag
236-
if (sic) {
234+
if (sic)
237235
__sig_generate(SIGCHLD, sic);
238-
}
239236
}
240237
return 0;
241238
}

test/libc/calls/fchmod_test.c

Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
 (0)