11#include "hook.h"
22#include "yieldtypes.h"
3+ #include <time.h>
34#include <stdlib.h>
45#include <dlfcn.h>
56#include <fcntl.h>
@@ -44,6 +45,7 @@ sendmsg_t sendmsg_f = NULL;
4445poll_t poll_f = NULL ;
4546ppoll_t ppoll_f = NULL ;
4647select_t select_f = NULL ;
48+ pselect_t pselect_f = NULL ;
4749accept_t accept_f = NULL ;
4850sleep_t sleep_f = NULL ;
4951usleep_t usleep_f = NULL ;
@@ -355,6 +357,10 @@ ssize_t recv(int sockfd, void *buf, size_t len, int flags)
355357 while (1 ) {
356358 int beblk = crn_fd_would_blocking (sockfd , 0 );
357359 if (beblk < 0 ) { return beblk ; }
360+ if (beblk && (flags & MSG_DONTWAIT )) {
361+ errno = EWOULDBLOCK ;
362+ return -1 ;
363+ }
358364 if (beblk ) {
359365 crn_procer_yield (sockfd , YIELD_TYPE_RECV );
360366 continue ;
@@ -395,6 +401,10 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
395401 while (1 ){
396402 int beblk = crn_fd_would_blocking (sockfd , 0 );
397403 if (beblk < 0 ) { return beblk ; }
404+ if (beblk && (flags & MSG_DONTWAIT )) {
405+ errno = EWOULDBLOCK ;
406+ return -1 ;
407+ }
398408 if (beblk ) {
399409 crn_procer_yield (sockfd , YIELD_TYPE_RECVFROM );
400410 continue ;
@@ -427,6 +437,10 @@ ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
427437 for (int i = 0 ; ; i ++ ){
428438 int beblk = crn_fd_would_blocking (sockfd , 0 );
429439 if (beblk < 0 ) { return beblk ; }
440+ if (beblk && (flags & MSG_DONTWAIT )) {
441+ errno = EWOULDBLOCK ;
442+ return -1 ;
443+ }
430444 if (beblk ) {
431445 crn_procer_yield (sockfd , YIELD_TYPE_RECVMSG );
432446 continue ;
@@ -862,8 +876,86 @@ int select(int nfds, fd_set *readfds, fd_set *writefds,
862876{
863877 if (!select_f ) initHook ();
864878 if (!crn_in_procer ()) return select_f (nfds , readfds , writefds , exceptfds , timeout );
865- linfo ("%d\n" , nfds );
866- assert (1 == 2 );
879+ linfo ("%d %p %d.%d\n" , nfds , timeout , timeout ? timeout -> tv_sec : -1 , timeout ? timeout -> tv_usec : -1 );
880+
881+ if (timeout != 0 ) {
882+ struct timespec ts = {0 };
883+ ts .tv_sec = timeout -> tv_sec ;
884+ ts .tv_nsec = timeout -> tv_usec * 1000 ;
885+
886+ return pselect (nfds , readfds , writefds , exceptfds , & ts , 0 );
887+ } else {
888+ return pselect (nfds , readfds , writefds , exceptfds , 0 , 0 );
889+ }
890+ }
891+
892+ int pselect (int nfds , fd_set * readfds , fd_set * writefds ,
893+ fd_set * exceptfds , const struct timespec * timeout , const __sigset_t * sigmask )
894+ {
895+ if (!pselect_f ) initHook ();
896+ if (!crn_in_procer ()) return pselect_f (nfds , readfds , writefds , exceptfds , timeout , sigmask );
897+ linfo ("%d %p %d.%d\n" , nfds , timeout , timeout ? timeout -> tv_sec : -1 , timeout ? timeout -> tv_nsec : -1 );
898+
899+ // not blocking
900+ if (timeout != 0 && timeout -> tv_sec == 0 && timeout -> tv_nsec == 0 ) {
901+ return pselect_f (nfds , readfds , writefds , exceptfds , timeout , sigmask );
902+ }
903+
904+ long nsu = 1000 * 1000 * 1000 ;
905+ struct timespec bts = {0 };
906+ clock_gettime (CLOCK_REALTIME , & bts );
907+ long tons = bts .tv_nsec + ((long )bts .tv_sec )* nsu ;
908+ if (timeout != 0 ) {
909+ tons += timeout -> tv_nsec + ((long )bts .tv_sec )* nsu ;
910+ }
911+
912+ while (1 ) {
913+ int beblk = 1 ; int rdcnt = 0 ; int wrcnt = 0 ; int etcnt = 0 ;
914+ int n = 0 ; long fds [nfds + 1 ]; int ytypes [nfds + 1 ];
915+
916+ for (int i = 0 ; i < nfds ; i ++ ) {
917+ if (readfds != 0 && FD_ISSET (i , readfds )) {
918+ fds [n ] = i ;
919+ ytypes [n ] = YIELD_TYPE_READ ;
920+ n ++ ; rdcnt ++ ;
921+ if (!crn_fd_would_blocking (i , 0 )) { beblk = 0 ; }
922+ }
923+ if (writefds != 0 && FD_ISSET (i , writefds )) {
924+ fds [n ] = i ;
925+ ytypes [n ] = YIELD_TYPE_WRITE ;
926+ n ++ ; wrcnt ++ ;
927+ if (!crn_fd_would_blocking (i , 1 )) { beblk = 0 ; }
928+ }
929+ if (exceptfds != 0 && FD_ISSET (i , exceptfds )) {
930+ etcnt ++ ;
931+ assert (0 ); // not impl
932+ }
933+ }
934+ lwarn ("rdcnt/wrcnt/etcnt %d/%d\n" , rdcnt , wrcnt , etcnt );
935+ if (beblk ) {
936+ if (timeout != 0 ) {
937+ struct timespec ts = {0 };
938+ clock_gettime (CLOCK_REALTIME , & ts );
939+ long nowns = ts .tv_nsec + ((long )ts .tv_sec )* nsu ;
940+ if (nowns >= tons ) {
941+ return 0 ;
942+ }
943+
944+ fds [n ] = timeout -> tv_nsec + ((long )timeout -> tv_sec )* nsu ;
945+ ytypes [n ] = YIELD_TYPE_NANOSLEEP ;
946+ n ++ ;
947+ }
948+
949+ crn_procer_yield_multi (YIELD_TYPE_PSELECT , n , fds , ytypes );
950+ continue ;
951+ }
952+
953+ struct timespec ztv = {0 };
954+ int rc = pselect_f (nfds , readfds , writefds , exceptfds , timeout , sigmask );
955+ return rc ;
956+ }
957+
958+ assert (0 );
867959}
868960
869961unsigned int sleep (unsigned int seconds )
@@ -1084,7 +1176,8 @@ int dup(int oldfd)
10841176{
10851177 if (!dup_f ) initHook ();
10861178 linfo ("%d\n" , oldfd );
1087- assert (1 == 2 );
1179+ int rv = dup_f (oldfd );
1180+ return rv ;
10881181}
10891182// TODO: support FD_CLOEXEC
10901183int dup2 (int oldfd , int newfd )
@@ -1093,7 +1186,8 @@ int dup2(int oldfd, int newfd)
10931186 if (!crn_in_procer ()) return dup2_f (oldfd , newfd );
10941187
10951188 linfo ("%d\n" , newfd );
1096- assert (1 == 2 );
1189+ int rv = dup2_f (oldfd , newfd );
1190+ return rv ;
10971191}
10981192// TODO: support FD_CLOEXEC
10991193int dup3 (int oldfd , int newfd , int flags )
@@ -1102,7 +1196,8 @@ int dup3(int oldfd, int newfd, int flags)
11021196 if (!crn_in_procer ()) return dup3_f (oldfd , newfd , flags );
11031197
11041198 linfo ("%d\n" , flags );
1105- assert (1 == 2 );
1199+ int rv = dup3_f (oldfd , newfd , flags );
1200+ return rv ;
11061201}
11071202
11081203int fclose (FILE * fp )
@@ -1344,6 +1439,8 @@ ATTRIBUTE_WEAK extern int __libc_ppoll(struct pollfd *fds, nfds_t nfds,
13441439 const struct timespec * tmo_p , const sigset_t * sigmask );
13451440ATTRIBUTE_WEAK extern int __select (int nfds , fd_set * readfds , fd_set * writefds ,
13461441 fd_set * exceptfds , struct timeval * timeout );
1442+ ATTRIBUTE_WEAK extern int __pselect (int nfds , fd_set * readfds , fd_set * writefds ,
1443+ fd_set * exceptfds , const struct timespec * timeout , const __sigset_t * sigmask );
13471444ATTRIBUTE_WEAK extern unsigned int __sleep (unsigned int seconds );
13481445ATTRIBUTE_WEAK extern int __nanosleep (const struct timespec * req , struct timespec * rem );
13491446ATTRIBUTE_WEAK extern int __libc_close (int );
@@ -1410,6 +1507,7 @@ static int doInitHook()
14101507 poll_f = (poll_t )dlsym (RTLD_NEXT , "poll" );
14111508 ppoll_f = (ppoll_t )dlsym (RTLD_NEXT , "ppoll" );
14121509 select_f = (select_t )dlsym (RTLD_NEXT , "select" );
1510+ pselect_f = (pselect_t )dlsym (RTLD_NEXT , "pselect" );
14131511 sleep_f = (sleep_t )dlsym (RTLD_NEXT , "sleep" );
14141512 usleep_f = (usleep_t )dlsym (RTLD_NEXT , "usleep" );
14151513 nanosleep_f = (nanosleep_t )dlsym (RTLD_NEXT , "nanosleep" );
@@ -1467,6 +1565,7 @@ static int doInitHook()
14671565 poll_f = & __libc_poll ;
14681566 ppoll_f = & __libc_ppoll ;
14691567 select_f = & __select ;
1568+ pselect_f = & __pselect ;
14701569 sleep_f = & __sleep ;
14711570 usleep_f = & __usleep ;
14721571 nanosleep_f = & __nanosleep ;
0 commit comments