@@ -102,6 +102,73 @@ var SyscallsLibrary = {
102102#endif
103103 return ret ;
104104 } ,
105+
106+ getTimeoutInMillis ( timeout ) {
107+ // select(2) is declared to accept "struct timeval { time_t tv_sec; suseconds_t tv_usec; }".
108+ // However, musl passes the two values to the syscall as an array of long values.
109+ // Note that sizeof(time_t) != sizeof(long) in wasm32. The former is 8, while the latter is 4.
110+ // This means using "C_STRUCTS.timeval.tv_usec" leads to a wrong offset.
111+ // So, instead, we use POINTER_SIZE.
112+ var tv_sec = ( { { { makeGetValue ( 'timeout' , 0 , 'i32' ) } } } ) ,
113+ tv_usec = ( { { { makeGetValue ( 'timeout' , POINTER_SIZE , 'i32' ) } } } ) ;
114+ return ( tv_sec + tv_usec / 1000000 ) * 1000 ;
115+ } ,
116+
117+ parseSelectFDSet ( readfds, writefds, exceptfds ) {
118+ var total = 0 ;
119+
120+ var srcReadLow = ( readfds ? { { { makeGetValue ( 'readfds' , 0 , 'i32' ) } } } : 0 ) ,
121+ srcReadHigh = ( readfds ? { { { makeGetValue ( 'readfds' , 4 , 'i32' ) } } } : 0 ) ;
122+ var srcWriteLow = ( writefds ? { { { makeGetValue ( 'writefds' , 0 , 'i32' ) } } } : 0 ) ,
123+ srcWriteHigh = ( writefds ? { { { makeGetValue ( 'writefds' , 4 , 'i32' ) } } } : 0 ) ;
124+ var srcExceptLow = ( exceptfds ? { { { makeGetValue ( 'exceptfds' , 0 , 'i32' ) } } } : 0 ) ,
125+ srcExceptHigh = ( exceptfds ? { { { makeGetValue ( 'exceptfds' , 4 , 'i32' ) } } } : 0 ) ;
126+
127+ var dstReadLow = 0 ,
128+ dstReadHigh = 0 ;
129+ var dstWriteLow = 0 ,
130+ dstWriteHigh = 0 ;
131+ var dstExceptLow = 0 ,
132+ dstExceptHigh = 0 ;
133+
134+ var check = ( fd , low , high , val ) => fd < 32 ? ( low & val ) : ( high & val ) ;
135+
136+ return {
137+ allLow : srcReadLow | srcWriteLow | srcExceptLow ,
138+ allHigh : srcReadHigh | srcWriteHigh | srcExceptHigh ,
139+ getTotal : ( ) => total ,
140+ setFlags : ( fd , flags ) => {
141+ var mask = 1 << ( fd % 32 ) ;
142+
143+ if ( ( flags & { { { cDefs . POLLIN } } } ) && check ( fd , srcReadLow , srcReadHigh , mask ) ) {
144+ fd < 32 ? ( dstReadLow = dstReadLow | mask ) : ( dstReadHigh = dstReadHigh | mask ) ;
145+ total ++ ;
146+ }
147+ if ( ( flags & { { { cDefs . POLLOUT } } } ) && check ( fd , srcWriteLow , srcWriteHigh , mask ) ) {
148+ fd < 32 ? ( dstWriteLow = dstWriteLow | mask ) : ( dstWriteHigh = dstWriteHigh | mask ) ;
149+ total ++ ;
150+ }
151+ if ( ( flags & { { { cDefs . POLLPRI } } } ) && check ( fd , srcExceptLow , srcExceptHigh , mask ) ) {
152+ fd < 32 ? ( dstExceptLow = dstExceptLow | mask ) : ( dstExceptHigh = dstExceptHigh | mask ) ;
153+ total ++ ;
154+ }
155+ } ,
156+ commit : ( ) => {
157+ if ( readfds ) {
158+ { { { makeSetValue ( 'readfds' , '0' , 'dstReadLow' , 'i32' ) } } } ;
159+ { { { makeSetValue ( 'readfds' , '4' , 'dstReadHigh' , 'i32' ) } } } ;
160+ }
161+ if ( writefds ) {
162+ { { { makeSetValue ( 'writefds' , '0' , 'dstWriteLow' , 'i32' ) } } } ;
163+ { { { makeSetValue ( 'writefds' , '4' , 'dstWriteHigh' , 'i32' ) } } } ;
164+ }
165+ if ( exceptfds ) {
166+ { { { makeSetValue ( 'exceptfds' , '0' , 'dstExceptLow' , 'i32' ) } } } ;
167+ { { { makeSetValue ( 'exceptfds' , '4' , 'dstExceptHigh' , 'i32' ) } } } ;
168+ }
169+ }
170+ } ;
171+ } ,
105172 } ,
106173
107174 $syscallGetVarargI__internal : true ,
@@ -552,27 +619,18 @@ var SyscallsLibrary = {
552619 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
553620#endif
554621
555- var total = 0 ;
556-
557- var srcReadLow = ( readfds ? { { { makeGetValue ( 'readfds' , 0 , 'i32' ) } } } : 0 ) ,
558- srcReadHigh = ( readfds ? { { { makeGetValue ( 'readfds' , 4 , 'i32' ) } } } : 0 ) ;
559- var srcWriteLow = ( writefds ? { { { makeGetValue ( 'writefds' , 0 , 'i32' ) } } } : 0 ) ,
560- srcWriteHigh = ( writefds ? { { { makeGetValue ( 'writefds' , 4 , 'i32' ) } } } : 0 ) ;
561- var srcExceptLow = ( exceptfds ? { { { makeGetValue ( 'exceptfds' , 0 , 'i32' ) } } } : 0 ) ,
562- srcExceptHigh = ( exceptfds ? { { { makeGetValue ( 'exceptfds' , 4 , 'i32' ) } } } : 0 ) ;
563-
564- var dstReadLow = 0 ,
565- dstReadHigh = 0 ;
566- var dstWriteLow = 0 ,
567- dstWriteHigh = 0 ;
568- var dstExceptLow = 0 ,
569- dstExceptHigh = 0 ;
622+ var fdSet = SYSCALLS . parseSelectFDSet ( readfds , writefds , exceptfds ) ;
570623
571- var allLow = srcReadLow | srcWriteLow | srcExceptLow ;
572- var allHigh = srcReadHigh | srcWriteHigh | srcExceptHigh ;
624+ var allLow = fdSet . allLow ;
625+ var allHigh = fdSet . allHigh ;
573626
574627 var check = ( fd , low , high , val ) => fd < 32 ? ( low & val ) : ( high & val ) ;
575628
629+ var timeoutInMillis = - 1 ;
630+ if ( timeout ) {
631+ timeoutInMillis = SYSCALLS . getTimeoutInMillis ( timeout ) ;
632+ }
633+
576634 for ( var fd = 0 ; fd < nfds ; fd ++ ) {
577635 var mask = 1 << ( fd % 32 ) ;
578636 if ( ! ( check ( fd , allLow , allHigh , mask ) ) ) {
@@ -584,48 +642,16 @@ var SyscallsLibrary = {
584642 var flags = SYSCALLS . DEFAULT_POLLMASK ;
585643
586644 if ( stream . stream_ops . poll ) {
587- var timeoutInMillis = - 1 ;
588- if ( timeout ) {
589- // select(2) is declared to accept "struct timeval { time_t tv_sec; suseconds_t tv_usec; }".
590- // However, musl passes the two values to the syscall as an array of long values.
591- // Note that sizeof(time_t) != sizeof(long) in wasm32. The former is 8, while the latter is 4.
592- // This means using "C_STRUCTS.timeval.tv_usec" leads to a wrong offset.
593- // So, instead, we use POINTER_SIZE.
594- var tv_sec = ( readfds ? { { { makeGetValue ( 'timeout' , 0 , 'i32' ) } } } : 0 ) ,
595- tv_usec = ( readfds ? { { { makeGetValue ( 'timeout' , POINTER_SIZE , 'i32' ) } } } : 0 ) ;
596- timeoutInMillis = ( tv_sec + tv_usec / 1000000 ) * 1000 ;
597- }
598- flags = stream . stream_ops . poll ( stream , timeoutInMillis ) ;
645+ flags = stream . stream_ops . poll ( stream , ( ( timeoutInMillis < 0 ) || readfds ) ? timeoutInMillis : 0 ) ;
599646 }
600647
601- if ( ( flags & { { { cDefs . POLLIN } } } ) && check ( fd , srcReadLow , srcReadHigh , mask ) ) {
602- fd < 32 ? ( dstReadLow = dstReadLow | mask ) : ( dstReadHigh = dstReadHigh | mask ) ;
603- total ++ ;
604- }
605- if ( ( flags & { { { cDefs . POLLOUT } } } ) && check ( fd , srcWriteLow , srcWriteHigh , mask ) ) {
606- fd < 32 ? ( dstWriteLow = dstWriteLow | mask ) : ( dstWriteHigh = dstWriteHigh | mask ) ;
607- total ++ ;
608- }
609- if ( ( flags & { { { cDefs . POLLPRI } } } ) && check ( fd , srcExceptLow , srcExceptHigh , mask ) ) {
610- fd < 32 ? ( dstExceptLow = dstExceptLow | mask ) : ( dstExceptHigh = dstExceptHigh | mask ) ;
611- total ++ ;
612- }
648+ fdSet . setFlags ( fd , flags ) ;
613649 }
614650
615- if ( readfds ) {
616- { { { makeSetValue ( 'readfds ', '0 ', 'dstReadLow ', 'i32 ') } } } ;
617- { { { makeSetValue ( 'readfds ', '4 ', 'dstReadHigh ', 'i32 ') } } } ;
618- }
619- if ( writefds ) {
620- { { { makeSetValue ( 'writefds ', '0 ', 'dstWriteLow ', 'i32 ') } } } ;
621- { { { makeSetValue ( 'writefds ', '4 ', 'dstWriteHigh ', 'i32 ') } } } ;
622- }
623- if ( exceptfds ) {
624- { { { makeSetValue ( 'exceptfds ', '0 ', 'dstExceptLow ', 'i32 ') } } } ;
625- { { { makeSetValue ( 'exceptfds ', '4 ', 'dstExceptHigh ', 'i32 ') } } } ;
626- }
627651
628- return total ;
652+ fdSet . commit ( ) ;
653+
654+ return fdSet . getTotal ( ) ;
629655 } ,
630656 _msync_js__i53abi : true ,
631657 _msync_js : ( addr , len , prot , flags , fd , offset ) => {
0 commit comments