|
4 | 4 | * SPDX-License-Identifier: MIT |
5 | 5 | */ |
6 | 6 |
|
7 | | -{{{ |
8 | | -DEFAULT_POLLMASK = cDefs.POLLIN | cDefs.POLLOUT; |
9 | | -}}} |
10 | | - |
11 | 7 | var SyscallsLibrary = { |
12 | 8 | $SYSCALLS__deps: [ |
13 | 9 | #if FILESYSTEM && SYSCALLS_REQUIRE_FILESYSTEM |
@@ -107,63 +103,6 @@ var SyscallsLibrary = { |
107 | 103 | }, |
108 | 104 | }, |
109 | 105 |
|
110 | | - $parseSelectFDSet__internal: true, |
111 | | - $parseSelectFDSet: (readfds, writefds, exceptfds) => { |
112 | | - var total = 0; |
113 | | - |
114 | | - var srcReadLow = (readfds ? {{{ makeGetValue('readfds', 0, 'i32') }}} : 0), |
115 | | - srcReadHigh = (readfds ? {{{ makeGetValue('readfds', 4, 'i32') }}} : 0); |
116 | | - var srcWriteLow = (writefds ? {{{ makeGetValue('writefds', 0, 'i32') }}} : 0), |
117 | | - srcWriteHigh = (writefds ? {{{ makeGetValue('writefds', 4, 'i32') }}} : 0); |
118 | | - var srcExceptLow = (exceptfds ? {{{ makeGetValue('exceptfds', 0, 'i32') }}} : 0), |
119 | | - srcExceptHigh = (exceptfds ? {{{ makeGetValue('exceptfds', 4, 'i32') }}} : 0); |
120 | | - |
121 | | - var dstReadLow = 0, |
122 | | - dstReadHigh = 0; |
123 | | - var dstWriteLow = 0, |
124 | | - dstWriteHigh = 0; |
125 | | - var dstExceptLow = 0, |
126 | | - dstExceptHigh = 0; |
127 | | - |
128 | | - var check = (fd, low, high, val) => fd < 32 ? (low & val) : (high & val); |
129 | | - |
130 | | - return { |
131 | | - allLow: srcReadLow | srcWriteLow | srcExceptLow, |
132 | | - allHigh: srcReadHigh | srcWriteHigh | srcExceptHigh, |
133 | | - getTotal: () => total, |
134 | | - setFlags: (fd, flags) => { |
135 | | - var mask = 1 << (fd % 32); |
136 | | - |
137 | | - if ((flags & {{{ cDefs.POLLIN }}}) && check(fd, srcReadLow, srcReadHigh, mask)) { |
138 | | - fd < 32 ? (dstReadLow = dstReadLow | mask) : (dstReadHigh = dstReadHigh | mask); |
139 | | - total++; |
140 | | - } |
141 | | - if ((flags & {{{ cDefs.POLLOUT }}}) && check(fd, srcWriteLow, srcWriteHigh, mask)) { |
142 | | - fd < 32 ? (dstWriteLow = dstWriteLow | mask) : (dstWriteHigh = dstWriteHigh | mask); |
143 | | - total++; |
144 | | - } |
145 | | - if ((flags & {{{ cDefs.POLLPRI }}}) && check(fd, srcExceptLow, srcExceptHigh, mask)) { |
146 | | - fd < 32 ? (dstExceptLow = dstExceptLow | mask) : (dstExceptHigh = dstExceptHigh | mask); |
147 | | - total++; |
148 | | - } |
149 | | - }, |
150 | | - commit: () => { |
151 | | - if (readfds) { |
152 | | - {{{ makeSetValue('readfds', '0', 'dstReadLow', 'i32') }}}; |
153 | | - {{{ makeSetValue('readfds', '4', 'dstReadHigh', 'i32') }}}; |
154 | | - } |
155 | | - if (writefds) { |
156 | | - {{{ makeSetValue('writefds', '0', 'dstWriteLow', 'i32') }}}; |
157 | | - {{{ makeSetValue('writefds', '4', 'dstWriteHigh', 'i32') }}}; |
158 | | - } |
159 | | - if (exceptfds) { |
160 | | - {{{ makeSetValue('exceptfds', '0', 'dstExceptLow', 'i32') }}}; |
161 | | - {{{ makeSetValue('exceptfds', '4', 'dstExceptHigh', 'i32') }}}; |
162 | | - } |
163 | | - } |
164 | | - }; |
165 | | - }, |
166 | | - |
167 | 106 | $syscallGetVarargI__internal: true, |
168 | 107 | $syscallGetVarargI: () => { |
169 | 108 | #if ASSERTIONS |
@@ -602,133 +541,106 @@ var SyscallsLibrary = { |
602 | 541 | FS.chdir(stream.path); |
603 | 542 | return 0; |
604 | 543 | }, |
605 | | - _newselect_js__i53abi: true, |
606 | | - _newselect_js__proxy: 'none', |
607 | | - _newselect_js__deps: ['$parseSelectFDSet', |
| 544 | + _msync_js__i53abi: true, |
| 545 | + _msync_js: (addr, len, prot, flags, fd, offset) => { |
| 546 | + if (isNaN(offset)) return -{{{ cDefs.EOVERFLOW }}}; |
| 547 | + SYSCALLS.doMsync(addr, SYSCALLS.getStreamFromFD(fd), len, flags, offset); |
| 548 | + return 0; |
| 549 | + }, |
| 550 | + __syscall_fdatasync: (fd) => { |
| 551 | + var stream = SYSCALLS.getStreamFromFD(fd); |
| 552 | + return 0; // we can't do anything synchronously; the in-memory FS is already synced to |
| 553 | + }, |
| 554 | + _poll_js__proxy: 'none', |
| 555 | + _poll_js__deps: [ |
608 | 556 | #if PTHREADS |
609 | | - '_emscripten_proxy_newselect_finish', |
| 557 | + '_emscripten_proxy_poll_finish', |
610 | 558 | #endif |
611 | 559 | ], |
612 | | - _newselect_js: (ctx, arg, nfds, readfds, writefds, exceptfds, timeoutInMillis) => { |
613 | | - // readfds are supported, |
614 | | - // writefds checks socket open status |
615 | | - // exceptfds are supported, although on web, such exceptional conditions never arise in web sockets |
616 | | - // and so the exceptfds list will always return empty. |
617 | | - // timeout is supported, although on SOCKFS these are ignored and always treated as 0 - fully async |
618 | | - // and PIPEFS supports timeout only when the select is called from a worker. |
619 | | -#if ASSERTIONS |
620 | | - assert(nfds <= 64, 'nfds must be less than or equal to 64'); // fd sets have 64 bits // TODO: this could be 1024 based on current musl headers |
621 | | -#if PTHREADS |
622 | | - assert(!ENVIRONMENT_IS_PTHREAD, '_newselect_js must be called in the main thread'); |
623 | | -#endif |
624 | | -#endif |
625 | | -
|
626 | | - var fdSet = parseSelectFDSet(readfds, writefds, exceptfds); |
627 | | -
|
628 | | - var allLow = fdSet.allLow; |
629 | | - var allHigh = fdSet.allHigh; |
630 | | -
|
631 | | - var check = (fd, low, high, val) => fd < 32 ? (low & val) : (high & val); |
| 560 | + _poll_js: (fds, nfds, timeout, ctx, arg) => { |
| 561 | + var count = 0; |
632 | 562 |
|
633 | 563 | #if PTHREADS |
634 | | - var makeNotifyCallback = null; |
635 | 564 | if (ctx) { |
636 | | - // Enable event handlers only when the select call is proxied from a worker. |
| 565 | +#if RUNTIME_DEBUG |
| 566 | + dbg('async poll start'); |
| 567 | +#endif |
| 568 | + // Enable event handlers only when the poll call is proxied from a worker. |
637 | 569 | var cleanupFuncs = []; |
638 | 570 | var notifyDone = false; |
639 | | - makeNotifyCallback = (fd) => { |
640 | | - var cb = (flags) => { |
641 | | - if (notifyDone) { |
642 | | - return; |
643 | | - } |
644 | | - if (fd >= 0) { |
645 | | - fdSet.setFlags(fd, flags); |
646 | | - } |
647 | | - notifyDone = true; |
648 | | - cleanupFuncs.forEach(cb => cb()); |
649 | | - fdSet.commit(); |
650 | | - __emscripten_proxy_newselect_finish(ctx, arg, fdSet.getTotal()); |
651 | | - } |
652 | | - cb.registerCleanupFunc = (f) => { |
653 | | - if (f != null) cleanupFuncs.push(f); |
654 | | - } |
655 | | - return cb; |
656 | | - } |
657 | | - if (timeoutInMillis > 0) { |
658 | | - setTimeout(() => makeNotifyCallback(-1)(0), timeoutInMillis); |
659 | | - } |
660 | | - } |
| 571 | + function asyncPollComplete(count) { |
| 572 | + if (notifyDone) { |
| 573 | + return; |
| 574 | + } |
| 575 | + notifyDone = true; |
| 576 | +#if RUNTIME_DEBUG |
| 577 | + dbg('asyncPollComplete', count); |
661 | 578 | #endif |
662 | | -
|
663 | | - for (var fd = 0; fd < nfds; fd++) { |
664 | | - var mask = 1 << (fd % 32); |
665 | | - if (!(check(fd, allLow, allHigh, mask))) { |
666 | | - continue; // index isn't in the set |
| 579 | + cleanupFuncs.forEach(cb => cb()); |
| 580 | + __emscripten_proxy_poll_finish(ctx, arg, count); |
667 | 581 | } |
668 | | -
|
669 | | - var stream = SYSCALLS.getStreamFromFD(fd); |
670 | | -
|
671 | | - var flags = {{{ DEFAULT_POLLMASK }}}; |
672 | | -
|
673 | | - if (stream.stream_ops.poll) { |
674 | | - flags = (() => { |
675 | | -#if PTHREADS |
676 | | - if (makeNotifyCallback != null) { |
677 | | - return stream.stream_ops.poll(stream, timeoutInMillis, timeoutInMillis != 0 ? makeNotifyCallback(fd) : null); |
| 582 | + function makeNotifyCallback(stream, pollfd) { |
| 583 | + var cb = (flags) => { |
| 584 | + if (notifyDone) { |
| 585 | + return; |
678 | 586 | } |
679 | | -#endif |
680 | | - return stream.stream_ops.poll(stream, timeoutInMillis); |
681 | | - })(); |
682 | | - } else { |
683 | | -#if ASSERTIONS |
684 | | - if (timeoutInMillis != 0) warnOnce('non-zero select() timeout not supported: ' + timeoutInMillis) |
685 | | -#endif |
| 587 | +#if RUNTIME_DEBUG |
| 588 | + dbg(`async poll notify: stream=${stream}`); |
| 589 | +#endif |
| 590 | + var events = {{{ makeGetValue('pollfd', C_STRUCTS.pollfd.events, 'i16') }}}; |
| 591 | + flags &= events | {{{ cDefs.POLLERR }}} | {{{ cDefs.POLLHUP }}}; |
| 592 | + assert(flags) |
| 593 | + {{{ makeSetValue('pollfd', C_STRUCTS.pollfd.revents, 'flags', 'i16') }}}; |
| 594 | + asyncPollComplete(1); |
| 595 | + } |
| 596 | + cb.registerCleanupFunc = (f) => { |
| 597 | + if (f) cleanupFuncs.push(f); |
| 598 | + } |
| 599 | + return cb; |
686 | 600 | } |
687 | | -
|
688 | | - fdSet.setFlags(fd, flags); |
689 | | - } |
690 | | -
|
691 | | -#if PTHREADS |
692 | | - if (makeNotifyCallback != null) { |
693 | | - if ((fdSet.getTotal() > 0) || (timeoutInMillis == 0) ) { |
694 | | - makeNotifyCallback(-1)(0); |
| 601 | + if (timeout > 0) { |
| 602 | + setTimeout(() => { |
| 603 | +#if RUNTIME_DEBUG |
| 604 | + dbg('poll: timeout'); |
| 605 | +#endif |
| 606 | + asyncPollComplete(0); |
| 607 | + }, timeout); |
695 | 608 | } |
696 | | - return 0; |
697 | 609 | } |
698 | 610 | #endif |
699 | 611 |
|
700 | | - fdSet.commit(); |
701 | | -
|
702 | | - return fdSet.getTotal(); |
703 | | - }, |
704 | | - _msync_js__i53abi: true, |
705 | | - _msync_js: (addr, len, prot, flags, fd, offset) => { |
706 | | - if (isNaN(offset)) return -{{{ cDefs.EOVERFLOW }}}; |
707 | | - SYSCALLS.doMsync(addr, SYSCALLS.getStreamFromFD(fd), len, flags, offset); |
708 | | - return 0; |
709 | | - }, |
710 | | - __syscall_fdatasync: (fd) => { |
711 | | - var stream = SYSCALLS.getStreamFromFD(fd); |
712 | | - return 0; // we can't do anything synchronously; the in-memory FS is already synced to |
713 | | - }, |
714 | | - __syscall_poll: (fds, nfds, timeout) => { |
715 | | - var count = 0; |
716 | 612 | for (var i = 0; i < nfds; i++) { |
717 | 613 | var pollfd = fds + {{{ C_STRUCTS.pollfd.__size__ }}} * i; |
718 | 614 | var fd = {{{ makeGetValue('pollfd', C_STRUCTS.pollfd.fd, 'i32') }}}; |
719 | 615 | var events = {{{ makeGetValue('pollfd', C_STRUCTS.pollfd.events, 'i16') }}}; |
720 | 616 | var mask = {{{ cDefs.POLLNVAL }}}; |
721 | 617 | var stream = FS.getStream(fd); |
722 | 618 | if (stream) { |
723 | | - mask = {{{ DEFAULT_POLLMASK }}}; |
724 | 619 | if (stream.stream_ops.poll) { |
| 620 | +#if PTHREADS |
| 621 | + if (ctx && timeout) { |
| 622 | + mask = stream.stream_ops.poll(stream, timeout, makeNotifyCallback(stream, pollfd)); |
| 623 | + } else |
| 624 | +#endif |
725 | 625 | mask = stream.stream_ops.poll(stream, -1); |
| 626 | + } else { |
| 627 | + mask = {{{ cDefs.POLLIN | cDefs.POLLOUT }}}; |
726 | 628 | } |
727 | 629 | } |
728 | 630 | mask &= events | {{{ cDefs.POLLERR }}} | {{{ cDefs.POLLHUP }}}; |
729 | 631 | if (mask) count++; |
730 | 632 | {{{ makeSetValue('pollfd', C_STRUCTS.pollfd.revents, 'mask', 'i16') }}}; |
731 | 633 | } |
| 634 | +
|
| 635 | +#if PTHREADS |
| 636 | + if (ctx) { |
| 637 | + if (count || !timeout) { |
| 638 | + asyncPollComplete(count); |
| 639 | + } |
| 640 | + return 0; |
| 641 | + } |
| 642 | +#endif |
| 643 | +
|
732 | 644 | #if ASSERTIONS |
733 | 645 | if (!count && timeout != 0) warnOnce('non-zero poll() timeout not supported: ' + timeout) |
734 | 646 | #endif |
|
0 commit comments