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.
This commit is contained in:
Matthew Flatt 2011-11-08 17:36:25 -07:00
parent 794779b997
commit 646f7e70e7
8 changed files with 491 additions and 57 deletions

68
src/configure vendored
View File

@ -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 <poll.h>
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

View File

@ -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 <poll.h> ]
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])

View File

@ -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)

View File

@ -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

View File

@ -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)));

View File

@ -46,6 +46,9 @@
# ifdef SELECT_INCLUDE
# include <sys/select.h>
# endif
# ifdef HAVE_POLL_SYSCALL
# include <poll.h>
# endif
#endif
#ifdef IO_INCLUDE
# include <io.h>
@ -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)

View File

@ -48,6 +48,9 @@
# ifdef SELECT_INCLUDE
# include <sys/select.h>
# endif
# ifdef HAVE_POLL_SYSCALL
# include <poll.h>
# endif
#endif
#ifdef USE_ITIMER
# include <sys/types.h>
@ -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
}

View File

@ -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 */