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:
parent
794779b997
commit
646f7e70e7
68
src/configure
vendored
68
src/configure
vendored
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue
Block a user