@@ -104,6 +104,63 @@ var SyscallsLibrary = {
104104 } ,
105105 } ,
106106
107+ $parseSelectFDSet__internal : true ,
108+ $parseSelectFDSet : ( readfds , writefds , exceptfds ) => {
109+ var total = 0 ;
110+
111+ var srcReadLow = ( readfds ? { { { makeGetValue ( 'readfds' , 0 , 'i32' ) } } } : 0 ) ,
112+ srcReadHigh = ( readfds ? { { { makeGetValue ( 'readfds' , 4 , 'i32' ) } } } : 0 ) ;
113+ var srcWriteLow = ( writefds ? { { { makeGetValue ( 'writefds' , 0 , 'i32' ) } } } : 0 ) ,
114+ srcWriteHigh = ( writefds ? { { { makeGetValue ( 'writefds' , 4 , 'i32' ) } } } : 0 ) ;
115+ var srcExceptLow = ( exceptfds ? { { { makeGetValue ( 'exceptfds' , 0 , 'i32' ) } } } : 0 ) ,
116+ srcExceptHigh = ( exceptfds ? { { { makeGetValue ( 'exceptfds' , 4 , 'i32' ) } } } : 0 ) ;
117+
118+ var dstReadLow = 0 ,
119+ dstReadHigh = 0 ;
120+ var dstWriteLow = 0 ,
121+ dstWriteHigh = 0 ;
122+ var dstExceptLow = 0 ,
123+ dstExceptHigh = 0 ;
124+
125+ var check = ( fd , low , high , val ) => fd < 32 ? ( low & val ) : ( high & val ) ;
126+
127+ return {
128+ allLow : srcReadLow | srcWriteLow | srcExceptLow ,
129+ allHigh : srcReadHigh | srcWriteHigh | srcExceptHigh ,
130+ getTotal : ( ) => total ,
131+ setFlags : ( fd , flags ) => {
132+ var mask = 1 << ( fd % 32 ) ;
133+
134+ if ( ( flags & { { { cDefs . POLLIN } } } ) && check ( fd , srcReadLow , srcReadHigh , mask ) ) {
135+ fd < 32 ? ( dstReadLow = dstReadLow | mask ) : ( dstReadHigh = dstReadHigh | mask ) ;
136+ total ++ ;
137+ }
138+ if ( ( flags & { { { cDefs . POLLOUT } } } ) && check ( fd , srcWriteLow , srcWriteHigh , mask ) ) {
139+ fd < 32 ? ( dstWriteLow = dstWriteLow | mask ) : ( dstWriteHigh = dstWriteHigh | mask ) ;
140+ total ++ ;
141+ }
142+ if ( ( flags & { { { cDefs . POLLPRI } } } ) && check ( fd , srcExceptLow , srcExceptHigh , mask ) ) {
143+ fd < 32 ? ( dstExceptLow = dstExceptLow | mask ) : ( dstExceptHigh = dstExceptHigh | mask ) ;
144+ total ++ ;
145+ }
146+ } ,
147+ commit : ( ) => {
148+ if ( readfds ) {
149+ { { { makeSetValue ( 'readfds' , '0' , 'dstReadLow' , 'i32' ) } } } ;
150+ { { { makeSetValue ( 'readfds' , '4' , 'dstReadHigh' , 'i32' ) } } } ;
151+ }
152+ if ( writefds ) {
153+ { { { makeSetValue ( 'writefds' , '0' , 'dstWriteLow' , 'i32' ) } } } ;
154+ { { { makeSetValue ( 'writefds' , '4' , 'dstWriteHigh' , 'i32' ) } } } ;
155+ }
156+ if ( exceptfds ) {
157+ { { { makeSetValue ( 'exceptfds' , '0' , 'dstExceptLow' , 'i32' ) } } } ;
158+ { { { makeSetValue ( 'exceptfds' , '4' , 'dstExceptHigh' , 'i32' ) } } } ;
159+ }
160+ }
161+ } ;
162+ } ,
163+
107164 $syscallGetVarargI__internal : true ,
108165 $syscallGetVarargI : ( ) = > {
109166#if ASSERTIONS
@@ -543,37 +600,88 @@ var SyscallsLibrary = {
543600 return 0 ;
544601 } ,
545602 __syscall__newselect__i53abi : true ,
603+ __syscall__newselect__proxy : 'none ',
604+ __syscall__newselect__deps : [ '_newselect_js' ,
605+ #if PTHREADS
606+ '_emscripten_proxy_newselect' ,
607+ #endif
608+ ] ,
546609 __syscall__newselect : ( nfds , readfds , writefds , exceptfds , timeoutInMillis ) = > {
610+ #if PTHREADS
611+ if ( ENVIRONMENT_IS_PTHREAD ) {
612+ return __emscripten_proxy_newselect ( nfds ,
613+ { { { to64 ( 'readfds' ) } } } ,
614+ { { { to64 ( 'writefds' ) } } } ,
615+ { { { to64 ( 'exceptfds' ) } } } ,
616+ { { { splitI64 ( 'timeoutInMillis' ) } } } ) ;
617+ }
618+ #endif
619+ return __newselect_js ( { { { to64 ( '0 ') } } } ,
620+ { { { to64 ( '0' ) } } } ,
621+ nfds ,
622+ { { { to64 ( 'readfds' ) } } } ,
623+ { { { to64 ( 'writefds' ) } } } ,
624+ { { { to64 ( 'exceptfds' ) } } } ,
625+ { { { splitI64 ( 'timeoutInMillis' ) } } } ) ;
626+ } ,
627+ _newselect_js__i53abi : true ,
628+ _newselect_js__proxy : 'none' ,
629+ _newselect_js__deps : [ '$parseSelectFDSet' ,
630+ #if PTHREADS
631+ '_emscripten_proxy_newselect_finish' ,
632+ #endif
633+ ] ,
634+ _newselect_js : ( ctx , arg , nfds , readfds , writefds , exceptfds , timeoutInMillis ) = > {
547635 // readfds are supported,
548636 // writefds checks socket open status
549637 // exceptfds are supported, although on web, such exceptional conditions never arise in web sockets
550638 // and so the exceptfds list will always return empty.
551- // timeout is supported, although on SOCKFS and PIPEFS these are ignored and always treated as 0 - fully async
639+ // timeout is supported, although on SOCKFS these are ignored and always treated as 0 - fully async
640+ // and PIPEFS supports timeout only when the select is called from a worker.
552641#if ASSERTIONS
553642 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
643+ #if PTHREADS
644+ assert ( ! ENVIRONMENT_IS_PTHREAD , '_newselect_js must be called in the main thread' ) ;
645+ #endif
554646#endif
555647
556- var total = 0 ;
557-
558- var srcReadLow = ( readfds ? { { { makeGetValue ( 'readfds' , 0 , 'i32' ) } } } : 0 ) ,
559- srcReadHigh = ( readfds ? { { { makeGetValue ( 'readfds' , 4 , 'i32' ) } } } : 0 ) ;
560- var srcWriteLow = ( writefds ? { { { makeGetValue ( 'writefds' , 0 , 'i32' ) } } } : 0 ) ,
561- srcWriteHigh = ( writefds ? { { { makeGetValue ( 'writefds' , 4 , 'i32' ) } } } : 0 ) ;
562- var srcExceptLow = ( exceptfds ? { { { makeGetValue ( 'exceptfds' , 0 , 'i32' ) } } } : 0 ) ,
563- srcExceptHigh = ( exceptfds ? { { { makeGetValue ( 'exceptfds' , 4 , 'i32' ) } } } : 0 ) ;
564-
565- var dstReadLow = 0 ,
566- dstReadHigh = 0 ;
567- var dstWriteLow = 0 ,
568- dstWriteHigh = 0 ;
569- var dstExceptLow = 0 ,
570- dstExceptHigh = 0 ;
648+ var fdSet = parseSelectFDSet ( readfds , writefds , exceptfds ) ;
571649
572- var allLow = srcReadLow | srcWriteLow | srcExceptLow ;
573- var allHigh = srcReadHigh | srcWriteHigh | srcExceptHigh ;
650+ var allLow = fdSet . allLow ;
651+ var allHigh = fdSet . allHigh ;
574652
575653 var check = ( fd , low , high , val ) => fd < 32 ? ( low & val ) : ( high & val ) ;
576654
655+ #if PTHREADS
656+ var makeNotifyCallback = null ;
657+ if ( ctx ) {
658+ // Enable event handlers only when the select call is proxied from a worker.
659+ var cleanupFuncs = [ ] ;
660+ var notifyDone = false ;
661+ makeNotifyCallback = ( fd ) => {
662+ var cb = ( flags ) => {
663+ if ( notifyDone ) {
664+ return ;
665+ }
666+ if ( fd >= 0 ) {
667+ fdSet . setFlags ( fd , flags ) ;
668+ }
669+ notifyDone = true ;
670+ cleanupFuncs . forEach ( cb => cb ( ) ) ;
671+ fdSet . commit ( ) ;
672+ __emscripten_proxy_newselect_finish ( { { { to64 ( 'ctx' ) } } } , { { { to64 ( 'arg' ) } } } , fdSet . getTotal ( ) ) ;
673+ }
674+ cb . registerCleanupFunc = ( f ) => {
675+ if ( f != null ) cleanupFuncs . push ( f ) ;
676+ }
677+ return cb ;
678+ }
679+ if ( timeoutInMillis > 0 ) {
680+ setTimeout ( ( ) => makeNotifyCallback ( - 1 ) ( 0 ) , timeoutInMillis ) ;
681+ }
682+ }
683+ #endif
684+
577685 for ( var fd = 0 ; fd < nfds ; fd ++ ) {
578686 var mask = 1 << ( fd % 32 ) ;
579687 if ( ! ( check ( fd , allLow , allHigh , mask ) ) ) {
@@ -585,41 +693,35 @@ var SyscallsLibrary = {
585693 var flags = SYSCALLS . DEFAULT_POLLMASK ;
586694
587695 if ( stream . stream_ops . poll ) {
588- flags = stream . stream_ops . poll ( stream , timeoutInMillis ) ;
696+ flags = ( ( ) => {
697+ #if PTHREADS
698+ if ( makeNotifyCallback != null ) {
699+ return stream . stream_ops . poll ( stream , timeoutInMillis , timeoutInMillis != 0 ? makeNotifyCallback ( fd ) : null ) ;
700+ }
701+ #endif
702+ return stream . stream_ops . poll ( stream , timeoutInMillis ) ;
703+ } ) ( ) ;
589704 } else {
590705#if ASSERTIONS
591706 if ( timeoutInMillis != 0 ) warnOnce ( 'non-zero select() timeout not supported: ' + timeoutInMillis )
592707#endif
593708 }
594709
595- if ( ( flags & { { { cDefs . POLLIN } } } ) && check ( fd , srcReadLow , srcReadHigh , mask ) ) {
596- fd < 32 ? ( dstReadLow = dstReadLow | mask ) : ( dstReadHigh = dstReadHigh | mask ) ;
597- total ++ ;
598- }
599- if ( ( flags & { { { cDefs . POLLOUT } } } ) && check ( fd , srcWriteLow , srcWriteHigh , mask ) ) {
600- fd < 32 ? ( dstWriteLow = dstWriteLow | mask ) : ( dstWriteHigh = dstWriteHigh | mask ) ;
601- total ++ ;
602- }
603- if ( ( flags & { { { cDefs . POLLPRI } } } ) && check ( fd , srcExceptLow , srcExceptHigh , mask ) ) {
604- fd < 32 ? ( dstExceptLow = dstExceptLow | mask ) : ( dstExceptHigh = dstExceptHigh | mask ) ;
605- total ++ ;
606- }
710+ fdSet . setFlags ( fd , flags ) ;
607711 }
608712
609- if ( readfds ) {
610- { { { makeSetValue ( 'readfds' , '0' , 'dstReadLow' , 'i32' ) } } } ;
611- { { { makeSetValue ( 'readfds' , '4' , 'dstReadHigh' , 'i32' ) } } } ;
612- }
613- if ( writefds ) {
614- { { { makeSetValue ( 'writefds' , '0' , 'dstWriteLow' , 'i32' ) } } } ;
615- { { { makeSetValue ( 'writefds' , '4' , 'dstWriteHigh' , 'i32' ) } } } ;
616- }
617- if ( exceptfds ) {
618- { { { makeSetValue ( 'exceptfds' , '0' , 'dstExceptLow' , 'i32' ) } } } ;
619- { { { makeSetValue ( 'exceptfds' , '4' , 'dstExceptHigh' , 'i32' ) } } } ;
713+ #if PTHREADS
714+ if ( makeNotifyCallback != null ) {
715+ if ( ( fdSet . getTotal ( ) > 0 ) || ( timeoutInMillis == 0 ) ) {
716+ makeNotifyCallback ( - 1 ) ( 0 ) ;
717+ }
718+ return 0 ;
620719 }
720+ #endif
721+
722+ fdSet . commit ( ) ;
621723
622- return total ;
724+ return fdSet . getTotal ( ) ;
623725 } ,
624726 _msync_js__i53abi : true ,
625727 _msync_js : ( addr , len , prot , flags , fd , offset ) = > {
0 commit comments