44 * SPDX-License-Identifier: MIT
55 */
66
7- { { {
8- DEFAULT_POLLMASK = cDefs . POLLIN | cDefs . POLLOUT ;
9- } } }
10-
117var SyscallsLibrary = {
128 $SYSCALLS__deps : [
139#if FILESYSTEM && SYSCALLS_REQUIRE_FILESYSTEM
@@ -107,63 +103,6 @@ var SyscallsLibrary = {
107103 } ,
108104 } ,
109105
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-
167106 $syscallGetVarargI__internal : true ,
168107 $syscallGetVarargI : ( ) => {
169108#if ASSERTIONS
@@ -602,116 +541,75 @@ var SyscallsLibrary = {
602541 FS.chdir(stream.path);
603542 return 0;
604543 },
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: [
608556#if PTHREADS
609- '_emscripten_proxy_newselect_finish ',
557+ '_emscripten_proxy_poll_finish ',
610558#endif
611559 ],
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
560+ _poll_js: (fds, nfds, timeout, ctx, arg) => {
621561#if PTHREADS
622- assert(!ENVIRONMENT_IS_PTHREAD, '_newselect_js must be called in the main thread');
562+ // Enable event handlers only when the poll call is proxied from a worker.
563+ var cleanupFuncs = [];
564+ var notifyDone = false;
565+ function asyncPollComplete(count) {
566+ if (notifyDone) {
567+ return;
568+ }
569+ notifyDone = true;
570+ #if RUNTIME_DEBUG
571+ dbg('asyncPollComplete', count);
572+ #endif
573+ cleanupFuncs.forEach(cb => cb());
574+ __emscripten_proxy_poll_finish(ctx, arg, count);
575+ }
576+ function makeNotifyCallback(stream, pollfd) {
577+ var cb = (flags) => {
578+ if (notifyDone) {
579+ return;
580+ }
581+ #if RUNTIME_DEBUG
582+ dbg(` async poll notify : stream = $ { stream} `);
623583#endif
584+ var events = {{{ makeGetValue('pollfd', C_STRUCTS.pollfd.events, 'i16') }}};
585+ flags &= events | {{{ cDefs.POLLERR }}} | {{{ cDefs.POLLHUP }}};
586+ #if ASSERTIONS
587+ assert(flags)
624588#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);
632-
633- #if PTHREADS
634- var makeNotifyCallback = null;
635- if (ctx) {
636- // Enable event handlers only when the select call is proxied from a worker.
637- var cleanupFuncs = [];
638- 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;
589+ {{{ makeSetValue('pollfd', C_STRUCTS.pollfd.revents, 'flags', 'i16') }}};
590+ asyncPollComplete(1);
656591 }
657- if (timeoutInMillis > 0) {
658- setTimeout(() => makeNotifyCallback(-1)(0), timeoutInMillis );
592+ cb.registerCleanupFunc = (f) => {
593+ if (f) cleanupFuncs.push(f );
659594 }
595+ return cb;
660596 }
661- #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
667- }
668-
669- var stream = SYSCALLS.getStreamFromFD(fd);
670-
671- var flags = {{{ DEFAULT_POLLMASK }}};
672597
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);
678- }
598+ if (ctx) {
599+ #if RUNTIME_DEBUG
600+ dbg('async poll start');
679601#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)
602+ if (timeout > 0) {
603+ setTimeout(() => {
604+ #if RUNTIME_DEBUG
605+ dbg('poll: timeout');
685606#endif
607+ asyncPollComplete(0);
608+ }, timeout);
686609 }
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);
695- }
696- return 0;
697610 }
698611#endif
699612
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) => {
715613 var count = 0;
716614 for (var i = 0; i < nfds; i++) {
717615 var pollfd = fds + {{{ C_STRUCTS.pollfd.__size__ }}} * i;
@@ -720,15 +618,31 @@ var SyscallsLibrary = {
720618 var mask = {{{ cDefs.POLLNVAL }}};
721619 var stream = FS.getStream(fd);
722620 if (stream) {
723- mask = {{{ DEFAULT_POLLMASK }}};
724621 if (stream.stream_ops.poll) {
622+ #if PTHREADS
623+ if (ctx && timeout) {
624+ mask = stream.stream_ops.poll(stream, timeout, makeNotifyCallback(stream, pollfd));
625+ } else
626+ #endif
725627 mask = stream.stream_ops.poll(stream, -1);
628+ } else {
629+ mask = {{{ cDefs.POLLIN | cDefs.POLLOUT }}};
726630 }
727631 }
728632 mask &= events | {{{ cDefs.POLLERR }}} | {{{ cDefs.POLLHUP }}};
729633 if (mask) count++;
730634 {{{ makeSetValue('pollfd', C_STRUCTS.pollfd.revents, 'mask', 'i16') }}};
731635 }
636+
637+ #if PTHREADS
638+ if (ctx) {
639+ if (count || !timeout) {
640+ asyncPollComplete(count);
641+ }
642+ return 0;
643+ }
644+ #endif
645+
732646#if ASSERTIONS
733647 if (!count && timeout != 0) warnOnce('non-zero poll() timeout not supported: ' + timeout)
734648#endif
0 commit comments