From 646f7e70e7ddc17a54d3a679515e205fc4c94e36 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Tue, 8 Nov 2011 17:36:25 -0700 Subject: [PATCH] prefer poll() to select() on Linux On Mac OS X, poll() doesn't work right in versions earlier than 10.5.5, select() is always faster, and large number of sockets will be better handled via kqueue(). On Linux, poll() is defintely better. Otherwise, we stick with select() to be conservative. --- src/configure | 68 +++++++++++ src/racket/configure.ac | 20 +++ src/racket/include/scheme.h | 3 + src/racket/mzconfig.h.in | 3 + src/racket/src/mzmarksrc.c | 3 + src/racket/src/network.c | 184 +++++++++++++++++++++++----- src/racket/src/port.c | 234 +++++++++++++++++++++++++++++++++--- src/racket/src/schfd.h | 33 +++-- 8 files changed, 491 insertions(+), 57 deletions(-) diff --git a/src/configure b/src/configure index a075ff50c5..cc8abee2a5 100755 --- a/src/configure +++ b/src/configure @@ -3963,6 +3963,7 @@ case "$host_os" in LIBS="$LIBS -ldl -lm -rdynamic" DYN_CFLAGS="-fPIC" STRIP_DEBUG="strip -S" + try_poll_syscall=yes case "$host_cpu" in #Required for CentOS 4.6 x86_64) @@ -5152,6 +5153,73 @@ fi { echo "$as_me:$LINENO: result: $mbsrtowcs" >&5 echo "${ECHO_T}$mbsrtowcs" >&6; } +if test "${try_poll_syscall}" = "yes" ; then + msg="for poll" + { echo "$as_me:$LINENO: checking $msg" >&5 +echo $ECHO_N "checking $msg... $ECHO_C" >&6; } + if test "$cross_compiling" = yes; then + use_poll=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + #include + int main() { + struct pollfd pfd; + int r; + pfd.fd = 0; + pfd.events = POLLIN; + r = poll(&pfd, 1, 0); + return 0; + } +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + use_poll=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +use_poll=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + { echo "$as_me:$LINENO: result: $use_poll" >&5 +echo "${ECHO_T}$use_poll" >&6; } + if test "${use_poll}" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_POLL_SYSCALL 1 +_ACEOF + + fi +fi + if test "${enable_libffi}" = "yes" ; then if test "${enable_foreign}" = "yes" ; then { echo "$as_me:$LINENO: checking for libffi" >&5 diff --git a/src/racket/configure.ac b/src/racket/configure.ac index a3e1b572a3..24844be0e8 100644 --- a/src/racket/configure.ac +++ b/src/racket/configure.ac @@ -493,6 +493,7 @@ case "$host_os" in LIBS="$LIBS -ldl -lm -rdynamic" DYN_CFLAGS="-fPIC" STRIP_DEBUG="strip -S" + try_poll_syscall=yes case "$host_cpu" in #Required for CentOS 4.6 x86_64) @@ -785,6 +786,25 @@ if test "$mbsrtowcs" = "no" ; then fi AC_MSG_RESULT($mbsrtowcs) +if test "${try_poll_syscall}" = "yes" ; then + [ msg="for poll" ] + AC_MSG_CHECKING($msg) + AC_TRY_RUN( + [ #include ] + int main() { + struct pollfd pfd; + int r; + pfd.fd = 0; + pfd.events = POLLIN; + r = poll(&pfd, 1, 0); + return 0; + }, use_poll=yes, use_poll=no, use_poll=no) + AC_MSG_RESULT($use_poll) + if test "${use_poll}" = "yes" ; then + AC_DEFINE(HAVE_POLL_SYSCALL,1,[Have poll()]) + fi +fi + if test "${enable_libffi}" = "yes" ; then if test "${enable_foreign}" = "yes" ; then AC_MSG_CHECKING([for libffi]) diff --git a/src/racket/include/scheme.h b/src/racket/include/scheme.h index 5f977d7ec2..90966a5a4b 100644 --- a/src/racket/include/scheme.h +++ b/src/racket/include/scheme.h @@ -1986,6 +1986,9 @@ extern Scheme_Extension_Table *scheme_extension_table; #ifdef USE_BEOS_PORT_THREADS # define USE_FAR_MZ_FDCALLS #endif +#ifdef HAVE_POLL_SYSCALL +# define USE_FAR_MZ_FDCALLS +#endif #ifdef USE_FAR_MZ_FDCALLS # define MZ_GET_FDSET(p, n) scheme_get_fdset(p, n) diff --git a/src/racket/mzconfig.h.in b/src/racket/mzconfig.h.in index 43f546d093..a8b0d37e9c 100644 --- a/src/racket/mzconfig.h.in +++ b/src/racket/mzconfig.h.in @@ -56,6 +56,9 @@ typedef unsigned long uintptr_t; /* Whether pthread_rwlock is available. */ #undef HAVE_PTHREAD_RWLOCK +/* When poll() is available: */ +#undef HAVE_POLL_SYSCALL + /* Enable futures: */ #undef MZ_USE_FUTURES diff --git a/src/racket/src/mzmarksrc.c b/src/racket/src/mzmarksrc.c index 4d9e58a02c..38c588a02b 100644 --- a/src/racket/src/mzmarksrc.c +++ b/src/racket/src/mzmarksrc.c @@ -1699,6 +1699,9 @@ mark_listener { mark: gcMARK2(l->mref, gc); +# ifdef HAVE_POLL_SYSCALL + gcMARK2(l->pfd, gc); +# endif size: gcBYTES_TO_WORDS(sizeof(listener_t) + ((l->count - mzFLEX_DELTA) * sizeof(tcp_t))); diff --git a/src/racket/src/network.c b/src/racket/src/network.c index ac720dd4ef..888234e70b 100644 --- a/src/racket/src/network.c +++ b/src/racket/src/network.c @@ -46,6 +46,9 @@ # ifdef SELECT_INCLUDE # include # endif +# ifdef HAVE_POLL_SYSCALL +# include +# endif #endif #ifdef IO_INCLUDE # include @@ -123,6 +126,9 @@ typedef struct { Scheme_Object so; Scheme_Custodian_Reference *mref; int count; +# ifdef HAVE_POLL_SYSCALL + struct pollfd *pfd; +# endif tcp_t s[mzFLEX_ARRAY_DECL]; } listener_t; #endif @@ -883,8 +889,27 @@ static int stop_listener(Scheme_Object *o); static int tcp_check_accept(Scheme_Object *_listener) { #ifdef USE_SOCKETS_TCP - tcp_t s, mx; listener_t *listener = (listener_t *)_listener; +# ifdef HAVE_POLL_SYSCALL + int sr, i; + + if (LISTENER_WAS_CLOSED(listener)) + return 1; + + do { + sr = poll(listener->pfd, listener->count, 0); + } while ((sr == -1) && (errno == EINTR)); + + if (sr) { + for (i = listener->count; i--; ) { + if (listener->pfd[i].revents) + return i + 1; + } + } + + return sr; +# else + tcp_t s, mx; DECL_OS_FDSET(readfds); DECL_OS_FDSET(exnfds); struct timeval time = {0, 0}; @@ -922,6 +947,7 @@ static int tcp_check_accept(Scheme_Object *_listener) } return sr; +# endif #endif } @@ -949,32 +975,53 @@ static int tcp_check_connect(Scheme_Object *connector_p) { #ifdef USE_SOCKETS_TCP tcp_t s; - DECL_OS_FDSET(writefds); - DECL_OS_FDSET(exnfds); - struct timeval time = {0, 0}; int sr; - INIT_DECL_OS_WR_FDSET(writefds); - INIT_DECL_OS_ER_FDSET(exnfds); - s = *(tcp_t *)connector_p; - MZ_OS_FD_ZERO(writefds); - MZ_OS_FD_ZERO(exnfds); +# ifdef HAVE_POLL_SYSCALL + { + GC_CAN_IGNORE struct pollfd pfd[1]; + pfd[0].fd = s; + pfd[0].events = POLLOUT; + do { + sr = poll(pfd, 1, 0); + } while ((sr == -1) && (errno == EINTR)); - MZ_OS_FD_SET(s, writefds); - MZ_OS_FD_SET(s, exnfds); + if (!sr) + return 0; + else if (pfd[0].revents & POLLOUT) + return 1; + else + return -1; + } +# else + { + DECL_OS_FDSET(writefds); + DECL_OS_FDSET(exnfds); + struct timeval time = {0, 0}; - do { - sr = select(s + 1, NULL, writefds, exnfds, &time); - } while ((sr == -1) && (NOT_WINSOCK(errno) == EINTR)); + INIT_DECL_OS_WR_FDSET(writefds); + INIT_DECL_OS_ER_FDSET(exnfds); - if (!sr) - return 0; - if (FD_ISSET(s, exnfds)) - return -1; - else - return 1; + MZ_OS_FD_ZERO(writefds); + MZ_OS_FD_ZERO(exnfds); + + MZ_OS_FD_SET(s, writefds); + MZ_OS_FD_SET(s, exnfds); + + do { + sr = select(s + 1, NULL, writefds, exnfds, &time); + } while ((sr == -1) && (NOT_WINSOCK(errno) == EINTR)); + + if (!sr) + return 0; + else if (FD_ISSET(s, exnfds)) + return -1; + else + return 1; + } +# endif #else return 0; #endif @@ -1002,6 +1049,25 @@ static int tcp_check_write(Scheme_Object *port) return 1; #ifdef USE_SOCKETS_TCP +# ifdef HAVE_POLL_SYSCALL + { + GC_CAN_IGNORE struct pollfd pfd[1]; + int sr; + + pfd[0].fd = data->tcp; + pfd[0].events = POLLOUT; + do { + sr = poll(pfd, 1, 0); + } while ((sr == -1) && (errno == EINTR)); + + if (!sr) + return 0; + else if (pfd[0].revents & POLLOUT) + return 1; + else + return -1; + } +# else { tcp_t s; DECL_OS_FDSET(writefds); @@ -1025,6 +1091,7 @@ static int tcp_check_write(Scheme_Object *port) return sr; } +# endif #else { TCPiopbX *xpb; @@ -1104,12 +1171,14 @@ static int tcp_byte_ready (Scheme_Input_Port *port) Scheme_Tcp *data; #ifdef USE_SOCKETS_TCP int sr; +# ifndef HAVE_POLL_SYSCALL DECL_OS_FDSET(readfds); DECL_OS_FDSET(exfds); struct timeval time = {0, 0}; INIT_DECL_OS_RD_FDSET(readfds); INIT_DECL_OS_ER_FDSET(exfds); +# endif #endif if (port->closed) @@ -1123,16 +1192,32 @@ static int tcp_byte_ready (Scheme_Input_Port *port) return 1; #ifdef USE_SOCKETS_TCP - MZ_OS_FD_ZERO(readfds); - MZ_OS_FD_ZERO(exfds); - MZ_OS_FD_SET(data->tcp, readfds); - MZ_OS_FD_SET(data->tcp, exfds); - - do { - sr = select(data->tcp + 1, readfds, NULL, exfds, &time); - } while ((sr == -1) && (NOT_WINSOCK(errno) == EINTR)); +# ifdef HAVE_POLL_SYSCALL + { + GC_CAN_IGNORE struct pollfd pfd[1]; - return sr; + pfd[0].fd = data->tcp; + pfd[0].events = POLLIN; + do { + sr = poll(pfd, 1, 0); + } while ((sr == -1) && (errno == EINTR)); + + return sr; + } +# else + { + MZ_OS_FD_ZERO(readfds); + MZ_OS_FD_ZERO(exfds); + MZ_OS_FD_SET(data->tcp, readfds); + MZ_OS_FD_SET(data->tcp, exfds); + + do { + sr = select(data->tcp + 1, readfds, NULL, exfds, &time); + } while ((sr == -1) && (NOT_WINSOCK(errno) == EINTR)); + + return sr; + } +# endif #endif return 0; @@ -2009,6 +2094,13 @@ tcp_listen(int argc, Scheme_Object *argv[]) l = scheme_malloc_tagged(sizeof(listener_t) + ((count - mzFLEX_DELTA) * sizeof(tcp_t))); l->so.type = scheme_listener_type; l->count = count; +# ifdef HAVE_POLL_SYSCALL + { + struct pollfd *pfd; + pfd = (struct pollfd *)scheme_malloc_atomic(sizeof(struct pollfd) * count); + l->pfd = pfd; + } +# endif { Scheme_Custodian_Reference *mref; mref = scheme_add_managed(NULL, @@ -2019,6 +2111,10 @@ tcp_listen(int argc, Scheme_Object *argv[]) l->mref = mref; } } +# ifdef HAVE_POLL_SYSCALL + l->pfd[pos].fd = s; + l->pfd[pos].events = POLLIN; +# endif l->s[pos++] = s; REGISTER_SOCKET(s); @@ -3001,6 +3097,20 @@ static int udp_check_send(Scheme_Object *_udp) if (udp->s == INVALID_SOCKET) return 1; +# ifdef HAVE_POLL_SYSCALL + { + GC_CAN_IGNORE struct pollfd pfd[1]; + int sr; + + pfd[0].fd = udp->s; + pfd[0].events = POLLOUT; + do { + sr = poll(pfd, 1, 0); + } while ((sr == -1) && (errno == EINTR)); + + return sr; + } +# else { DECL_OS_FDSET(writefds); DECL_OS_FDSET(exnfds); @@ -3021,6 +3131,7 @@ static int udp_check_send(Scheme_Object *_udp) return sr; } +#endif } static void udp_send_needs_wakeup(Scheme_Object *_udp, void *fds) @@ -3233,6 +3344,20 @@ static int udp_check_recv(Scheme_Object *_udp) if (udp->s == INVALID_SOCKET) return 1; +# ifdef HAVE_POLL_SYSCALL + { + GC_CAN_IGNORE struct pollfd pfd[1]; + int sr; + + pfd[0].fd = udp->s; + pfd[0].events = POLLIN; + do { + sr = poll(pfd, 1, 0); + } while ((sr == -1) && (errno == EINTR)); + + return sr; + } +# else { DECL_OS_FDSET(readfds); DECL_OS_FDSET(exnfds); @@ -3253,6 +3378,7 @@ static int udp_check_recv(Scheme_Object *_udp) return sr; } +# endif } static void udp_recv_needs_wakeup(Scheme_Object *_udp, void *fds) diff --git a/src/racket/src/port.c b/src/racket/src/port.c index 5708c8f691..f5f5063cac 100644 --- a/src/racket/src/port.c +++ b/src/racket/src/port.c @@ -48,6 +48,9 @@ # ifdef SELECT_INCLUDE # include # endif +# ifdef HAVE_POLL_SYSCALL +# include +# endif #endif #ifdef USE_ITIMER # include @@ -780,7 +783,136 @@ void scheme_alloc_global_fdset() { #endif } -#ifdef USE_DYNAMIC_FDSET_SIZE +#ifdef HAVE_POLL_SYSCALL + +# define PFD_EXTRA_SPACE 1 + +void *scheme_alloc_fdset_array(int count, int permanent) +{ + struct mz_fd_set_data *data; + struct mz_fd_set *r, *w, *e; + struct pollfd *pfd; + + data = (struct mz_fd_set_data *)scheme_malloc(sizeof(struct mz_fd_set_data)); + r = (struct mz_fd_set *)scheme_malloc(sizeof(struct mz_fd_set)); + w = (struct mz_fd_set *)scheme_malloc(sizeof(struct mz_fd_set)); + e = (struct mz_fd_set *)scheme_malloc(sizeof(struct mz_fd_set)); + + r->w = w; + r->e = e; + r->data = data; + w->data = data; + e->data = data; + + r->flags = scheme_make_integer(POLLIN); + w->flags = scheme_make_integer(POLLOUT); + e->flags = scheme_make_integer(0); + + data->size = scheme_make_integer(32); + data->count = scheme_make_integer(0); + + pfd = (struct pollfd *)scheme_malloc_atomic(sizeof(struct pollfd) * (32 + PFD_EXTRA_SPACE)); + data->pfd = pfd; + + if (permanent) + scheme_dont_gc_ptr(data); + + return r; +} + +void *scheme_init_fdset_array(void *fdarray, int count) +{ + ((struct mz_fd_set *)fdarray)->data->count = scheme_make_integer(0); + return fdarray; +} + +void *scheme_get_fdset(void *fdarray, int pos) +{ + switch (pos) { + case 0: + return fdarray; + case 1: + return ((struct mz_fd_set *)fdarray)->w; + case 2: + default: + return ((struct mz_fd_set *)fdarray)->e; + } +} + +void scheme_fdzero(void *fd) +{ + ((struct mz_fd_set *)fd)->data->count = scheme_make_integer(0); +} + +void scheme_fdclr(void *fd, int n) +{ + struct mz_fd_set_data *data = ((struct mz_fd_set *)fd)->data; + intptr_t flag = SCHEME_INT_VAL(((struct mz_fd_set *)fd)->flags); + intptr_t count = SCHEME_INT_VAL(data->count); + intptr_t i; + + for (i = 0; i < count; i++) { + if (data->pfd[i].fd == n) { + data->pfd[i].events -= (data->pfd[i].events & flag); + return; + } + } +} + +void scheme_fdset(void *fd, int n) +{ + struct mz_fd_set_data *data = ((struct mz_fd_set *)fd)->data; + intptr_t flag = SCHEME_INT_VAL(((struct mz_fd_set *)fd)->flags); + intptr_t count = SCHEME_INT_VAL(data->count); + intptr_t size, i; + struct pollfd *pfd; + + for (i = 0; i < count; i++) { + if (data->pfd[i].fd == n) { + data->pfd[i].events |= flag; + return; + } + } + + size = SCHEME_INT_VAL(data->size); + if (count >= size) { + size = size * 2; + pfd = scheme_malloc_atomic(sizeof(struct pollfd) * (size + PFD_EXTRA_SPACE)); + memcpy(pfd, data->pfd, sizeof(struct pollfd) * count); + data->pfd = pfd; + data->size = scheme_make_integer(size); + } + + data->pfd[count].fd = n; + data->pfd[count].events = flag; + count++; + data->count = scheme_make_integer(count); +} + +int scheme_fdisset(void *fd, int n) +{ + struct mz_fd_set_data *data = ((struct mz_fd_set *)fd)->data; + intptr_t flag = SCHEME_INT_VAL(((struct mz_fd_set *)fd)->flags); + intptr_t count = SCHEME_INT_VAL(data->count); + intptr_t i; + + if (!flag) flag = (POLLERR | POLLHUP); + + for (i = 0; i < count; i++) { + if (data->pfd[i].fd == n) { + if (data->pfd[i].revents & flag) + return 1; + else + return 0; + } + } + + return 0; +} + +#else + +# if defined(USE_DYNAMIC_FDSET_SIZE) /* initialized early via scheme_alloc_global_fdset */ SHARED_OK static int dynamic_fd_size; @@ -828,7 +960,7 @@ void scheme_fdzero(void *fd) memset(fd, 0, dynamic_fd_size + sizeof(intptr_t)); } -#else +# else # if defined(WIN32_FD_HANDLES) # define fdset_type win_extended_fd_set @@ -917,7 +1049,7 @@ void scheme_fdzero(void *fd) # endif } -#endif +# endif void scheme_fdclr(void *fd, int n) { @@ -983,6 +1115,8 @@ int scheme_fdisset(void *fd, int n) #endif } +#endif + void scheme_add_fd_handle(void *h, void *fds, int repost) { #if defined(WIN32_FD_HANDLES) @@ -5559,6 +5693,14 @@ fd_byte_ready (Scheme_Input_Port *port) return 0; #else int r; +# ifdef HAVE_POLL_SYSCALL + GC_CAN_IGNORE struct pollfd pfd[1]; + pfd[0].fd = fip->fd; + pfd[0].events = POLLIN; + do { + r = poll(pfd, 1, 0); + } while ((r == -1) && (errno == EINTR)); +# else DECL_FDSET(readfds, 1); DECL_FDSET(exnfds, 1); struct timeval time = {0, 0}; @@ -5574,6 +5716,7 @@ fd_byte_ready (Scheme_Input_Port *port) do { r = select(fip->fd + 1, readfds, NULL, exnfds, &time); } while ((r == -1) && (errno == EINTR)); +# endif # ifdef SOME_FDS_ARE_NOT_SELECTABLE /* Try a non-blocking read: */ @@ -6588,10 +6731,18 @@ fd_write_ready (Scheme_Object *port) return 1; /* non-blocking output, such as a console, or haven't written yet */ #else { + int sr; +# ifdef HAVE_POLL_SYSCALL + GC_CAN_IGNORE struct pollfd pfd[1]; + pfd[0].fd = fop->fd; + pfd[0].events = POLLOUT; + do { + sr = poll(pfd, 1, 0); + } while ((sr == -1) && (errno == EINTR)); +# else DECL_FDSET(writefds, 1); DECL_FDSET(exnfds, 1); struct timeval time = {0, 0}; - int sr; INIT_DECL_WR_FDSET(writefds); INIT_DECL_ER_FDSET(exnfds); @@ -6604,6 +6755,7 @@ fd_write_ready (Scheme_Object *port) do { sr = select(fop->fd + 1, NULL, writefds, exnfds, &time); } while ((sr == -1) && (errno == EINTR)); +#endif return sr; } @@ -9175,6 +9327,24 @@ static void default_sleep(float v, void *fds) if (!fds) { /* Nothing to block on - just sleep for some amount of time. */ #if defined(FILES_HAVE_FDS) +# ifdef HAVE_POLL_SYSCALL + int timeout; + if (v <= 0.0) + timeout = -1; + else { + timeout = (int)(v * 1000.0); + if (timeout < 0) + timeout = 0; + } + if (external_event_fd) { + GC_CAN_IGNORE struct pollfd pfd[1]; + pfd[0].fd = external_event_fd; + pfd[0].events = POLLIN; + poll(pfd, 1, timeout); + } else { + poll(NULL, 0, timeout); + } +# else /* Sleep by selecting on the external event fd */ struct timeval time; intptr_t secs = (intptr_t)v; @@ -9202,7 +9372,7 @@ static void default_sleep(float v, void *fds) } else { select(0, NULL, NULL, NULL, &time); } - +# endif #else # ifndef NO_SLEEP # ifndef NO_USLEEP @@ -9216,18 +9386,21 @@ static void default_sleep(float v, void *fds) /* Something to block on - sort our the parts in Windows. */ #if defined(FILES_HAVE_FDS) || defined(USE_WINSOCK_TCP) +# ifndef HAVE_POLL_SYSCALL int limit, actual_limit; fd_set *rd, *wr, *ex; struct timeval time; +# endif -#ifdef SIGCHILD_DOESNT_INTERRUPT_SELECT +# ifdef SIGCHILD_DOESNT_INTERRUPT_SELECT if (scheme_system_children) { /* Better poll every second or so... */ if (!v || (v > 1)) v = 1; } -#endif +# endif +# ifndef HAVE_POLL_SYSCALL { intptr_t secs = (intptr_t)v; intptr_t usecs = (intptr_t)(fmod(v, 1.0) * 1000000); @@ -9243,32 +9416,33 @@ static void default_sleep(float v, void *fds) time.tv_usec = usecs; } -# ifdef USE_WINSOCK_TCP +# ifdef USE_WINSOCK_TCP limit = 0; -# else -# ifdef USE_ULIMIT - limit = ulimit(4, 0); # else -# ifdef FIXED_FD_LIMIT - limit = FIXED_FD_LIMIT; +# ifdef USE_ULIMIT + limit = ulimit(4, 0); # else +# ifdef FIXED_FD_LIMIT + limit = FIXED_FD_LIMIT; +# else limit = getdtablesize(); +# endif # endif # endif -#endif rd = (fd_set *)fds; wr = (fd_set *)MZ_GET_FDSET(fds, 1); ex = (fd_set *)MZ_GET_FDSET(fds, 2); -# ifdef STORED_ACTUAL_FDSET_LIMIT +# ifdef STORED_ACTUAL_FDSET_LIMIT actual_limit = FDSET_LIMIT(rd); if (FDSET_LIMIT(wr) > actual_limit) actual_limit = FDSET_LIMIT(wr); if (FDSET_LIMIT(ex) > actual_limit) actual_limit = FDSET_LIMIT(ex); actual_limit++; -# else +# else actual_limit = limit; +# endif # endif /******* Start Windows stuff *******/ @@ -9369,16 +9543,40 @@ static void default_sleep(float v, void *fds) /******* End Windows stuff *******/ -#if defined(FILES_HAVE_FDS) +# ifdef HAVE_POLL_SYSCALL + { + struct mz_fd_set_data *data = ((struct mz_fd_set *)fds)->data; + intptr_t count = SCHEME_INT_VAL(data->count); + int timeout; + + if (v <= 0.0) + timeout = -1; + else { + timeout = (int)(v * 1000.0); + if (timeout < 0) + timeout = 0; + } + + if (external_event_fd) { + data->pfd[count].fd = external_event_fd; + data->pfd[count].events = POLLIN; + count++; + } + + poll(data->pfd, count, timeout); + } +#else +# if defined(FILES_HAVE_FDS) /* Watch for external events, too: */ if (external_event_fd) { MZ_FD_SET(external_event_fd, rd); if (external_event_fd >= actual_limit) actual_limit = external_event_fd + 1; } -#endif +# endif select(actual_limit, rd, wr, ex, v ? &time : NULL); +#endif #endif } diff --git a/src/racket/src/schfd.h b/src/racket/src/schfd.h index 2172b311a3..e0737a62bb 100644 --- a/src/racket/src/schfd.h +++ b/src/racket/src/schfd.h @@ -1,16 +1,29 @@ #ifdef USE_FAR_MZ_FDCALLS -struct mz_fd_set { fd_set fd; }; THREAD_LOCAL_DECL(extern struct mz_fd_set *scheme_fd_set); -# define DECL_FDSET(n, c) fd_set *n -# define INIT_DECL_FDSET(r, w, e) { \ - r = MZ_GET_FDSET(&scheme_fd_set->fd, 0 ); \ - w = MZ_GET_FDSET(&scheme_fd_set->fd, 1 ); \ - e = MZ_GET_FDSET(&scheme_fd_set->fd, 2 ); \ - } -# define INIT_DECL_RD_FDSET(r) r = MZ_GET_FDSET(&scheme_fd_set->fd, 0 ) -# define INIT_DECL_WR_FDSET(r) r = MZ_GET_FDSET(&scheme_fd_set->fd, 1 ) -# define INIT_DECL_ER_FDSET(r) r = MZ_GET_FDSET(&scheme_fd_set->fd, 2 ) +# ifdef HAVE_POLL_SYSCALL +struct mz_fd_set { + struct mz_fd_set_data *data; + struct mz_fd_set *w; + struct mz_fd_set *e; + Scheme_Object *flags; +}; +struct mz_fd_set_data { + struct pollfd *pfd; + Scheme_Object *size, *count; +}; +# else +struct mz_fd_set { fd_set data; }; +# endif +#define DECL_FDSET(n, c) fd_set *n +#define INIT_DECL_FDSET(r, w, e) { \ + r = MZ_GET_FDSET(&scheme_fd_set->data, 0 ); \ + w = MZ_GET_FDSET(&scheme_fd_set->data, 1 ); \ + e = MZ_GET_FDSET(&scheme_fd_set->data, 2 ); \ + } +# define INIT_DECL_RD_FDSET(r) r = MZ_GET_FDSET(&scheme_fd_set->data, 0 ) +# define INIT_DECL_WR_FDSET(r) r = MZ_GET_FDSET(&scheme_fd_set->data, 1 ) +# define INIT_DECL_ER_FDSET(r) r = MZ_GET_FDSET(&scheme_fd_set->data, 2 ) #else # define DECL_FDSET(n, c) fd_set n[c] # define INIT_DECL_FDSET(r, w, e) /* empty */