server: Added support for kqueue() as an alternative to poll() on FreeBSD.
This commit is contained in:
parent
9925b0561e
commit
c82789264b
|
@ -4118,12 +4118,12 @@ else
|
||||||
X_LIBS="$X_LIBS -L$x_libraries"
|
X_LIBS="$X_LIBS -L$x_libraries"
|
||||||
# For Solaris; some versions of Sun CC require a space after -R and
|
# For Solaris; some versions of Sun CC require a space after -R and
|
||||||
# others require no space. Words are not sufficient . . . .
|
# others require no space. Words are not sufficient . . . .
|
||||||
case `(uname -sr) 2>/dev/null` in
|
{ echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5
|
||||||
"SunOS 5"*)
|
|
||||||
{ echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5
|
|
||||||
echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6; }
|
echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6; }
|
||||||
ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries"
|
ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries"
|
||||||
cat >conftest.$ac_ext <<_ACEOF
|
ac_xsave_c_werror_flag=$ac_c_werror_flag
|
||||||
|
ac_c_werror_flag=yes
|
||||||
|
cat >conftest.$ac_ext <<_ACEOF
|
||||||
/* confdefs.h. */
|
/* confdefs.h. */
|
||||||
_ACEOF
|
_ACEOF
|
||||||
cat confdefs.h >>conftest.$ac_ext
|
cat confdefs.h >>conftest.$ac_ext
|
||||||
|
@ -4172,23 +4172,15 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
(exit $ac_status); }; }; then
|
(exit $ac_status); }; }; then
|
||||||
ac_R_nospace=yes
|
{ echo "$as_me:$LINENO: result: no" >&5
|
||||||
else
|
|
||||||
echo "$as_me: failed program was:" >&5
|
|
||||||
sed 's/^/| /' conftest.$ac_ext >&5
|
|
||||||
|
|
||||||
ac_R_nospace=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f core conftest.err conftest.$ac_objext \
|
|
||||||
conftest$ac_exeext conftest.$ac_ext
|
|
||||||
if test $ac_R_nospace = yes; then
|
|
||||||
{ echo "$as_me:$LINENO: result: no" >&5
|
|
||||||
echo "${ECHO_T}no" >&6; }
|
echo "${ECHO_T}no" >&6; }
|
||||||
X_LIBS="$X_LIBS -R$x_libraries"
|
X_LIBS="$X_LIBS -R$x_libraries"
|
||||||
else
|
else
|
||||||
|
echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
LIBS="$ac_xsave_LIBS -R $x_libraries"
|
LIBS="$ac_xsave_LIBS -R $x_libraries"
|
||||||
cat >conftest.$ac_ext <<_ACEOF
|
cat >conftest.$ac_ext <<_ACEOF
|
||||||
/* confdefs.h. */
|
/* confdefs.h. */
|
||||||
_ACEOF
|
_ACEOF
|
||||||
cat confdefs.h >>conftest.$ac_ext
|
cat confdefs.h >>conftest.$ac_ext
|
||||||
|
@ -4237,27 +4229,25 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||||
ac_status=$?
|
ac_status=$?
|
||||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
(exit $ac_status); }; }; then
|
(exit $ac_status); }; }; then
|
||||||
ac_R_space=yes
|
{ echo "$as_me:$LINENO: result: yes" >&5
|
||||||
else
|
|
||||||
echo "$as_me: failed program was:" >&5
|
|
||||||
sed 's/^/| /' conftest.$ac_ext >&5
|
|
||||||
|
|
||||||
ac_R_space=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f core conftest.err conftest.$ac_objext \
|
|
||||||
conftest$ac_exeext conftest.$ac_ext
|
|
||||||
if test $ac_R_space = yes; then
|
|
||||||
{ echo "$as_me:$LINENO: result: yes" >&5
|
|
||||||
echo "${ECHO_T}yes" >&6; }
|
echo "${ECHO_T}yes" >&6; }
|
||||||
X_LIBS="$X_LIBS -R $x_libraries"
|
X_LIBS="$X_LIBS -R $x_libraries"
|
||||||
else
|
else
|
||||||
{ echo "$as_me:$LINENO: result: neither works" >&5
|
echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
|
{ echo "$as_me:$LINENO: result: neither works" >&5
|
||||||
echo "${ECHO_T}neither works" >&6; }
|
echo "${ECHO_T}neither works" >&6; }
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
LIBS=$ac_xsave_LIBS
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
esac
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
ac_c_werror_flag=$ac_xsave_c_werror_flag
|
||||||
|
LIBS=$ac_xsave_LIBS
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check for system-dependent libraries X programs must link with.
|
# Check for system-dependent libraries X programs must link with.
|
||||||
|
@ -8434,6 +8424,7 @@ done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for ac_header in \
|
for ac_header in \
|
||||||
|
@ -8504,6 +8495,7 @@ for ac_header in \
|
||||||
sys/elf32.h \
|
sys/elf32.h \
|
||||||
sys/epoll.h \
|
sys/epoll.h \
|
||||||
sys/errno.h \
|
sys/errno.h \
|
||||||
|
sys/event.h \
|
||||||
sys/exec_elf.h \
|
sys/exec_elf.h \
|
||||||
sys/filio.h \
|
sys/filio.h \
|
||||||
sys/ioctl.h \
|
sys/ioctl.h \
|
||||||
|
@ -19347,6 +19339,7 @@ fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for ac_func in \
|
for ac_func in \
|
||||||
|
@ -19385,6 +19378,7 @@ for ac_func in \
|
||||||
gettimeofday \
|
gettimeofday \
|
||||||
getuid \
|
getuid \
|
||||||
inet_network \
|
inet_network \
|
||||||
|
kqueue \
|
||||||
lstat \
|
lstat \
|
||||||
memmove \
|
memmove \
|
||||||
mmap \
|
mmap \
|
||||||
|
|
|
@ -227,6 +227,7 @@ AC_CHECK_HEADERS(\
|
||||||
sys/elf32.h \
|
sys/elf32.h \
|
||||||
sys/epoll.h \
|
sys/epoll.h \
|
||||||
sys/errno.h \
|
sys/errno.h \
|
||||||
|
sys/event.h \
|
||||||
sys/exec_elf.h \
|
sys/exec_elf.h \
|
||||||
sys/filio.h \
|
sys/filio.h \
|
||||||
sys/ioctl.h \
|
sys/ioctl.h \
|
||||||
|
@ -1289,6 +1290,7 @@ AC_CHECK_FUNCS(\
|
||||||
gettimeofday \
|
gettimeofday \
|
||||||
getuid \
|
getuid \
|
||||||
inet_network \
|
inet_network \
|
||||||
|
kqueue \
|
||||||
lstat \
|
lstat \
|
||||||
memmove \
|
memmove \
|
||||||
mmap \
|
mmap \
|
||||||
|
|
|
@ -263,6 +263,9 @@
|
||||||
/* Define to 1 if you have the <jpeglib.h> header file. */
|
/* Define to 1 if you have the <jpeglib.h> header file. */
|
||||||
#undef HAVE_JPEGLIB_H
|
#undef HAVE_JPEGLIB_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `kqueue' function. */
|
||||||
|
#undef HAVE_KQUEUE
|
||||||
|
|
||||||
/* Define to 1 if you have the <lber.h> header file. */
|
/* Define to 1 if you have the <lber.h> header file. */
|
||||||
#undef HAVE_LBER_H
|
#undef HAVE_LBER_H
|
||||||
|
|
||||||
|
@ -725,6 +728,9 @@
|
||||||
/* Define to 1 if you have the <sys/errno.h> header file. */
|
/* Define to 1 if you have the <sys/errno.h> header file. */
|
||||||
#undef HAVE_SYS_ERRNO_H
|
#undef HAVE_SYS_ERRNO_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/event.h> header file. */
|
||||||
|
#undef HAVE_SYS_EVENT_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/exec_elf.h> header file. */
|
/* Define to 1 if you have the <sys/exec_elf.h> header file. */
|
||||||
#undef HAVE_SYS_EXEC_ELF_H
|
#undef HAVE_SYS_EXEC_ELF_H
|
||||||
|
|
||||||
|
|
122
server/fd.c
122
server/fd.c
|
@ -37,6 +37,11 @@
|
||||||
#ifdef HAVE_SYS_POLL_H
|
#ifdef HAVE_SYS_POLL_H
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SYS_EVENT_H
|
||||||
|
#include <sys/event.h>
|
||||||
|
#undef LIST_INIT
|
||||||
|
#undef LIST_ENTRY
|
||||||
|
#endif
|
||||||
#ifdef HAVE_STDINT_H
|
#ifdef HAVE_STDINT_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -358,7 +363,7 @@ static int get_next_timeout(void);
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_EPOLL
|
||||||
|
|
||||||
static int epoll_fd;
|
static int epoll_fd = -1;
|
||||||
|
|
||||||
static inline void init_epoll(void)
|
static inline void init_epoll(void)
|
||||||
{
|
{
|
||||||
|
@ -452,7 +457,120 @@ static inline void main_loop_epoll(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* USE_EPOLL */
|
#elif defined(HAVE_KQUEUE)
|
||||||
|
|
||||||
|
static int kqueue_fd = -1;
|
||||||
|
|
||||||
|
static inline void init_epoll(void)
|
||||||
|
{
|
||||||
|
#ifndef __APPLE__ /* kqueue support is broken in the MacOS kernel so we can't use it */
|
||||||
|
kqueue_fd = kqueue();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_fd_epoll_events( struct fd *fd, int user, int events )
|
||||||
|
{
|
||||||
|
struct kevent ev[2];
|
||||||
|
|
||||||
|
if (kqueue_fd == -1) return;
|
||||||
|
|
||||||
|
EV_SET( &ev[0], fd->unix_fd, EVFILT_READ, 0, NOTE_LOWAT, 1, (void *)user );
|
||||||
|
EV_SET( &ev[1], fd->unix_fd, EVFILT_WRITE, 0, NOTE_LOWAT, 1, (void *)user );
|
||||||
|
|
||||||
|
if (events == -1) /* stop waiting on this fd completely */
|
||||||
|
{
|
||||||
|
if (pollfd[user].fd == -1) return; /* already removed */
|
||||||
|
ev[0].flags |= EV_DELETE;
|
||||||
|
ev[1].flags |= EV_DELETE;
|
||||||
|
}
|
||||||
|
else if (pollfd[user].fd == -1)
|
||||||
|
{
|
||||||
|
if (pollfd[user].events) return; /* stopped waiting on it, don't restart */
|
||||||
|
ev[0].flags |= EV_ADD | ((events & POLLIN) ? EV_ENABLE : EV_DISABLE);
|
||||||
|
ev[1].flags |= EV_ADD | ((events & POLLOUT) ? EV_ENABLE : EV_DISABLE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pollfd[user].events == events) return; /* nothing to do */
|
||||||
|
ev[0].flags |= (events & POLLIN) ? EV_ENABLE : EV_DISABLE;
|
||||||
|
ev[1].flags |= (events & POLLOUT) ? EV_ENABLE : EV_DISABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kevent( kqueue_fd, ev, 2, NULL, 0, NULL ) == -1)
|
||||||
|
{
|
||||||
|
if (errno == ENOMEM) /* not enough memory, give up on kqueue */
|
||||||
|
{
|
||||||
|
close( kqueue_fd );
|
||||||
|
kqueue_fd = -1;
|
||||||
|
}
|
||||||
|
else perror( "kevent" ); /* should not happen */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void remove_epoll_user( struct fd *fd, int user )
|
||||||
|
{
|
||||||
|
if (kqueue_fd == -1) return;
|
||||||
|
|
||||||
|
if (pollfd[user].fd != -1)
|
||||||
|
{
|
||||||
|
struct kevent ev[2];
|
||||||
|
|
||||||
|
EV_SET( &ev[0], fd->unix_fd, EVFILT_READ, EV_DELETE, 0, 0, 0 );
|
||||||
|
EV_SET( &ev[1], fd->unix_fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0 );
|
||||||
|
kevent( kqueue_fd, ev, 2, NULL, 0, NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void main_loop_epoll(void)
|
||||||
|
{
|
||||||
|
int i, ret, timeout;
|
||||||
|
struct kevent events[128];
|
||||||
|
|
||||||
|
if (kqueue_fd == -1) return;
|
||||||
|
|
||||||
|
while (active_users)
|
||||||
|
{
|
||||||
|
timeout = get_next_timeout();
|
||||||
|
|
||||||
|
if (!active_users) break; /* last user removed by a timeout */
|
||||||
|
if (kqueue_fd == -1) break; /* an error occurred with kqueue */
|
||||||
|
|
||||||
|
if (timeout != -1)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
ts.tv_sec = timeout / 1000;
|
||||||
|
ts.tv_nsec = (timeout % 1000) * 1000000;
|
||||||
|
ret = kevent( kqueue_fd, NULL, 0, events, sizeof(events)/sizeof(events[0]), &ts );
|
||||||
|
}
|
||||||
|
else ret = kevent( kqueue_fd, NULL, 0, events, sizeof(events)/sizeof(events[0]), NULL );
|
||||||
|
|
||||||
|
/* put the events into the pollfd array first, like poll does */
|
||||||
|
for (i = 0; i < ret; i++)
|
||||||
|
{
|
||||||
|
long user = (long)events[i].udata;
|
||||||
|
pollfd[user].revents = 0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < ret; i++)
|
||||||
|
{
|
||||||
|
long user = (long)events[i].udata;
|
||||||
|
if (events[i].filter == EVFILT_READ) pollfd[user].revents |= POLLIN;
|
||||||
|
else if (events[i].filter == EVFILT_WRITE) pollfd[user].revents |= POLLOUT;
|
||||||
|
if (events[i].flags & EV_EOF) pollfd[user].revents |= POLLHUP;
|
||||||
|
if (events[i].flags & EV_ERROR) pollfd[user].revents |= POLLERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read events from the pollfd array, as set_fd_events may modify them */
|
||||||
|
for (i = 0; i < ret; i++)
|
||||||
|
{
|
||||||
|
long user = (long)events[i].udata;
|
||||||
|
if (pollfd[user].revents) fd_poll_event( poll_users[user], pollfd[user].revents );
|
||||||
|
pollfd[user].revents = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* HAVE_KQUEUE */
|
||||||
|
|
||||||
static inline void init_epoll(void) { }
|
static inline void init_epoll(void) { }
|
||||||
static inline void set_fd_epoll_events( struct fd *fd, int user, int events ) { }
|
static inline void set_fd_epoll_events( struct fd *fd, int user, int events ) { }
|
||||||
|
|
Loading…
Reference in New Issue