@@ -102,6 +102,71 @@ 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+ getTotal : ( ) => total ,
138+ setFlags : ( fd , flags ) => {
139+ var mask = 1 << ( fd % 32 ) ;
140+
141+ if ( ( flags & { { { cDefs . POLLIN } } } ) && check ( fd , srcReadLow , srcReadHigh , mask ) ) {
142+ fd < 32 ? ( dstReadLow = dstReadLow | mask ) : ( dstReadHigh = dstReadHigh | mask ) ;
143+ total ++ ;
144+ }
145+ if ( ( flags & { { { cDefs . POLLOUT } } } ) && check ( fd , srcWriteLow , srcWriteHigh , mask ) ) {
146+ fd < 32 ? ( dstWriteLow = dstWriteLow | mask ) : ( dstWriteHigh = dstWriteHigh | mask ) ;
147+ total ++ ;
148+ }
149+ if ( ( flags & { { { cDefs . POLLPRI } } } ) && check ( fd , srcExceptLow , srcExceptHigh , mask ) ) {
150+ fd < 32 ? ( dstExceptLow = dstExceptLow | mask ) : ( dstExceptHigh = dstExceptHigh | mask ) ;
151+ total ++ ;
152+ }
153+ } ,
154+ commit : ( ) => {
155+ if ( readfds ) {
156+ { { { makeSetValue ( 'readfds' , '0' , 'dstReadLow' , 'i32' ) } } } ;
157+ { { { makeSetValue ( 'readfds' , '4' , 'dstReadHigh' , 'i32' ) } } } ;
158+ }
159+ if ( writefds ) {
160+ { { { makeSetValue ( 'writefds' , '0' , 'dstWriteLow' , 'i32' ) } } } ;
161+ { { { makeSetValue ( 'writefds' , '4' , 'dstWriteHigh' , 'i32' ) } } } ;
162+ }
163+ if ( exceptfds ) {
164+ { { { makeSetValue ( 'exceptfds' , '0' , 'dstExceptLow' , 'i32' ) } } } ;
165+ { { { makeSetValue ( 'exceptfds' , '4' , 'dstExceptHigh' , 'i32' ) } } } ;
166+ }
167+ }
168+ } ;
169+ } ,
105170 } ,
106171
107172 $syscallGetVarargI__internal : true ,
@@ -552,21 +617,7 @@ var SyscallsLibrary = {
552617 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
553618#endif
554619
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 ;
620+ var fdSet = SYSCALLS . parseSelectFDSet ( readfds , writefds , exceptfds ) ;
570621
571622 var allLow = ( readfds ? { { { makeGetValue ( 'readfds' , 0 , 'i32' ) } } } : 0 ) |
572623 ( writefds ? { { { makeGetValue ( 'writefds' , 0 , 'i32' ) } } } : 0 ) |
@@ -577,6 +628,11 @@ var SyscallsLibrary = {
577628
578629 var check = ( fd , low , high , val ) => fd < 32 ? ( low & val ) : ( high & val ) ;
579630
631+ var timeoutInMillis = - 1 ;
632+ if ( timeout ) {
633+ timeoutInMillis = SYSCALLS . getTimeoutInMillis ( timeout ) ;
634+ }
635+
580636 for ( var fd = 0 ; fd < nfds ; fd ++ ) {
581637 var mask = 1 << ( fd % 32 ) ;
582638 if ( ! ( check ( fd , allLow , allHigh , mask ) ) ) {
@@ -588,48 +644,16 @@ var SyscallsLibrary = {
588644 var flags = SYSCALLS . DEFAULT_POLLMASK ;
589645
590646 if ( stream . stream_ops . poll ) {
591- var timeoutInMillis = - 1 ;
592- if ( timeout ) {
593- // select(2) is declared to accept "struct timeval { time_t tv_sec; suseconds_t tv_usec; }".
594- // However, musl passes the two values to the syscall as an array of long values.
595- // Note that sizeof(time_t) != sizeof(long) in wasm32. The former is 8, while the latter is 4.
596- // This means using "C_STRUCTS.timeval.tv_usec" leads to a wrong offset.
597- // So, instead, we use POINTER_SIZE.
598- var tv_sec = ( readfds ? { { { makeGetValue ( 'timeout' , 0 , 'i32' ) } } } : 0 ) ,
599- tv_usec = ( readfds ? { { { makeGetValue ( 'timeout' , POINTER_SIZE , 'i32' ) } } } : 0 ) ;
600- timeoutInMillis = ( tv_sec + tv_usec / 1000000 ) * 1000 ;
601- }
602- flags = stream . stream_ops . poll ( stream , timeoutInMillis ) ;
647+ flags = stream . stream_ops . poll ( stream , ( ( timeoutInMillis < 0 ) || readfds ) ? timeoutInMillis : 0 ) ;
603648 }
604649
605- if ( ( flags & { { { cDefs . POLLIN } } } ) && check ( fd , srcReadLow , srcReadHigh , mask ) ) {
606- fd < 32 ? ( dstReadLow = dstReadLow | mask ) : ( dstReadHigh = dstReadHigh | mask ) ;
607- total ++ ;
608- }
609- if ( ( flags & { { { cDefs . POLLOUT } } } ) && check ( fd , srcWriteLow , srcWriteHigh , mask ) ) {
610- fd < 32 ? ( dstWriteLow = dstWriteLow | mask ) : ( dstWriteHigh = dstWriteHigh | mask ) ;
611- total ++ ;
612- }
613- if ( ( flags & { { { cDefs . POLLPRI } } } ) && check ( fd , srcExceptLow , srcExceptHigh , mask ) ) {
614- fd < 32 ? ( dstExceptLow = dstExceptLow | mask ) : ( dstExceptHigh = dstExceptHigh | mask ) ;
615- total ++ ;
616- }
650+ fdSet . setFlags ( fd , flags ) ;
617651 }
618652
619- if ( readfds ) {
620- { { { makeSetValue ( 'readfds ', '0 ', 'dstReadLow ', 'i32 ') } } } ;
621- { { { makeSetValue ( 'readfds ', '4 ', 'dstReadHigh ', 'i32 ') } } } ;
622- }
623- if ( writefds ) {
624- { { { makeSetValue ( 'writefds ', '0 ', 'dstWriteLow ', 'i32 ') } } } ;
625- { { { makeSetValue ( 'writefds ', '4 ', 'dstWriteHigh ', 'i32 ') } } } ;
626- }
627- if ( exceptfds ) {
628- { { { makeSetValue ( 'exceptfds ', '0 ', 'dstExceptLow ', 'i32 ') } } } ;
629- { { { makeSetValue ( 'exceptfds ', '4 ', 'dstExceptHigh ', 'i32 ') } } } ;
630- }
631653
632- return total ;
654+ fdSet . commit ( fd , flags ) ;
655+
656+ return fdSet . getTotal ( ) ;
633657 } ,
634658 _msync_js__i53abi : true ,
635659 _msync_js : ( addr , len , prot , flags , fd , offset ) => {
0 commit comments