summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES5
-rw-r--r--NWGNUmakefile2
-rw-r--r--apr.dsp8
-rw-r--r--configure.in122
-rw-r--r--include/apr_poll.h184
-rw-r--r--include/arch/unix/apr_arch_poll_private.h86
-rw-r--r--libapr.dsp8
-rw-r--r--poll/os2/pollset.c9
-rw-r--r--poll/unix/epoll.c356
-rw-r--r--poll/unix/kqueue.c355
-rw-r--r--poll/unix/poll.c348
-rw-r--r--poll/unix/port.c370
-rw-r--r--poll/unix/select.c311
13 files changed, 1079 insertions, 1085 deletions
diff --git a/CHANGES b/CHANGES
index debc1ca70..e2cf21dc7 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,11 @@
-*- coding: utf-8 -*-
Changes for APR 1.4.0
+ *) Make apr_pollset and apr_pollcb implementations using providers.
+ Added apr_pollset_create_ex and apr_pollcb_create_ex that allows
+ choosing non-default providers.
+ [Mladen Turk]
+
*) apr_temp_dir_get() now checks the TMPDIR environment variable first,
instead of third. [Jim Jagielski]
diff --git a/NWGNUmakefile b/NWGNUmakefile
index 571227ac9..ae4257ee6 100644
--- a/NWGNUmakefile
+++ b/NWGNUmakefile
@@ -311,6 +311,8 @@ FILES_lib_objs = \
$(OBJDIR)/rand.o \
$(OBJDIR)/readwrite.o \
$(OBJDIR)/seek.o \
+ $(OBJDIR)/pollcb.o \
+ $(OBJDIR)/pollset.o \
$(OBJDIR)/select.o \
$(OBJDIR)/sendrecv.o \
$(OBJDIR)/sha2.o \
diff --git a/apr.dsp b/apr.dsp
index 88a87adeb..e1251593a 100644
--- a/apr.dsp
+++ b/apr.dsp
@@ -412,6 +412,14 @@ SOURCE=.\passwd\apr_getpass.c
# PROP Default_Filter ""
# Begin Source File
+SOURCE=.\poll\unix\pollcb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\poll\unix\pollset.c
+# End Source File
+# Begin Source File
+
SOURCE=.\poll\unix\select.c
# End Source File
# End Group
diff --git a/configure.in b/configure.in
index f02479f6b..a342c8412 100644
--- a/configure.in
+++ b/configure.in
@@ -903,6 +903,128 @@ fi
dnl ----------------------------- Checking for fdatasync: OS X doesn't have it
AC_CHECK_FUNCS(fdatasync)
+dnl ----------------------------- Checking for extended file descriptor handling
+# test for epoll_create1
+AC_CACHE_CHECK([for epoll_create1 support], [apr_cv_epoll_create1],
+[AC_TRY_RUN([
+#include <sys/epoll.h>
+#include <unistd.h>
+
+int main()
+{
+ return epoll_create1(0) == -1;
+}], [apr_cv_epoll_create1=yes], [apr_cv_epoll_create1=no], [apr_cv_epoll_create1=no])])
+
+if test "$apr_cv_epoll_create1" = "yes"; then
+ AC_DEFINE([HAVE_EPOLL_CREATE1], 1, [Define if epoll_create1 function is supported])
+fi
+
+# test for dup3
+AC_CACHE_CHECK([for dup3 support], [apr_cv_dup3],
+[AC_TRY_RUN([
+#include <unistd.h>
+
+int main()
+{
+ return dup3(STDOUT_FILENO, STDERR_FILENO, 0) == -1;
+}], [apr_cv_dup3=yes], [apr_cv_dup3=no], [apr_cv_dup3=no])])
+
+if test "$apr_cv_dup3" = "yes"; then
+ AC_DEFINE([HAVE_DUP3], 1, [Define if dup3 function is supported])
+fi
+
+# test for accept4
+AC_CACHE_CHECK([for accept4 support], [apr_cv_accept4],
+[AC_TRY_RUN([
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <errno.h>
+
+#define A4_SOCK "./apr_accept4_test_socket"
+
+int main()
+{
+ pid_t pid;
+ int fd;
+ struct sockaddr_un loc, rem;
+ socklen_t rem_sz;
+
+ if ((pid = fork())) {
+ int status;
+
+ unlink(A4_SOCK);
+
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ goto cleanup_failure2;
+
+ loc.sun_family = AF_UNIX;
+ strncpy(loc.sun_path, A4_SOCK, sizeof(loc.sun_path) - 1);
+
+ if (bind(fd, (struct sockaddr *) &loc,
+ sizeof(struct sockaddr_un)) == -1)
+ goto cleanup_failure;
+
+ if (listen(fd, 5) == -1)
+ goto cleanup_failure;
+
+ rem_sz = sizeof(struct sockaddr_un);
+ if (accept4(fd, (struct sockaddr *) &rem, &rem_sz, 0) == -1) {
+ goto cleanup_failure;
+ }
+ else {
+ close(fd);
+ waitpid(pid, &status, 0);
+ unlink(A4_SOCK);
+ return 0;
+ }
+
+cleanup_failure:
+ close(fd);
+cleanup_failure2:
+ kill(pid, SIGKILL);
+ waitpid(pid, &status, 0);
+ unlink(A4_SOCK);
+ return 1;
+ }
+ else {
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
+ return 1; /* this will be bad: we'll hang */
+
+ loc.sun_family = AF_UNIX;
+ strncpy(loc.sun_path, A4_SOCK, sizeof(loc.sun_path) - 1);
+
+ while(connect(fd, (struct sockaddr *) &loc,
+ sizeof(struct sockaddr_un)) == -1 &&
+ (errno==ENOENT || errno==ECONNREFUSED))
+ ;
+
+ close(fd);
+ return 0;
+ }
+}], [apr_cv_accept4=yes], [apr_cv_accept4=no], [apr_cv_accept4=no])])
+
+if test "$apr_cv_accept4" = "yes"; then
+ AC_DEFINE([HAVE_ACCEPT4], 1, [Define if accept4 function is supported])
+fi
+
+AC_CACHE_CHECK([for SOCK_CLOEXEC support], [apr_cv_sock_cloexec],
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int main()
+{
+ return socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0) == -1;
+}], [apr_cv_sock_cloexec=yes], [apr_cv_sock_cloexec=no], [apr_cv_sock_cloexec=no])])
+
+if test "$apr_cv_sock_cloexec" = "yes"; then
+ AC_DEFINE([HAVE_SOCK_CLOEXEC], 1, [Define if the SOCK_CLOEXEC flag is supported])
+fi
+
dnl ----------------------------- Checking for missing POSIX thread functions
AC_CHECK_FUNCS([getpwnam_r getpwuid_r getgrnam_r getgrgid_r])
diff --git a/include/apr_poll.h b/include/apr_poll.h
index 3e5d8f96d..9521eee92 100644
--- a/include/apr_poll.h
+++ b/include/apr_poll.h
@@ -49,14 +49,36 @@ extern "C" {
#define APR_POLLOUT 0x004 /**< Can write without blocking */
#define APR_POLLERR 0x010 /**< Pending error */
#define APR_POLLHUP 0x020 /**< Hangup occurred */
-#define APR_POLLNVAL 0x040 /**< Descriptior invalid */
+#define APR_POLLNVAL 0x040 /**< Descriptor invalid */
/**
* Pollset Flags
*/
-#define APR_POLLSET_THREADSAFE 0x001 /**< Adding or Removing a Descriptor is thread safe */
-#define APR_POLLSET_NOCOPY 0x002 /**< Descriptors passed to apr_pollset_create() are not copied */
-#define APR_POLLSET_WAKEABLE 0x004 /**< Pollset poll operation is interruptable */
+#define APR_POLLSET_THREADSAFE 0x001 /**< Adding or removing a descriptor is
+ * thread-safe
+ */
+#define APR_POLLSET_NOCOPY 0x002 /**< Descriptors passed to apr_pollset_add()
+ * are not copied
+ */
+#define APR_POLLSET_WAKEABLE 0x004 /**< Poll operations are interruptable by
+ * apr_pollset_wakeup()
+ */
+#define APR_POLLSET_NODEFAULT 0x010 /**< Do not try to use the default method if
+ * the specified non-default method cannot be
+ * used
+ */
+
+/**
+ * Pollset Methods
+ */
+typedef enum {
+ APR_POLLSET_DEFAULT, /**< Platform default poll method */
+ APR_POLLSET_SELECT, /**< Poll uses select method */
+ APR_POLLSET_KQUEUE,
+ APR_POLLSET_PORT,
+ APR_POLLSET_EPOLL,
+ APR_POLLSET_POLL
+} apr_pollset_method_e;
/** Used in apr_pollfd_t to determine what the apr_descriptor is */
typedef enum {
@@ -94,24 +116,27 @@ struct apr_pollfd_t {
typedef struct apr_pollset_t apr_pollset_t;
/**
- * Setup a pollset object
+ * Set up a pollset object
* @param pollset The pointer in which to return the newly created object
* @param size The maximum number of descriptors that this pollset can hold
* @param p The pool from which to allocate the pollset
* @param flags Optional flags to modify the operation of the pollset.
*
- * @remark If flags equals APR_POLLSET_THREADSAFE, then a pollset is
+ * @remark If flags contains APR_POLLSET_THREADSAFE, then a pollset is
* created on which it is safe to make concurrent calls to
* apr_pollset_add(), apr_pollset_remove() and apr_pollset_poll()
* from separate threads. This feature is only supported on some
* platforms; the apr_pollset_create() call will fail with
* APR_ENOTIMPL on platforms where it is not supported.
- * @remark If flags contain APR_POLLSET_WAKEABLE, then a pollset is
- * created with additional internal pipe object used for
+ * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollset is
+ * created with an additional internal pipe object used for the
* apr_pollset_wakeup() call. The actual size of pollset is
* in that case size + 1. This feature is only supported on some
* platforms; the apr_pollset_create() call will fail with
* APR_ENOTIMPL on platforms where it is not supported.
+ * @remark If flags contains APR_POLLSET_NOCOPY, then the apr_pollfd_t
+ * structures passed to apr_pollset_add() are not copied and
+ * must have a lifetime at least as long as the pollset.
*/
APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
apr_uint32_t size,
@@ -119,6 +144,38 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
apr_uint32_t flags);
/**
+ * Set up a pollset object
+ * @param pollset The pointer in which to return the newly created object
+ * @param size The maximum number of descriptors that this pollset can hold
+ * @param p The pool from which to allocate the pollset
+ * @param flags Optional flags to modify the operation of the pollset.
+ * @param method Poll method to use. See @apr_pollset_method_e. If this
+ * method cannot be used, the default method will be used unless the
+ * APR_POLLSET_NODEFAULT flag has been specified.
+ *
+ * @remark If flags contains APR_POLLSET_THREADSAFE, then a pollset is
+ * created on which it is safe to make concurrent calls to
+ * apr_pollset_add(), apr_pollset_remove() and apr_pollset_poll()
+ * from separate threads. This feature is only supported on some
+ * platforms; the apr_pollset_create_ex() call will fail with
+ * APR_ENOTIMPL on platforms where it is not supported.
+ * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollset is
+ * created with additional internal pipe object used for the
+ * apr_pollset_wakeup() call. The actual size of pollset is
+ * in that case size + 1. This feature is only supported on some
+ * platforms; the apr_pollset_create_ex() call will fail with
+ * APR_ENOTIMPL on platforms where it is not supported.
+ * @remark If flags contains APR_POLLSET_NOCOPY, then the apr_pollfd_t
+ * structures passed to apr_pollset_add() are not copied and
+ * must have a lifetime at least as long as the pollset.
+ */
+APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **pollset,
+ apr_uint32_t size,
+ apr_pool_t *p,
+ apr_uint32_t flags,
+ apr_pollset_method_e method);
+
+/**
* Destroy a pollset object
* @param pollset The pollset to destroy
*/
@@ -140,6 +197,15 @@ APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset);
* with APR_EINTR. Option (1) is recommended, but option (2) is
* allowed for implementations where option (1) is impossible
* or impractical.
+ * @remark If the pollset has been created with APR_POLLSET_NOCOPY, the
+ * apr_pollfd_t structure referenced by descriptor will not be copied
+ * and must have a lifetime at least as long as the pollset.
+ * @remark Do not add the same socket or file descriptor to the same pollset
+ * multiple times, even if the requested events differ for the
+ * different calls to apr_pollset_add(). If the events of interest
+ * for a descriptor change, you must first remove the descriptor
+ * from the pollset with apr_pollset_remove(), then add it again
+ * specifying all requested events.
*/
APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
const apr_pollfd_t *descriptor);
@@ -157,6 +223,9 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
* with APR_EINTR. Option (1) is recommended, but option (2) is
* allowed for implementations where option (1) is impossible
* or impractical.
+ * @remark apr_pollset_remove() cannot be used to remove a subset of requested
+ * events for a descriptor. The reqevents field in the apr_pollfd_t
+ * parameter must contain the same value when removing as when adding.
*/
APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
const apr_pollfd_t *descriptor);
@@ -164,16 +233,20 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
/**
* Block for activity on the descriptor(s) in a pollset
* @param pollset The pollset to use
- * @param timeout The amount of time in microseconds to wait. This is
- * a maximum, not a minimum. If a descriptor is signalled, we
- * will wake up before this time. A negative number means
- * wait until a descriptor is signalled.
+ * @param timeout The amount of time in microseconds to wait. This is a
+ * maximum, not a minimum. If a descriptor is signalled, the
+ * function will return before this time. If timeout is
+ * negative, the function will block until a descriptor is
+ * signalled or until apr_pollset_wakeup() has been called.
* @param num Number of signalled descriptors (output parameter)
* @param descriptors Array of signalled descriptors (output parameter)
- * @remark If the pollset has been created with APR_POLLSET_WAKEABLE
- * and the wakeup has been called while waiting for activity
- * return value is APR_EINTR in case there was no signaled
- * descriptors at the time of wakeup call.
+ * @remark APR_EINTR will be returned if the pollset has been created with
+ * APR_POLLSET_WAKEABLE, apr_pollset_wakeup() has been called while
+ * waiting for activity, and there were no signalled descriptors at the
+ * time of the wakeup call.
+ * @remark Multiple signalled conditions for the same descriptor may be reported
+ * in one or more returned apr_pollfd_t structures, depending on the
+ * implementation.
*/
APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
apr_interval_time_t timeout,
@@ -181,7 +254,7 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
const apr_pollfd_t **descriptors);
/**
- * Interrupt the blocked apr_pollset_poll call.
+ * Interrupt the blocked apr_pollset_poll() call.
* @param pollset The pollset to use
* @remark If the pollset was not created with APR_POLLSET_WAKEABLE the
* return value is APR_EINIT.
@@ -193,13 +266,14 @@ APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset);
* @param aprset The poll structure we will be using.
* @param numsock The number of descriptors we are polling
* @param nsds The number of descriptors signalled (output parameter)
- * @param timeout The amount of time in microseconds to wait. This is
- * a maximum, not a minimum. If a descriptor is signalled, we
- * will wake up before this time. A negative number means
- * wait until a descriptor is signalled.
+ * @param timeout The amount of time in microseconds to wait. This is a
+ * maximum, not a minimum. If a descriptor is signalled, the
+ * function will return before this time. If timeout is
+ * negative, the function will block until a descriptor is
+ * signalled or until apr_pollset_wakeup() has been called.
* @remark The number of descriptors signalled is returned in the third argument.
* This is a blocking call, and it will not return until either a
- * descriptor has been signalled, or the timeout has expired.
+ * descriptor has been signalled or the timeout has expired.
* @remark The rtnevents field in the apr_pollfd_t array will only be filled-
* in if the return value is APR_SUCCESS.
*/
@@ -207,11 +281,23 @@ APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t numsock,
apr_int32_t *nsds,
apr_interval_time_t timeout);
+/**
+ * Return a printable representation of the pollset method.
+ * @param pollset The pollset to use
+ */
+APR_DECLARE(const char *) apr_pollset_method_name(apr_pollset_t *pollset);
+
+/**
+ * Return a printable representation of the default pollset method
+ * (APR_POLLSET_DEFAULT).
+ */
+APR_DECLARE(const char *) apr_poll_method_defname(void);
+
/** Opaque structure used for pollset API */
typedef struct apr_pollcb_t apr_pollcb_t;
/**
- * Setup a pollcb object
+ * Set up a pollcb object
* @param pollcb The pointer in which to return the newly created object
* @param size The maximum number of descriptors that a single _poll can return.
* @param p The pool from which to allocate the pollcb
@@ -226,15 +312,40 @@ APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
apr_uint32_t flags);
/**
+ * Set up a pollcb object
+ * @param pollcb The pointer in which to return the newly created object
+ * @param size The maximum number of descriptors that a single _poll can return.
+ * @param p The pool from which to allocate the pollcb
+ * @param flags Optional flags to modify the operation of the pollcb.
+ * @param method Poll method to use. See @apr_pollset_method_e. If this
+ * method cannot be used, the default method will be used unless the
+ * APR_POLLSET_NODEFAULT flag has been specified.
+ *
+ * @remark Pollcb is only supported on some platforms; the apr_pollcb_create_ex()
+ * call will fail with APR_ENOTIMPL on platforms where it is not supported.
+ */
+APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **pollcb,
+ apr_uint32_t size,
+ apr_pool_t *pool,
+ apr_uint32_t flags,
+ apr_pollset_method_e method);
+
+/**
* Add a socket or file descriptor to a pollcb
* @param pollcb The pollcb to which to add the descriptor
* @param descriptor The descriptor to add
- * @remark If you set client_data in the descriptor, that value
- * will be returned in the client_data field whenever this
- * descriptor is signalled in apr_pollcb_poll().
+ * @remark If you set client_data in the descriptor, that value will be
+ * returned in the client_data field whenever this descriptor is
+ * signalled in apr_pollcb_poll().
* @remark Unlike the apr_pollset API, the descriptor is not copied, and users
- * must retain the memory used by descriptor, as the same pointer will be
- * returned to them from apr_pollcb_poll.
+ * must retain the memory used by descriptor, as the same pointer will
+ * be returned to them from apr_pollcb_poll.
+ * @remark Do not add the same socket or file descriptor to the same pollcb
+ * multiple times, even if the requested events differ for the
+ * different calls to apr_pollcb_add(). If the events of interest
+ * for a descriptor change, you must first remove the descriptor
+ * from the pollcb with apr_pollcb_remove(), then add it again
+ * specifying all requested events.
*/
APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
apr_pollfd_t *descriptor);
@@ -242,6 +353,9 @@ APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
* Remove a descriptor from a pollcb
* @param pollcb The pollcb from which to remove the descriptor
* @param descriptor The descriptor to remove
+ * @remark apr_pollcb_remove() cannot be used to remove a subset of requested
+ * events for a descriptor. The reqevents field in the apr_pollfd_t
+ * parameter must contain the same value when removing as when adding.
*/
APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
apr_pollfd_t *descriptor);
@@ -257,12 +371,16 @@ typedef apr_status_t (*apr_pollcb_cb_t)(void *baton, apr_pollfd_t *descriptor);
/**
* Block for activity on the descriptor(s) in a pollcb
* @param pollcb The pollcb to use
- * @param timeout The amount of time in microseconds to wait. This is
- * a maximum, not a minimum. If a descriptor is signalled, we
- * will wake up before this time. A negative number means
- * wait until a descriptor is signalled.
- * @param func Callback function to call for each active socket
+ * @param timeout The amount of time in microseconds to wait. This is a
+ * maximum, not a minimum. If a descriptor is signalled, the
+ * function will return before this time. If timeout is
+ * negative, the function will block until a descriptor is
+ * signalled.
+ * @param func Callback function to call for each active descriptor.
* @param baton Opaque baton passed to the callback function.
+ * @remark Multiple signalled conditions for the same descriptor may be reported
+ * in one or more calls to the callback function, depending on the
+ * implementation.
*/
APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
apr_interval_time_t timeout,
diff --git a/include/arch/unix/apr_arch_poll_private.h b/include/arch/unix/apr_arch_poll_private.h
index f176eac0e..a26730490 100644
--- a/include/arch/unix/apr_arch_poll_private.h
+++ b/include/arch/unix/apr_arch_poll_private.h
@@ -17,13 +17,6 @@
#ifndef APR_ARCH_POLL_PRIVATE_H
#define APR_ARCH_POLL_PRIVATE_H
-#include "apr.h"
-#include "apr_poll.h"
-#include "apr_time.h"
-#include "apr_portable.h"
-#include "apr_arch_networkio.h"
-#include "apr_arch_file_io.h"
-
#if HAVE_POLL_H
#include <poll.h>
#endif
@@ -55,21 +48,32 @@
/* Choose the best method platform specific to use in apr_pollset */
#ifdef HAVE_KQUEUE
#define POLLSET_USES_KQUEUE
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_KQUEUE
#elif defined(HAVE_PORT_CREATE)
#define POLLSET_USES_PORT
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_PORT
#elif defined(HAVE_EPOLL)
#define POLLSET_USES_EPOLL
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_EPOLL
#elif defined(HAVE_POLL)
#define POLLSET_USES_POLL
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_POLL
#else
#define POLLSET_USES_SELECT
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_SELECT
#endif
+#ifdef WIN32
+#define POLL_USES_SELECT
+#undef POLLSET_DEFAULT_METHOD
+#define POLLSET_DEFAULT_METHOD APR_POLLSET_SELECT
+#else
#ifdef HAVE_POLL
#define POLL_USES_POLL
#else
#define POLL_USES_SELECT
#endif
+#endif
#if defined(POLLSET_USES_KQUEUE) || defined(POLLSET_USES_EPOLL) || defined(POLLSET_USES_PORT)
@@ -79,10 +83,10 @@
#include "apr_thread_mutex.h"
#define pollset_lock_rings() \
if (pollset->flags & APR_POLLSET_THREADSAFE) \
- apr_thread_mutex_lock(pollset->ring_lock);
+ apr_thread_mutex_lock(pollset->p->ring_lock);
#define pollset_unlock_rings() \
if (pollset->flags & APR_POLLSET_THREADSAFE) \
- apr_thread_mutex_unlock(pollset->ring_lock);
+ apr_thread_mutex_unlock(pollset->p->ring_lock);
#else
#define pollset_lock_rings()
#define pollset_unlock_rings()
@@ -93,8 +97,72 @@ typedef struct pfd_elem_t pfd_elem_t;
struct pfd_elem_t {
APR_RING_ENTRY(pfd_elem_t) link;
apr_pollfd_t pfd;
+#ifdef HAVE_PORT_CREATE
+ int on_query_ring;
+#endif
+};
+
+#endif
+
+typedef struct apr_pollset_private_t apr_pollset_private_t;
+typedef struct apr_pollset_provider_t apr_pollset_provider_t;
+typedef struct apr_pollcb_provider_t apr_pollcb_provider_t;
+struct apr_pollset_t
+{
+ apr_pool_t *pool;
+ apr_uint32_t nelts;
+ apr_uint32_t nalloc;
+ apr_uint32_t flags;
+ /* Pipe descriptors used for wakeup */
+ apr_file_t *wakeup_pipe[2];
+ apr_pollset_private_t *p;
+ apr_pollset_provider_t *provider;
};
+typedef union {
+#if defined(HAVE_EPOLL)
+ struct epoll_event *epoll;
#endif
+#if defined(HAVE_PORT_CREATE)
+ port_event_t *port;
+#endif
+#if defined(HAVE_KQUEUE)
+ struct kevent *ke;
+#endif
+#if defined(HAVE_POLL)
+ struct pollfd *ps;
+#endif
+ void *undef;
+} apr_pollcb_pset;
+
+struct apr_pollcb_t {
+ apr_pool_t *pool;
+ apr_uint32_t nelts;
+ apr_uint32_t nalloc;
+ int fd;
+ apr_pollcb_pset pollset;
+ apr_pollfd_t **copyset;
+ apr_pollcb_provider_t *provider;
+};
+
+struct apr_pollset_provider_t {
+ apr_status_t (*create)(apr_pollset_t *, apr_uint32_t, apr_pool_t *, apr_uint32_t);
+ apr_status_t (*add)(apr_pollset_t *, const apr_pollfd_t *);
+ apr_status_t (*remove)(apr_pollset_t *, const apr_pollfd_t *);
+ apr_status_t (*poll)(apr_pollset_t *, apr_interval_time_t, apr_int32_t *, const apr_pollfd_t **);
+ apr_status_t (*cleanup)(apr_pollset_t *);
+ const char *name;
+};
+
+struct apr_pollcb_provider_t {
+ apr_status_t (*create)(apr_pollcb_t *, apr_uint32_t, apr_pool_t *, apr_uint32_t);
+ apr_status_t (*add)(apr_pollcb_t *, apr_pollfd_t *);
+ apr_status_t (*remove)(apr_pollcb_t *, apr_pollfd_t *);
+ apr_status_t (*poll)(apr_pollcb_t *, apr_interval_time_t, apr_pollcb_cb_t, void *);
+ const char *name;
+};
+
+/* Private functions */
+void apr_pollset_drain_wakeup_pipe(apr_pollset_t *pollset);
#endif /* APR_ARCH_POLL_PRIVATE_H */
diff --git a/libapr.dsp b/libapr.dsp
index 1210013a6..485f1c761 100644
--- a/libapr.dsp
+++ b/libapr.dsp
@@ -464,6 +464,14 @@ SOURCE=.\passwd\apr_getpass.c
# PROP Default_Filter ""
# Begin Source File
+SOURCE=.\poll\unix\pollcb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\poll\unix\pollset.c
+# End Source File
+# Begin Source File
+
SOURCE=.\poll\unix\select.c
# End Source File
# End Group
diff --git a/poll/os2/pollset.c b/poll/os2/pollset.c
index 0680c29c0..e77dc9a3e 100644
--- a/poll/os2/pollset.c
+++ b/poll/os2/pollset.c
@@ -51,7 +51,14 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
return APR_SUCCESS;
}
-
+APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **pollset,
+ apr_uint32_t size,
+ apr_pool_t *p,
+ apr_uint32_t flags,
+ apr_pollset_method_e method)
+{
+ return apr_pollset_create(pollset, size, p, flags);
+}
APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
{
diff --git a/poll/unix/epoll.c b/poll/unix/epoll.c
index 0c5fa8f67..326dac7b1 100644
--- a/poll/unix/epoll.c
+++ b/poll/unix/epoll.c
@@ -14,10 +14,16 @@
* limitations under the License.
*/
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
#include "apr_arch_poll_private.h"
#include "apr_arch_inherit.h"
-#ifdef POLLSET_USES_EPOLL
+#if defined(HAVE_EPOLL)
static apr_int16_t get_epoll_event(apr_int16_t event)
{
@@ -29,11 +35,7 @@ static apr_int16_t get_epoll_event(apr_int16_t event)
rv |= EPOLLPRI;
if (event & APR_POLLOUT)
rv |= EPOLLOUT;
- if (event & APR_POLLERR)
- rv |= EPOLLERR;
- if (event & APR_POLLHUP)
- rv |= EPOLLHUP;
- /* APR_POLLNVAL is not handled by epoll. */
+ /* APR_POLLNVAL is not handled by epoll. EPOLLERR and EPOLLHUP are return-only */
return rv;
}
@@ -57,17 +59,11 @@ static apr_int16_t get_epoll_revent(apr_int16_t event)
return rv;
}
-struct apr_pollset_t
+struct apr_pollset_private_t
{
- apr_pool_t *pool;
- apr_uint32_t nelts;
- apr_uint32_t nalloc;
int epoll_fd;
struct epoll_event *pollset;
apr_pollfd_t *result_set;
- apr_uint32_t flags;
- /* Pipe descriptors used for wakeup */
- apr_file_t *wakeup_pipe[2];
#if APR_HAS_THREADS
/* A thread mutex to protect operations on the rings */
apr_thread_mutex_t *ring_lock;
@@ -81,81 +77,29 @@ struct apr_pollset_t
APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring;
};
-static apr_status_t backend_cleanup(void *p_)
+static apr_status_t impl_pollset_cleanup(apr_pollset_t *pollset)
{
- apr_pollset_t *pollset = (apr_pollset_t *) p_;
- close(pollset->epoll_fd);
- if (pollset->flags & APR_POLLSET_WAKEABLE) {
- /* Close both sides of the wakeup pipe */
- if (pollset->wakeup_pipe[0]) {
- apr_file_close(pollset->wakeup_pipe[0]);
- pollset->wakeup_pipe[0] = NULL;
- }
- if (pollset->wakeup_pipe[1]) {
- apr_file_close(pollset->wakeup_pipe[1]);
- pollset->wakeup_pipe[1] = NULL;
- }
- }
+ close(pollset->p->epoll_fd);
return APR_SUCCESS;
}
-/* Create a dummy wakeup pipe for interrupting the poller
- */
-static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
-{
- apr_status_t rv;
- apr_pollfd_t fd;
-
- if ((rv = apr_file_pipe_create(&pollset->wakeup_pipe[0],
- &pollset->wakeup_pipe[1],
- pollset->pool)) != APR_SUCCESS)
- return rv;
- fd.reqevents = APR_POLLIN;
- fd.desc_type = APR_POLL_FILE;
- fd.desc.f = pollset->wakeup_pipe[0];
- /* Add the pipe to the pollset
- */
- return apr_pollset_add(pollset, &fd);
-}
-
-/* Read and discard what's ever in the wakeup pipe.
- */
-static void drain_wakeup_pipe(apr_pollset_t *pollset)
-{
- char rb[512];
- apr_size_t nr = sizeof(rb);
-
- while (apr_file_read(pollset->wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
- /* Although we write just one byte to the other end of the pipe
- * during wakeup, multiple treads could call the wakeup.
- * So simply drain out from the input side of the pipe all
- * the data.
- */
- if (nr != sizeof(rb))
- break;
- }
-}
-APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
- apr_uint32_t size,
- apr_pool_t *p,
- apr_uint32_t flags)
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
+ apr_uint32_t size,
+ apr_pool_t *p,
+ apr_uint32_t flags)
{
apr_status_t rv;
int fd;
- if (flags & APR_POLLSET_WAKEABLE) {
- /* Add room for wakeup descriptor */
- size++;
- }
#ifdef HAVE_EPOLL_CREATE1
fd = epoll_create1(EPOLL_CLOEXEC);
#else
fd = epoll_create(size);
#endif
if (fd < 0) {
- *pollset = NULL;
- return errno;
+ pollset->p = NULL;
+ return apr_get_netos_error();
}
#ifndef HAVE_EPOLL_CREATE1
@@ -171,54 +115,36 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
}
#endif
- *pollset = apr_palloc(p, sizeof(**pollset));
+ pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
#if APR_HAS_THREADS
if ((flags & APR_POLLSET_THREADSAFE) &&
!(flags & APR_POLLSET_NOCOPY) &&
- ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock,
+ ((rv = apr_thread_mutex_create(&pollset->p->ring_lock,
APR_THREAD_MUTEX_DEFAULT,
p)) != APR_SUCCESS)) {
- *pollset = NULL;
+ pollset->p = NULL;
return rv;
}
#else
if (flags & APR_POLLSET_THREADSAFE) {
- *pollset = NULL;
+ pollset->p = NULL;
return APR_ENOTIMPL;
}
#endif
- (*pollset)->nelts = 0;
- (*pollset)->nalloc = size;
- (*pollset)->flags = flags;
- (*pollset)->pool = p;
- (*pollset)->epoll_fd = fd;
- (*pollset)->pollset = apr_palloc(p, size * sizeof(struct epoll_event));
- (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+ pollset->p->epoll_fd = fd;
+ pollset->p->pollset = apr_palloc(p, size * sizeof(struct epoll_event));
+ pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
if (!(flags & APR_POLLSET_NOCOPY)) {
- APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link);
- APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link);
- APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link);
- }
- if (flags & APR_POLLSET_WAKEABLE) {
- /* Create wakeup pipe */
- if ((rv = create_wakeup_pipe(*pollset)) != APR_SUCCESS) {
- close(fd);
- *pollset = NULL;
- return rv;
- }
+ APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link);
+ APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link);
+ APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link);
}
- apr_pool_cleanup_register(p, *pollset, backend_cleanup, backend_cleanup);
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
-{
- return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup);
-}
-
-APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
- const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+ const apr_pollfd_t *descriptor)
{
struct epoll_event ev = {0};
int ret = -1;
@@ -233,8 +159,8 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
else {
pollset_lock_rings();
- if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) {
- elem = APR_RING_FIRST(&(pollset->free_ring));
+ if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) {
+ elem = APR_RING_FIRST(&(pollset->p->free_ring));
APR_RING_REMOVE(elem, link);
}
else {
@@ -245,27 +171,24 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
ev.data.ptr = elem;
}
if (descriptor->desc_type == APR_POLL_SOCKET) {
- ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD,
+ ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_ADD,
descriptor->desc.s->socketdes, &ev);
}
else {
- ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD,
+ ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_ADD,
descriptor->desc.f->filedes, &ev);
}
- if (pollset->flags & APR_POLLSET_NOCOPY) {
- if (0 != ret) {
- rv = APR_EBADF;
- }
+ if (0 != ret) {
+ rv = apr_get_netos_error();
}
- else {
- if (0 != ret) {
- rv = APR_EBADF;
- APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link);
+
+ if (!(pollset->flags & APR_POLLSET_NOCOPY)) {
+ if (rv != APR_SUCCESS) {
+ APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link);
}
else {
- pollset->nelts++;
- APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link);
+ APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link);
}
pollset_unlock_rings();
}
@@ -273,22 +196,22 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
- const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_remove(apr_pollset_t *pollset,
+ const apr_pollfd_t *descriptor)
{
pfd_elem_t *ep;
apr_status_t rv = APR_SUCCESS;
- struct epoll_event ev;
+ struct epoll_event ev = {0}; /* ignored, but must be passed with
+ * kernel < 2.6.9
+ */
int ret = -1;
- ev.events = get_epoll_event(descriptor->reqevents);
-
if (descriptor->desc_type == APR_POLL_SOCKET) {
- ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL,
+ ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_DEL,
descriptor->desc.s->socketdes, &ev);
}
else {
- ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL,
+ ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_DEL,
descriptor->desc.f->filedes, &ev);
}
if (ret < 0) {
@@ -298,18 +221,16 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
if (!(pollset->flags & APR_POLLSET_NOCOPY)) {
pollset_lock_rings();
- if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) {
- for (ep = APR_RING_FIRST(&(pollset->query_ring));
- ep != APR_RING_SENTINEL(&(pollset->query_ring),
- pfd_elem_t, link);
- ep = APR_RING_NEXT(ep, link)) {
+ for (ep = APR_RING_FIRST(&(pollset->p->query_ring));
+ ep != APR_RING_SENTINEL(&(pollset->p->query_ring),
+ pfd_elem_t, link);
+ ep = APR_RING_NEXT(ep, link)) {
- if (descriptor->desc.s == ep->pfd.desc.s) {
- APR_RING_REMOVE(ep, link);
- APR_RING_INSERT_TAIL(&(pollset->dead_ring),
- ep, pfd_elem_t, link);
- break;
- }
+ if (descriptor->desc.s == ep->pfd.desc.s) {
+ APR_RING_REMOVE(ep, link);
+ APR_RING_INSERT_TAIL(&(pollset->p->dead_ring),
+ ep, pfd_elem_t, link);
+ break;
}
}
@@ -319,20 +240,20 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
apr_interval_time_t timeout,
apr_int32_t *num,
const apr_pollfd_t **descriptors)
{
int ret, i, j;
apr_status_t rv = APR_SUCCESS;
- apr_pollfd_t fd;
+ apr_pollfd_t *fdptr;
if (timeout > 0) {
timeout /= 1000;
}
- ret = epoll_wait(pollset->epoll_fd, pollset->pollset, pollset->nalloc,
+ ret = epoll_wait(pollset->p->epoll_fd, pollset->p->pollset, pollset->nalloc,
timeout);
(*num) = ret;
@@ -343,58 +264,43 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
rv = APR_TIMEUP;
}
else {
- if (pollset->flags & APR_POLLSET_NOCOPY) {
- for (i = 0, j = 0; i < ret; i++) {
- fd = *((apr_pollfd_t *) (pollset->pollset[i].data.ptr));
- /* Check if the polled descriptor is our
- * wakeup pipe. In that case do not put it result set.
- */
- if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
- fd.desc_type == APR_POLL_FILE &&
- fd.desc.f == pollset->wakeup_pipe[0]) {
- drain_wakeup_pipe(pollset);
- rv = APR_EINTR;
- }
- else {
- pollset->result_set[j] = fd;
- pollset->result_set[j].rtnevents =
- get_epoll_revent(pollset->pollset[i].events);
- j++;
- }
+ for (i = 0, j = 0; i < ret; i++) {
+ if (pollset->flags & APR_POLLSET_NOCOPY) {
+ fdptr = (apr_pollfd_t *)(pollset->p->pollset[i].data.ptr);
}
- if (((*num) = j))
- rv = APR_SUCCESS;
- }
- else {
- for (i = 0, j = 0; i < ret; i++) {
- fd = (((pfd_elem_t *) (pollset->pollset[i].data.ptr))->pfd);
- if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
- fd.desc_type == APR_POLL_FILE &&
- fd.desc.f == pollset->wakeup_pipe[0]) {
- drain_wakeup_pipe(pollset);
- rv = APR_EINTR;
- }
- else {
- pollset->result_set[j] = fd;
- pollset->result_set[j].rtnevents =
- get_epoll_revent(pollset->pollset[i].events);
- j++;
- }
+ else {
+ fdptr = &(((pfd_elem_t *) (pollset->p->pollset[i].data.ptr))->pfd);
+ }
+ /* Check if the polled descriptor is our
+ * wakeup pipe. In that case do not put it result set.
+ */
+ if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
+ fdptr->desc_type == APR_POLL_FILE &&
+ fdptr->desc.f == pollset->wakeup_pipe[0]) {
+ apr_pollset_drain_wakeup_pipe(pollset);
+ rv = APR_EINTR;
+ }
+ else {
+ pollset->p->result_set[j] = *fdptr;
+ pollset->p->result_set[j].rtnevents =
+ get_epoll_revent(pollset->p->pollset[i].events);
+ j++;
}
- if (((*num) = j))
- rv = APR_SUCCESS;
}
+ if (((*num) = j)) { /* any event besides wakeup pipe? */
+ rv = APR_SUCCESS;
- if (descriptors) {
- *descriptors = pollset->result_set;
+ if (descriptors) {
+ *descriptors = pollset->p->result_set;
+ }
}
}
if (!(pollset->flags & APR_POLLSET_NOCOPY)) {
pollset_lock_rings();
- /* Shift all PFDs in the Dead Ring to be Free Ring */
- APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link);
+ /* Shift all PFDs in the Dead Ring to the Free Ring */
+ APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link);
pollset_unlock_rings();
}
@@ -402,32 +308,28 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset)
-{
- if (pollset->flags & APR_POLLSET_WAKEABLE)
- return apr_file_putc(1, pollset->wakeup_pipe[1]);
- else
- return APR_EINIT;
-}
-
-struct apr_pollcb_t {
- apr_pool_t *pool;
- apr_uint32_t nalloc;
- struct epoll_event *pollset;
- int epoll_fd;
+static apr_pollset_provider_t impl = {
+ impl_pollset_create,
+ impl_pollset_add,
+ impl_pollset_remove,
+ impl_pollset_poll,
+ impl_pollset_cleanup,
+ "epoll"
};
+apr_pollset_provider_t *apr_pollset_provider_epoll = &impl;
+
static apr_status_t cb_cleanup(void *p_)
{
apr_pollcb_t *pollcb = (apr_pollcb_t *) p_;
- close(pollcb->epoll_fd);
+ close(pollcb->fd);
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
- apr_uint32_t size,
- apr_pool_t *p,
- apr_uint32_t flags)
+static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
+ apr_uint32_t size,
+ apr_pool_t *p,
+ apr_uint32_t flags)
{
int fd;
@@ -438,7 +340,6 @@ APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
#endif
if (fd < 0) {
- *pollcb = NULL;
return apr_get_netos_error();
}
@@ -455,18 +356,15 @@ APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
}
#endif
- *pollcb = apr_palloc(p, sizeof(**pollcb));
- (*pollcb)->nalloc = size;
- (*pollcb)->pool = p;
- (*pollcb)->epoll_fd = fd;
- (*pollcb)->pollset = apr_palloc(p, size * sizeof(struct epoll_event));
- apr_pool_cleanup_register(p, *pollcb, cb_cleanup, cb_cleanup);
+ pollcb->fd = fd;
+ pollcb->pollset.epoll = apr_palloc(p, size * sizeof(struct epoll_event));
+ apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null);
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
- apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb,
+ apr_pollfd_t *descriptor)
{
struct epoll_event ev;
int ret;
@@ -475,11 +373,11 @@ APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
ev.data.ptr = (void *)descriptor;
if (descriptor->desc_type == APR_POLL_SOCKET) {
- ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_ADD,
+ ret = epoll_ctl(pollcb->fd, EPOLL_CTL_ADD,
descriptor->desc.s->socketdes, &ev);
}
else {
- ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_ADD,
+ ret = epoll_ctl(pollcb->fd, EPOLL_CTL_ADD,
descriptor->desc.f->filedes, &ev);
}
@@ -490,21 +388,21 @@ APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
- apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb,
+ apr_pollfd_t *descriptor)
{
apr_status_t rv = APR_SUCCESS;
- struct epoll_event ev;
+ struct epoll_event ev = {0}; /* ignored, but must be passed with
+ * kernel < 2.6.9
+ */
int ret = -1;
- ev.events = get_epoll_event(descriptor->reqevents);
-
if (descriptor->desc_type == APR_POLL_SOCKET) {
- ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_DEL,
+ ret = epoll_ctl(pollcb->fd, EPOLL_CTL_DEL,
descriptor->desc.s->socketdes, &ev);
}
else {
- ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_DEL,
+ ret = epoll_ctl(pollcb->fd, EPOLL_CTL_DEL,
descriptor->desc.f->filedes, &ev);
}
@@ -516,10 +414,10 @@ APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
}
-APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
- apr_interval_time_t timeout,
- apr_pollcb_cb_t func,
- void *baton)
+static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
+ apr_interval_time_t timeout,
+ apr_pollcb_cb_t func,
+ void *baton)
{
int ret, i;
apr_status_t rv = APR_SUCCESS;
@@ -528,7 +426,7 @@ APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
timeout /= 1000;
}
- ret = epoll_wait(pollcb->epoll_fd, pollcb->pollset, pollcb->nalloc,
+ ret = epoll_wait(pollcb->fd, pollcb->pollset.epoll, pollcb->nalloc,
timeout);
if (ret < 0) {
rv = apr_get_netos_error();
@@ -538,8 +436,8 @@ APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
}
else {
for (i = 0; i < ret; i++) {
- apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset[i].data.ptr);
- pollfd->rtnevents = get_epoll_revent(pollcb->pollset[i].events);
+ apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.epoll[i].data.ptr);
+ pollfd->rtnevents = get_epoll_revent(pollcb->pollset.epoll[i].events);
rv = func(baton, pollfd);
if (rv) {
@@ -551,4 +449,14 @@ APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
return rv;
}
-#endif /* POLLSET_USES_EPOLL */
+static apr_pollcb_provider_t impl_cb = {
+ impl_pollcb_create,
+ impl_pollcb_add,
+ impl_pollcb_remove,
+ impl_pollcb_poll,
+ "epoll"
+};
+
+apr_pollcb_provider_t *apr_pollcb_provider_epoll = &impl_cb;
+
+#endif /* HAVE_EPOLL */
diff --git a/poll/unix/kqueue.c b/poll/unix/kqueue.c
index 34ec1dd42..dbe785a15 100644
--- a/poll/unix/kqueue.c
+++ b/poll/unix/kqueue.c
@@ -14,10 +14,16 @@
* limitations under the License.
*/
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
#include "apr_arch_poll_private.h"
#include "apr_arch_inherit.h"
-#ifdef POLLSET_USES_KQUEUE
+#ifdef HAVE_KQUEUE
static apr_int16_t get_kqueue_revent(apr_int16_t event, apr_int16_t flags)
{
@@ -25,28 +31,25 @@ static apr_int16_t get_kqueue_revent(apr_int16_t event, apr_int16_t flags)
if (event == EVFILT_READ)
rv |= APR_POLLIN;
- if (event == EVFILT_WRITE)
+ else if (event == EVFILT_WRITE)
rv |= APR_POLLOUT;
if (flags & EV_EOF)
rv |= APR_POLLHUP;
- if (flags & EV_ERROR)
- rv |= APR_POLLERR;
-
+ /* APR_POLLPRI, APR_POLLERR, and APR_POLLNVAL are not handled by this
+ * implementation.
+ * TODO: See if EV_ERROR + certain system errors in the returned data field
+ * should map to APR_POLLNVAL.
+ */
return rv;
}
-struct apr_pollset_t
+struct apr_pollset_private_t
{
- apr_pool_t *pool;
- apr_uint32_t nelts;
- apr_uint32_t nalloc;
int kqueue_fd;
struct kevent kevent;
+ apr_uint32_t setsize;
struct kevent *ke_set;
apr_pollfd_t *result_set;
- apr_uint32_t flags;
- /* Pipe descriptors used for wakeup */
- apr_file_t *wakeup_pipe[2];
#if APR_HAS_THREADS
/* A thread mutex to protect operations on the rings */
apr_thread_mutex_t *ring_lock;
@@ -60,140 +63,77 @@ struct apr_pollset_t
APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring;
};
-static apr_status_t backend_cleanup(void *p_)
+static apr_status_t impl_pollset_cleanup(apr_pollset_t *pollset)
{
- apr_pollset_t *pollset = (apr_pollset_t *) p_;
- close(pollset->kqueue_fd);
- if (pollset->flags & APR_POLLSET_WAKEABLE) {
- /* Close both sides of the wakeup pipe */
- if (pollset->wakeup_pipe[0]) {
- apr_file_close(pollset->wakeup_pipe[0]);
- pollset->wakeup_pipe[0] = NULL;
- }
- if (pollset->wakeup_pipe[1]) {
- apr_file_close(pollset->wakeup_pipe[1]);
- pollset->wakeup_pipe[1] = NULL;
- }
- }
+ close(pollset->p->kqueue_fd);
return APR_SUCCESS;
}
-/* Create a dummy wakeup pipe for interrupting the poller
- */
-static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
+ apr_uint32_t size,
+ apr_pool_t *p,
+ apr_uint32_t flags)
{
apr_status_t rv;
- apr_pollfd_t fd;
-
- if ((rv = apr_file_pipe_create(&pollset->wakeup_pipe[0],
- &pollset->wakeup_pipe[1],
- pollset->pool)) != APR_SUCCESS)
- return rv;
- fd.reqevents = APR_POLLIN;
- fd.desc_type = APR_POLL_FILE;
- fd.desc.f = pollset->wakeup_pipe[0];
- /* Add the pipe to the pollset
- */
- return apr_pollset_add(pollset, &fd);
-}
-
-/* Read and discard what's ever in the wakeup pipe.
- */
-static void drain_wakeup_pipe(apr_pollset_t *pollset)
-{
- char rb[512];
- apr_size_t nr = sizeof(rb);
-
- while (apr_file_read(pollset->wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
- /* Although we write just one byte to the other end of the pipe
- * during wakeup, multiple treads could call the wakeup.
- * So simply drain out from the input side of the pipe all
- * the data.
- */
- if (nr != sizeof(rb))
- break;
- }
-}
-
-APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
- apr_uint32_t size,
- apr_pool_t *p,
- apr_uint32_t flags)
-{
- apr_status_t rv = APR_SUCCESS;
- *pollset = apr_palloc(p, sizeof(**pollset));
+ pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
#if APR_HAS_THREADS
if (flags & APR_POLLSET_THREADSAFE &&
- ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock,
+ ((rv = apr_thread_mutex_create(&pollset->p->ring_lock,
APR_THREAD_MUTEX_DEFAULT,
p)) != APR_SUCCESS)) {
- *pollset = NULL;
+ pollset->p = NULL;
return rv;
}
#else
if (flags & APR_POLLSET_THREADSAFE) {
- *pollset = NULL;
+ pollset->p = NULL;
return APR_ENOTIMPL;
}
#endif
- if (flags & APR_POLLSET_WAKEABLE) {
- /* Add room for wakeup descriptor */
- size++;
- }
- (*pollset)->nelts = 0;
- (*pollset)->nalloc = size;
- (*pollset)->flags = flags;
- (*pollset)->pool = p;
+ /* POLLIN and POLLOUT are represented in different returned
+ * events, so we need 2 entries per descriptor in the result set,
+ * both for what is returned by kevent() and what is returned to
+ * the caller of apr_pollset_poll() (since it doesn't spend the
+ * CPU to coalesce separate APR_POLLIN and APR_POLLOUT events
+ * for the same descriptor)
+ */
+ pollset->p->setsize = 2 * size;
- (*pollset)->ke_set =
- (struct kevent *) apr_palloc(p, size * sizeof(struct kevent));
+ pollset->p->ke_set =
+ (struct kevent *) apr_palloc(p, pollset->p->setsize * sizeof(struct kevent));
- memset((*pollset)->ke_set, 0, size * sizeof(struct kevent));
+ memset(pollset->p->ke_set, 0, pollset->p->setsize * sizeof(struct kevent));
- (*pollset)->kqueue_fd = kqueue();
+ pollset->p->kqueue_fd = kqueue();
- if ((*pollset)->kqueue_fd == -1) {
+ if (pollset->p->kqueue_fd == -1) {
+ pollset->p = NULL;
return apr_get_netos_error();
}
{
int flags;
- if ((flags = fcntl((*pollset)->kqueue_fd, F_GETFD)) == -1)
+ if ((flags = fcntl(pollset->p->kqueue_fd, F_GETFD)) == -1)
return errno;
flags |= FD_CLOEXEC;
- if (fcntl((*pollset)->kqueue_fd, F_SETFD, flags) == -1)
+ if (fcntl(pollset->p->kqueue_fd, F_SETFD, flags) == -1)
return errno;
}
- (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
-
- APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link);
- APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link);
- APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link);
- if (flags & APR_POLLSET_WAKEABLE) {
- /* Create wakeup pipe */
- if ((rv = create_wakeup_pipe(*pollset)) != APR_SUCCESS) {
- close((*pollset)->kqueue_fd);
- *pollset = NULL;
- return rv;
- }
- }
- apr_pool_cleanup_register(p, (void *) (*pollset), backend_cleanup,
- apr_pool_cleanup_null);
+ pollset->p->result_set = apr_palloc(p, pollset->p->setsize * sizeof(apr_pollfd_t));
- return rv;
-}
+ APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link);
+ APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link);
+ APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link);
-APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset)
-{
- return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup);
+ return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
- const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+ const apr_pollfd_t *descriptor)
{
apr_os_sock_t fd;
pfd_elem_t *elem;
@@ -201,8 +141,8 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
pollset_lock_rings();
- if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) {
- elem = APR_RING_FIRST(&(pollset->free_ring));
+ if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) {
+ elem = APR_RING_FIRST(&(pollset->p->free_ring));
APR_RING_REMOVE(elem, link);
}
else {
@@ -219,29 +159,28 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
}
if (descriptor->reqevents & APR_POLLIN) {
- EV_SET(&pollset->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, elem);
+ EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, elem);
- if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0,
+ if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0,
NULL) == -1) {
rv = apr_get_netos_error();
}
}
if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) {
- EV_SET(&pollset->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, elem);
+ EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, elem);
- if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0,
+ if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0,
NULL) == -1) {
rv = apr_get_netos_error();
}
}
if (rv == APR_SUCCESS) {
- pollset->nelts++;
- APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link);
+ APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link);
}
else {
- APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link);
+ APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link);
}
pollset_unlock_rings();
@@ -249,11 +188,11 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
- const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_remove(apr_pollset_t *pollset,
+ const apr_pollfd_t *descriptor)
{
pfd_elem_t *ep;
- apr_status_t rv = APR_SUCCESS;
+ apr_status_t rv;
apr_os_sock_t fd;
pollset_lock_rings();
@@ -265,36 +204,35 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
fd = descriptor->desc.f->filedes;
}
+ rv = APR_NOTFOUND; /* unless at least one of the specified conditions is */
if (descriptor->reqevents & APR_POLLIN) {
- EV_SET(&pollset->kevent, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
+ EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
- if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0,
- NULL) == -1) {
- rv = APR_NOTFOUND;
+ if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0,
+ NULL) != -1) {
+ rv = APR_SUCCESS;
}
}
- if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) {
- EV_SET(&pollset->kevent, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
+ if (descriptor->reqevents & APR_POLLOUT) {
+ EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
- if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0,
- NULL) == -1) {
- rv = APR_NOTFOUND;
+ if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0,
+ NULL) != -1) {
+ rv = APR_SUCCESS;
}
}
- if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) {
- for (ep = APR_RING_FIRST(&(pollset->query_ring));
- ep != APR_RING_SENTINEL(&(pollset->query_ring),
- pfd_elem_t, link);
- ep = APR_RING_NEXT(ep, link)) {
+ for (ep = APR_RING_FIRST(&(pollset->p->query_ring));
+ ep != APR_RING_SENTINEL(&(pollset->p->query_ring),
+ pfd_elem_t, link);
+ ep = APR_RING_NEXT(ep, link)) {
- if (descriptor->desc.s == ep->pfd.desc.s) {
- APR_RING_REMOVE(ep, link);
- APR_RING_INSERT_TAIL(&(pollset->dead_ring),
- ep, pfd_elem_t, link);
- break;
- }
+ if (descriptor->desc.s == ep->pfd.desc.s) {
+ APR_RING_REMOVE(ep, link);
+ APR_RING_INSERT_TAIL(&(pollset->p->dead_ring),
+ ep, pfd_elem_t, link);
+ break;
}
}
@@ -303,10 +241,10 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
- apr_interval_time_t timeout,
- apr_int32_t *num,
- const apr_pollfd_t **descriptors)
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
+ apr_interval_time_t timeout,
+ apr_int32_t *num,
+ const apr_pollfd_t **descriptors)
{
int ret, i, j;
struct timespec tv, *tvptr;
@@ -322,8 +260,8 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
tvptr = &tv;
}
- ret = kevent(pollset->kqueue_fd, NULL, 0, pollset->ke_set, pollset->nalloc,
- tvptr);
+ ret = kevent(pollset->p->kqueue_fd, NULL, 0, pollset->p->ke_set,
+ pollset->p->setsize, tvptr);
(*num) = ret;
if (ret < 0) {
rv = apr_get_netos_error();
@@ -333,72 +271,68 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
}
else {
for (i = 0, j = 0; i < ret; i++) {
- fd = (((pfd_elem_t*)(pollset->ke_set[i].udata))->pfd);
+ fd = (((pfd_elem_t*)(pollset->p->ke_set[i].udata))->pfd);
if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
fd.desc_type == APR_POLL_FILE &&
fd.desc.f == pollset->wakeup_pipe[0]) {
- drain_wakeup_pipe(pollset);
+ apr_pollset_drain_wakeup_pipe(pollset);
rv = APR_EINTR;
}
else {
- pollset->result_set[j] = fd;
- pollset->result_set[j].rtnevents =
- get_kqueue_revent(pollset->ke_set[i].filter,
- pollset->ke_set[i].flags);
+ pollset->p->result_set[j] = fd;
+ pollset->p->result_set[j].rtnevents =
+ get_kqueue_revent(pollset->p->ke_set[i].filter,
+ pollset->p->ke_set[i].flags);
j++;
}
}
- if ((*num = j))
+ if ((*num = j)) { /* any event besides wakeup pipe? */
rv = APR_SUCCESS;
- if (descriptors) {
- *descriptors = pollset->result_set;
+ if (descriptors) {
+ *descriptors = pollset->p->result_set;
+ }
}
}
pollset_lock_rings();
- /* Shift all PFDs in the Dead Ring to be Free Ring */
- APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link);
+ /* Shift all PFDs in the Dead Ring to the Free Ring */
+ APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring),
+ pfd_elem_t, link);
pollset_unlock_rings();
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset)
-{
- if (pollset->flags & APR_POLLSET_WAKEABLE)
- return apr_file_putc(1, pollset->wakeup_pipe[1]);
- else
- return APR_EINIT;
-}
-
-struct apr_pollcb_t {
- apr_pool_t *pool;
- apr_uint32_t nalloc;
- struct kevent *pollset;
- int kqfd;
+static apr_pollset_provider_t impl = {
+ impl_pollset_create,
+ impl_pollset_add,
+ impl_pollset_remove,
+ impl_pollset_poll,
+ impl_pollset_cleanup,
+ "kqueue"
};
+apr_pollset_provider_t *apr_pollset_provider_kqueue = &impl;
+
static apr_status_t cb_cleanup(void *b_)
{
apr_pollcb_t *pollcb = (apr_pollcb_t *) b_;
- close(pollcb->kqfd);
+ close(pollcb->fd);
return APR_SUCCESS;
}
-
-APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
- apr_uint32_t size,
- apr_pool_t *p,
- apr_uint32_t flags)
+static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
+ apr_uint32_t size,
+ apr_pool_t *p,
+ apr_uint32_t flags)
{
int fd;
fd = kqueue();
if (fd < 0) {
- *pollcb = NULL;
return apr_get_netos_error();
}
@@ -413,18 +347,15 @@ APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
return errno;
}
- *pollcb = apr_palloc(p, sizeof(**pollcb));
- (*pollcb)->nalloc = size;
- (*pollcb)->pool = p;
- (*pollcb)->kqfd = fd;
- (*pollcb)->pollset = (struct kevent *)apr_pcalloc(p, size * sizeof(struct kevent));
- apr_pool_cleanup_register(p, *pollcb, cb_cleanup, cb_cleanup);
+ pollcb->fd = fd;
+ pollcb->pollset.ke = (struct kevent *)apr_pcalloc(p, 2 * size * sizeof(struct kevent));
+ apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null);
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
- apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb,
+ apr_pollfd_t *descriptor)
{
apr_os_sock_t fd;
struct kevent ev;
@@ -440,7 +371,7 @@ APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
if (descriptor->reqevents & APR_POLLIN) {
EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, descriptor);
- if (kevent(pollcb->kqfd, &ev, 1, NULL, 0, NULL) == -1) {
+ if (kevent(pollcb->fd, &ev, 1, NULL, 0, NULL) == -1) {
rv = apr_get_netos_error();
}
}
@@ -448,7 +379,7 @@ APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) {
EV_SET(&ev, fd, EVFILT_WRITE, EV_ADD, 0, 0, descriptor);
- if (kevent(pollcb->kqfd, &ev, 1, NULL, 0, NULL) == -1) {
+ if (kevent(pollcb->fd, &ev, 1, NULL, 0, NULL) == -1) {
rv = apr_get_netos_error();
}
}
@@ -456,10 +387,10 @@ APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
- apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb,
+ apr_pollfd_t *descriptor)
{
- apr_status_t rv = APR_SUCCESS;
+ apr_status_t rv;
struct kevent ev;
apr_os_sock_t fd;
@@ -469,23 +400,21 @@ APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
else {
fd = descriptor->desc.f->filedes;
}
-
+
+ rv = APR_NOTFOUND; /* unless at least one of the specified conditions is */
if (descriptor->reqevents & APR_POLLIN) {
EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
- if (kevent(pollcb->kqfd, &ev, 1, NULL, 0, NULL) == -1) {
- rv = APR_NOTFOUND;
+ if (kevent(pollcb->fd, &ev, 1, NULL, 0, NULL) != -1) {
+ rv = APR_SUCCESS;
}
}
- if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) {
- /* XXXX: this is less than optimal, shouldn't we still try to
- * remove the FD even if it wasn't in the readset?
- */
+ if (descriptor->reqevents & APR_POLLOUT) {
EV_SET(&ev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
- if (kevent(pollcb->kqfd, &ev, 1, NULL, 0, NULL) == -1) {
- rv = APR_NOTFOUND;
+ if (kevent(pollcb->fd, &ev, 1, NULL, 0, NULL) != -1) {
+ rv = APR_SUCCESS;
}
}
@@ -493,10 +422,10 @@ APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
}
-APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
- apr_interval_time_t timeout,
- apr_pollcb_cb_t func,
- void *baton)
+static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
+ apr_interval_time_t timeout,
+ apr_pollcb_cb_t func,
+ void *baton)
{
int ret, i;
struct timespec tv, *tvptr;
@@ -511,7 +440,7 @@ APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
tvptr = &tv;
}
- ret = kevent(pollcb->kqfd, NULL, 0, pollcb->pollset, pollcb->nalloc,
+ ret = kevent(pollcb->fd, NULL, 0, pollcb->pollset.ke, 2 * pollcb->nalloc,
tvptr);
if (ret < 0) {
@@ -522,10 +451,10 @@ APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
}
else {
for (i = 0; i < ret; i++) {
- apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset[i].udata);
+ apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset.ke[i].udata);
- pollfd->rtnevents = get_kqueue_revent(pollcb->pollset[i].filter,
- pollcb->pollset[i].flags);
+ pollfd->rtnevents = get_kqueue_revent(pollcb->pollset.ke[i].filter,
+ pollcb->pollset.ke[i].flags);
rv = func(baton, pollfd);
@@ -538,4 +467,14 @@ APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
return rv;
}
-#endif /* POLLSET_USES_KQUEUE */
+static apr_pollcb_provider_t impl_cb = {
+ impl_pollcb_create,
+ impl_pollcb_add,
+ impl_pollcb_remove,
+ impl_pollcb_poll,
+ "kqueue"
+};
+
+apr_pollcb_provider_t *apr_pollcb_provider_kqueue = &impl_cb;
+
+#endif /* HAVE_KQUEUE */
diff --git a/poll/unix/poll.c b/poll/unix/poll.c
index bd15687c1..3727b5b83 100644
--- a/poll/unix/poll.c
+++ b/poll/unix/poll.c
@@ -14,9 +14,16 @@
* limitations under the License.
*/
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_misc.h"
#include "apr_arch_poll_private.h"
-#if defined(POLL_USES_POLL) || defined(POLLSET_USES_POLL)
+#if defined(HAVE_POLL)
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
@@ -32,12 +39,7 @@ static apr_int16_t get_event(apr_int16_t event)
rv |= POLLPRI;
if (event & APR_POLLOUT)
rv |= POLLOUT;
- if (event & APR_POLLERR)
- rv |= POLLERR;
- if (event & APR_POLLHUP)
- rv |= POLLHUP;
- if (event & APR_POLLNVAL)
- rv |= POLLNVAL;
+ /* POLLERR, POLLHUP, and POLLNVAL aren't valid as requested events */
return rv;
}
@@ -62,9 +64,6 @@ static apr_int16_t get_revent(apr_int16_t event)
return rv;
}
-#endif /* POLL_USES_POLL || POLLSET_USES_POLL */
-
-
#ifdef POLL_USES_POLL
#define SMALL_POLLSET_LIMIT 8
@@ -148,163 +147,82 @@ APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t num,
#endif /* POLL_USES_POLL */
-
-#ifdef POLLSET_USES_POLL
-
-struct apr_pollset_t
+struct apr_pollset_private_t
{
- apr_pool_t *pool;
- apr_uint32_t nelts;
- apr_uint32_t nalloc;
- apr_uint32_t flags;
- /* Pipe descriptors used for wakeup */
- apr_file_t *wakeup_pipe[2];
struct pollfd *pollset;
apr_pollfd_t *query_set;
apr_pollfd_t *result_set;
};
-/* Create a dummy wakeup pipe for interrupting the poller
- */
-static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
-{
- apr_status_t rv;
- apr_pollfd_t fd;
-
- if ((rv = apr_file_pipe_create(&pollset->wakeup_pipe[0],
- &pollset->wakeup_pipe[1],
- pollset->pool)) != APR_SUCCESS)
- return rv;
- fd.reqevents = APR_POLLIN;
- fd.desc_type = APR_POLL_FILE;
- fd.desc.f = pollset->wakeup_pipe[0];
- /* Add the pipe to the pollset
- */
- return apr_pollset_add(pollset, &fd);
-}
-
-/* Read and discard what's ever in the wakeup pipe.
- */
-static void drain_wakeup_pipe(apr_pollset_t *pollset)
-{
- char rb[512];
- apr_size_t nr = sizeof(rb);
-
- while (apr_file_read(pollset->wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
- /* Although we write just one byte to the other end of the pipe
- * during wakeup, multiple treads could call the wakeup.
- * So simply drain out from the input side of the pipe all
- * the data.
- */
- if (nr != sizeof(rb))
- break;
- }
-}
-
-static apr_status_t wakeup_pipe_cleanup(void *p)
-{
- apr_pollset_t *pollset = (apr_pollset_t *) p;
- if (pollset->flags & APR_POLLSET_WAKEABLE) {
- /* Close both sides of the wakeup pipe */
- if (pollset->wakeup_pipe[0]) {
- apr_file_close(pollset->wakeup_pipe[0]);
- pollset->wakeup_pipe[0] = NULL;
- }
- if (pollset->wakeup_pipe[1]) {
- apr_file_close(pollset->wakeup_pipe[1]);
- pollset->wakeup_pipe[1] = NULL;
- }
- }
-
- return APR_SUCCESS;
-}
-
-APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
- apr_uint32_t size,
- apr_pool_t *p,
- apr_uint32_t flags)
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
+ apr_uint32_t size,
+ apr_pool_t *p,
+ apr_uint32_t flags)
{
if (flags & APR_POLLSET_THREADSAFE) {
- *pollset = NULL;
return APR_ENOTIMPL;
}
- if (flags & APR_POLLSET_WAKEABLE) {
- /* Add room for wakeup descriptor */
- size++;
+#ifdef WIN32
+ if (!APR_HAVE_LATE_DLL_FUNC(WSAPoll)) {
+ return APR_ENOTIMPL;
}
+#endif
+ pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
+ pollset->p->pollset = apr_palloc(p, size * sizeof(struct pollfd));
+ pollset->p->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+ pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
- *pollset = apr_palloc(p, sizeof(**pollset));
- (*pollset)->nelts = 0;
- (*pollset)->nalloc = size;
- (*pollset)->pool = p;
- (*pollset)->flags = flags;
- (*pollset)->pollset = apr_palloc(p, size * sizeof(struct pollfd));
- (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
- (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
-
- if (flags & APR_POLLSET_WAKEABLE) {
- apr_status_t rv;
- /* Create wakeup pipe */
- if ((rv = create_wakeup_pipe(*pollset)) != APR_SUCCESS) {
- *pollset = NULL;
- return rv;
- }
- apr_pool_cleanup_register(p, *pollset, wakeup_pipe_cleanup,
- apr_pool_cleanup_null);
- }
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
-{
- if (pollset->flags & APR_POLLSET_WAKEABLE)
- return apr_pool_cleanup_run(pollset->pool, pollset,
- wakeup_pipe_cleanup);
- else
- return APR_SUCCESS;
-}
-
-APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
- const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+ const apr_pollfd_t *descriptor)
{
if (pollset->nelts == pollset->nalloc) {
return APR_ENOMEM;
}
- pollset->query_set[pollset->nelts] = *descriptor;
+ pollset->p->query_set[pollset->nelts] = *descriptor;
if (descriptor->desc_type == APR_POLL_SOCKET) {
- pollset->pollset[pollset->nelts].fd = descriptor->desc.s->socketdes;
+ pollset->p->pollset[pollset->nelts].fd = descriptor->desc.s->socketdes;
}
else {
- pollset->pollset[pollset->nelts].fd = descriptor->desc.f->filedes;
+#if APR_FILES_AS_SOCKETS
+ pollset->p->pollset[pollset->nelts].fd = descriptor->desc.f->filedes;
+#else
+ if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
+ descriptor->desc.f == pollset->wakeup_pipe[0])
+ pollset->p->pollset[pollset->nelts].fd = (SOCKET)descriptor->desc.f->filedes;
+ else
+ return APR_EBADF;
+#endif
}
-
- pollset->pollset[pollset->nelts].events =
+ pollset->p->pollset[pollset->nelts].events =
get_event(descriptor->reqevents);
pollset->nelts++;
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
- const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_remove(apr_pollset_t *pollset,
+ const apr_pollfd_t *descriptor)
{
apr_uint32_t i;
for (i = 0; i < pollset->nelts; i++) {
- if (descriptor->desc.s == pollset->query_set[i].desc.s) {
+ if (descriptor->desc.s == pollset->p->query_set[i].desc.s) {
/* Found an instance of the fd: remove this and any other copies */
apr_uint32_t dst = i;
apr_uint32_t old_nelts = pollset->nelts;
pollset->nelts--;
for (i++; i < old_nelts; i++) {
- if (descriptor->desc.s == pollset->query_set[i].desc.s) {
+ if (descriptor->desc.s == pollset->p->query_set[i].desc.s) {
pollset->nelts--;
}
else {
- pollset->pollset[dst] = pollset->pollset[i];
- pollset->query_set[dst] = pollset->query_set[i];
+ pollset->p->pollset[dst] = pollset->p->pollset[i];
+ pollset->p->query_set[dst] = pollset->p->query_set[i];
dst++;
}
}
@@ -315,10 +233,10 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
return APR_NOTFOUND;
}
-APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
- apr_interval_time_t timeout,
- apr_int32_t *num,
- const apr_pollfd_t **descriptors)
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
+ apr_interval_time_t timeout,
+ apr_int32_t *num,
+ const apr_pollfd_t **descriptors)
{
int ret;
apr_status_t rv = APR_SUCCESS;
@@ -327,7 +245,11 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
if (timeout > 0) {
timeout /= 1000;
}
- ret = poll(pollset->pollset, pollset->nelts, timeout);
+#ifdef WIN32
+ ret = WSAPoll(pollset->p->pollset, pollset->nelts, (int)timeout);
+#else
+ ret = poll(pollset->p->pollset, pollset->nelts, timeout);
+#endif
(*num) = ret;
if (ret < 0) {
return apr_get_netos_error();
@@ -337,68 +259,168 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
}
else {
for (i = 0, j = 0; i < pollset->nelts; i++) {
- if (pollset->pollset[i].revents != 0) {
+ if (pollset->p->pollset[i].revents != 0) {
/* Check if the polled descriptor is our
* wakeup pipe. In that case do not put it result set.
*/
if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
- pollset->query_set[i].desc_type == APR_POLL_FILE &&
- pollset->query_set[i].desc.f == pollset->wakeup_pipe[0]) {
- drain_wakeup_pipe(pollset);
+ pollset->p->query_set[i].desc_type == APR_POLL_FILE &&
+ pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) {
+ apr_pollset_drain_wakeup_pipe(pollset);
rv = APR_EINTR;
}
else {
- pollset->result_set[j] = pollset->query_set[i];
- pollset->result_set[j].rtnevents =
- get_revent(pollset->pollset[i].revents);
+ pollset->p->result_set[j] = pollset->p->query_set[i];
+ pollset->p->result_set[j].rtnevents =
+ get_revent(pollset->p->pollset[i].revents);
j++;
}
}
}
- if (((*num) = j)) {
+ if (((*num) = j) > 0)
rv = APR_SUCCESS;
- }
}
if (descriptors && (*num))
- *descriptors = pollset->result_set;
+ *descriptors = pollset->p->result_set;
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset)
+static apr_pollset_provider_t impl = {
+ impl_pollset_create,
+ impl_pollset_add,
+ impl_pollset_remove,
+ impl_pollset_poll,
+ NULL,
+ "poll"
+};
+
+apr_pollset_provider_t *apr_pollset_provider_poll = &impl;
+
+/* Poll method pollcb.
+ * This is probably usable only for WIN32 having WSAPoll
+ */
+static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
+ apr_uint32_t size,
+ apr_pool_t *p,
+ apr_uint32_t flags)
{
- if (pollset->flags & APR_POLLSET_WAKEABLE)
- return apr_file_putc(1, pollset->wakeup_pipe[1]);
- else
- return APR_EINIT;
+#if APR_HAS_THREADS
+ return APR_ENOTIMPL;
+#endif
+
+ pollcb->fd = -1;
+#ifdef WIN32
+ if (!APR_HAVE_LATE_DLL_FUNC(WSAPoll)) {
+ return APR_ENOTIMPL;
+ }
+#endif
+
+ pollcb->pollset.ps = apr_palloc(p, size * sizeof(struct pollfd));
+ pollcb->copyset = apr_palloc(p, size * sizeof(apr_pollfd_t *));
+
+ return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
- apr_uint32_t size,
- apr_pool_t *p,
- apr_uint32_t flags)
+static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb,
+ apr_pollfd_t *descriptor)
{
- return APR_ENOTIMPL;
+ if (pollcb->nelts == pollcb->nalloc) {
+ return APR_ENOMEM;
+ }
+
+ if (descriptor->desc_type == APR_POLL_SOCKET) {
+ pollcb->pollset.ps[pollcb->nelts].fd = descriptor->desc.s->socketdes;
+ }
+ else {
+#if APR_FILES_AS_SOCKETS
+ pollcb->pollset.ps[pollcb->nelts].fd = descriptor->desc.f->filedes;
+#else
+ return APR_EBADF;
+#endif
+ }
+
+ pollcb->pollset.ps[pollcb->nelts].events =
+ get_event(descriptor->reqevents);
+ pollcb->copyset[pollcb->nelts] = descriptor;
+ pollcb->nelts++;
+
+ return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
- apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb,
+ apr_pollfd_t *descriptor)
{
- return APR_ENOTIMPL;
+ apr_uint32_t i;
+
+ for (i = 0; i < pollcb->nelts; i++) {
+ if (descriptor->desc.s == pollcb->copyset[i]->desc.s) {
+ /* Found an instance of the fd: remove this and any other copies */
+ apr_uint32_t dst = i;
+ apr_uint32_t old_nelts = pollcb->nelts;
+ pollcb->nelts--;
+ for (i++; i < old_nelts; i++) {
+ if (descriptor->desc.s == pollcb->copyset[i]->desc.s) {
+ pollcb->nelts--;
+ }
+ else {
+ pollcb->pollset.ps[dst] = pollcb->pollset.ps[i];
+ pollcb->copyset[dst] = pollcb->copyset[i];
+ dst++;
+ }
+ }
+ return APR_SUCCESS;
+ }
+ }
+
+ return APR_NOTFOUND;
}
-APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
- apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
+ apr_interval_time_t timeout,
+ apr_pollcb_cb_t func,
+ void *baton)
{
- return APR_ENOTIMPL;
+ int ret;
+ apr_status_t rv = APR_SUCCESS;
+ apr_uint32_t i;
+
+ if (timeout > 0) {
+ timeout /= 1000;
+ }
+#ifdef WIN32
+ ret = WSAPoll(pollcb->pollset.ps, pollcb->nelts, (int)timeout);
+#else
+ ret = poll(pollcb->pollset.ps, pollcb->nelts, timeout);
+#endif
+ if (ret < 0) {
+ return apr_get_netos_error();
+ }
+ else if (ret == 0) {
+ return APR_TIMEUP;
+ }
+ else {
+ for (i = 0; i < pollcb->nelts; i++) {
+ if (pollcb->pollset.ps[i].revents != 0) {
+ apr_pollfd_t *pollfd = pollcb->copyset[i];
+ pollfd->rtnevents = get_revent(pollcb->pollset.ps[i].revents);
+ rv = func(baton, pollfd);
+ if (rv) {
+ return rv;
+ }
+ }
+ }
+ }
+ return rv;
}
+static apr_pollcb_provider_t impl_cb = {
+ impl_pollcb_create,
+ impl_pollcb_add,
+ impl_pollcb_remove,
+ impl_pollcb_poll,
+ "poll"
+};
-APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
- apr_interval_time_t timeout,
- apr_pollcb_cb_t func,
- void *baton)
-{
- return APR_ENOTIMPL;
-}
+apr_pollcb_provider_t *apr_pollcb_provider_poll = &impl_cb;
-#endif /* POLLSET_USES_POLL */
+#endif /* HAVE_POLL */
diff --git a/poll/unix/port.c b/poll/unix/port.c
index c5d98749e..6e33196de 100644
--- a/poll/unix/port.c
+++ b/poll/unix/port.c
@@ -14,11 +14,17 @@
* limitations under the License.
*/
-#include "apr_arch_poll_private.h"
+#include "apr.h"
+#include "apr_poll.h"
+#include "apr_time.h"
+#include "apr_portable.h"
#include "apr_atomic.h"
+#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
+#include "apr_arch_poll_private.h"
#include "apr_arch_inherit.h"
-#ifdef POLLSET_USES_PORT
+#if defined(HAVE_PORT_CREATE)
static apr_int16_t get_event(apr_int16_t event)
{
@@ -56,16 +62,11 @@ static apr_int16_t get_revent(apr_int16_t event)
}
-struct apr_pollset_t
+struct apr_pollset_private_t
{
- apr_pool_t *pool;
- apr_uint32_t nalloc;
int port_fd;
port_event_t *port_set;
apr_pollfd_t *result_set;
- apr_uint32_t flags;
- /* Pipe descriptors used for wakeup */
- apr_file_t *wakeup_pipe[2];
#if APR_HAS_THREADS
/* A thread mutex to protect operations on the rings */
apr_thread_mutex_t *ring_lock;
@@ -137,138 +138,67 @@ static apr_status_t call_port_getn(int port, port_event_t list[],
return rv;
}
-static apr_status_t backend_cleanup(void *p_)
+static apr_status_t impl_pollset_cleanup(apr_pollset_t *pollset)
{
- apr_pollset_t *pollset = (apr_pollset_t *) p_;
- close(pollset->port_fd);
- if (pollset->flags & APR_POLLSET_WAKEABLE) {
- /* Close both sides of the wakeup pipe */
- if (pollset->wakeup_pipe[0]) {
- apr_file_close(pollset->wakeup_pipe[0]);
- pollset->wakeup_pipe[0] = NULL;
- }
- if (pollset->wakeup_pipe[1]) {
- apr_file_close(pollset->wakeup_pipe[1]);
- pollset->wakeup_pipe[1] = NULL;
- }
- }
+ close(pollset->p->port_fd);
return APR_SUCCESS;
}
-/* Create a dummy wakeup pipe for interrupting the poller
- */
-static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
-{
- apr_status_t rv;
- apr_pollfd_t fd;
-
- if ((rv = apr_file_pipe_create(&pollset->wakeup_pipe[0],
- &pollset->wakeup_pipe[1],
- pollset->pool)) != APR_SUCCESS)
- return rv;
- fd.reqevents = APR_POLLIN;
- fd.desc_type = APR_POLL_FILE;
- fd.desc.f = pollset->wakeup_pipe[0];
- /* Add the pipe to the pollset
- */
- return apr_pollset_add(pollset, &fd);
-}
-
-/* Read and discard what's ever in the wakeup pipe.
- */
-static void drain_wakeup_pipe(apr_pollset_t *pollset)
-{
- char rb[512];
- apr_size_t nr = sizeof(rb);
-
- while (apr_file_read(pollset->wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
- /* Although we write just one byte to the other end of the pipe
- * during wakeup, multiple treads could call the wakeup.
- * So simply drain out from the input side of the pipe all
- * the data.
- */
- if (nr != sizeof(rb))
- break;
- }
-}
-
-APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
apr_uint32_t size,
apr_pool_t *p,
apr_uint32_t flags)
{
apr_status_t rv = APR_SUCCESS;
- *pollset = apr_palloc(p, sizeof(**pollset));
+ pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
#if APR_HAS_THREADS
if (flags & APR_POLLSET_THREADSAFE &&
- ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock,
+ ((rv = apr_thread_mutex_create(&pollset->p->ring_lock,
APR_THREAD_MUTEX_DEFAULT,
p)) != APR_SUCCESS)) {
- *pollset = NULL;
+ pollset->p = NULL;
return rv;
}
#else
if (flags & APR_POLLSET_THREADSAFE) {
- *pollset = NULL;
+ pollset->p = NULL;
return APR_ENOTIMPL;
}
#endif
- if (flags & APR_POLLSET_WAKEABLE) {
- /* Add room for wakeup descriptor */
- size++;
- }
- (*pollset)->waiting = 0;
- (*pollset)->nalloc = size;
- (*pollset)->flags = flags;
- (*pollset)->pool = p;
+ pollset->p->waiting = 0;
- (*pollset)->port_set = apr_palloc(p, size * sizeof(port_event_t));
+ pollset->p->port_set = apr_palloc(p, size * sizeof(port_event_t));
- (*pollset)->port_fd = port_create();
+ pollset->p->port_fd = port_create();
- if ((*pollset)->port_fd < 0) {
+ if (pollset->p->port_fd < 0) {
+ pollset->p = NULL;
return apr_get_netos_error();
}
{
int flags;
- if ((flags = fcntl((*pollset)->port_fd, F_GETFD)) == -1)
+ if ((flags = fcntl(pollset->p->port_fd, F_GETFD)) == -1)
return errno;
flags |= FD_CLOEXEC;
- if (fcntl((*pollset)->port_fd, F_SETFD, flags) == -1)
+ if (fcntl(pollset->p->port_fd, F_SETFD, flags) == -1)
return errno;
}
- (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
-
- APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link);
- APR_RING_INIT(&(*pollset)->add_ring, pfd_elem_t, link);
- APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link);
- APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link);
+ pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
- if (flags & APR_POLLSET_WAKEABLE) {
- /* Create wakeup pipe */
- if ((rv = create_wakeup_pipe(*pollset)) != APR_SUCCESS) {
- close((*pollset)->port_fd);
- *pollset = NULL;
- return rv;
- }
- }
- apr_pool_cleanup_register(p, (void *) (*pollset), backend_cleanup,
- apr_pool_cleanup_null);
+ APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link);
+ APR_RING_INIT(&pollset->p->add_ring, pfd_elem_t, link);
+ APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link);
+ APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link);
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset)
-{
- return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup);
-}
-
-APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
- const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+ const apr_pollfd_t *descriptor)
{
apr_os_sock_t fd;
pfd_elem_t *elem;
@@ -277,13 +207,14 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
pollset_lock_rings();
- if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) {
- elem = APR_RING_FIRST(&(pollset->free_ring));
+ if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) {
+ elem = APR_RING_FIRST(&(pollset->p->free_ring));
APR_RING_REMOVE(elem, link);
}
else {
elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t));
APR_RING_ELEM_INIT(elem, link);
+ elem->on_query_ring = 0;
}
elem->pfd = *descriptor;
@@ -297,20 +228,21 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
/* If another thread is polling, notify the kernel immediately; otherwise,
* wait until the next call to apr_pollset_poll().
*/
- if (apr_atomic_read32(&pollset->waiting)) {
- res = port_associate(pollset->port_fd, PORT_SOURCE_FD, fd,
+ if (apr_atomic_read32(&pollset->p->waiting)) {
+ res = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, fd,
get_event(descriptor->reqevents), (void *)elem);
if (res < 0) {
rv = apr_get_netos_error();
- APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link);
+ APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link);
}
else {
- APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link);
+ elem->on_query_ring = 1;
+ APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link);
}
}
else {
- APR_RING_INSERT_TAIL(&(pollset->add_ring), elem, pfd_elem_t, link);
+ APR_RING_INSERT_TAIL(&(pollset->p->add_ring), elem, pfd_elem_t, link);
}
pollset_unlock_rings();
@@ -318,14 +250,15 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
- const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_remove(apr_pollset_t *pollset,
+ const apr_pollfd_t *descriptor)
{
apr_os_sock_t fd;
pfd_elem_t *ep;
apr_status_t rv = APR_SUCCESS;
int res;
int err = 0;
+ int found;
pollset_lock_rings();
@@ -336,42 +269,60 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
fd = descriptor->desc.f->filedes;
}
- res = port_dissociate(pollset->port_fd, PORT_SOURCE_FD, fd);
-
- if (res < 0) {
- err = errno;
- rv = APR_NOTFOUND;
- }
-
- for (ep = APR_RING_FIRST(&(pollset->query_ring));
- ep != APR_RING_SENTINEL(&(pollset->query_ring),
+ /* Search the add ring first. This ring is often shorter,
+ * and it often contains the descriptor being removed.
+ * (For the common scenario where apr_pollset_poll()
+ * returns activity for the descriptor and the descriptor
+ * is then removed from the pollset, it will have just
+ * been moved to the add ring by apr_pollset_poll().)
+ *
+ * If it is on the add ring, it isn't associated with the
+ * event port yet/anymore.
+ */
+ found = 0;
+ for (ep = APR_RING_FIRST(&(pollset->p->add_ring));
+ ep != APR_RING_SENTINEL(&(pollset->p->add_ring),
pfd_elem_t, link);
ep = APR_RING_NEXT(ep, link)) {
if (descriptor->desc.s == ep->pfd.desc.s) {
+ found = 1;
APR_RING_REMOVE(ep, link);
- APR_RING_INSERT_TAIL(&(pollset->dead_ring),
+ APR_RING_INSERT_TAIL(&(pollset->p->free_ring),
ep, pfd_elem_t, link);
- if (ENOENT == err) {
- rv = APR_SUCCESS;
- }
break;
}
}
- for (ep = APR_RING_FIRST(&(pollset->add_ring));
- ep != APR_RING_SENTINEL(&(pollset->add_ring),
- pfd_elem_t, link);
- ep = APR_RING_NEXT(ep, link)) {
+ if (!found) {
+ res = port_dissociate(pollset->p->port_fd, PORT_SOURCE_FD, fd);
- if (descriptor->desc.s == ep->pfd.desc.s) {
- APR_RING_REMOVE(ep, link);
- APR_RING_INSERT_TAIL(&(pollset->dead_ring),
- ep, pfd_elem_t, link);
- if (ENOENT == err) {
- rv = APR_SUCCESS;
+ if (res < 0) {
+ /* The expected case for this failure is that another
+ * thread's call to port_getn() returned this fd and
+ * disassociated the fd from the event port, and
+ * impl_pollset_poll() is blocked on the ring lock,
+ * which this thread holds.
+ */
+ err = errno;
+ rv = APR_NOTFOUND;
+ }
+
+ for (ep = APR_RING_FIRST(&(pollset->p->query_ring));
+ ep != APR_RING_SENTINEL(&(pollset->p->query_ring),
+ pfd_elem_t, link);
+ ep = APR_RING_NEXT(ep, link)) {
+
+ if (descriptor->desc.s == ep->pfd.desc.s) {
+ APR_RING_REMOVE(ep, link);
+ ep->on_query_ring = 0;
+ APR_RING_INSERT_TAIL(&(pollset->p->dead_ring),
+ ep, pfd_elem_t, link);
+ if (ENOENT == err) {
+ rv = APR_SUCCESS;
+ }
+ break;
}
- break;
}
}
@@ -380,10 +331,10 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
- apr_interval_time_t timeout,
- apr_int32_t *num,
- const apr_pollfd_t **descriptors)
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
+ apr_interval_time_t timeout,
+ apr_int32_t *num,
+ const apr_pollfd_t **descriptors)
{
apr_os_sock_t fd;
int ret, i, j;
@@ -396,10 +347,10 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
pollset_lock_rings();
- apr_atomic_inc32(&pollset->waiting);
+ apr_atomic_inc32(&pollset->p->waiting);
- while (!APR_RING_EMPTY(&(pollset->add_ring), pfd_elem_t, link)) {
- ep = APR_RING_FIRST(&(pollset->add_ring));
+ while (!APR_RING_EMPTY(&(pollset->p->add_ring), pfd_elem_t, link)) {
+ ep = APR_RING_FIRST(&(pollset->p->add_ring));
APR_RING_REMOVE(ep, link);
if (ep->pfd.desc_type == APR_POLL_SOCKET) {
@@ -409,30 +360,31 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
fd = ep->pfd.desc.f->filedes;
}
- ret = port_associate(pollset->port_fd, PORT_SOURCE_FD,
+ ret = port_associate(pollset->p->port_fd, PORT_SOURCE_FD,
fd, get_event(ep->pfd.reqevents), ep);
if (ret < 0) {
rv = apr_get_netos_error();
- APR_RING_INSERT_TAIL(&(pollset->free_ring), ep, pfd_elem_t, link);
+ APR_RING_INSERT_TAIL(&(pollset->p->free_ring), ep, pfd_elem_t, link);
break;
}
- APR_RING_INSERT_TAIL(&(pollset->query_ring), ep, pfd_elem_t, link);
+ ep->on_query_ring = 1;
+ APR_RING_INSERT_TAIL(&(pollset->p->query_ring), ep, pfd_elem_t, link);
}
pollset_unlock_rings();
if (rv != APR_SUCCESS) {
- apr_atomic_dec32(&pollset->waiting);
+ apr_atomic_dec32(&pollset->p->waiting);
return rv;
}
- rv = call_port_getn(pollset->port_fd, pollset->port_set, pollset->nalloc,
- &nget, timeout);
+ rv = call_port_getn(pollset->p->port_fd, pollset->p->port_set,
+ pollset->nalloc, &nget, timeout);
/* decrease the waiting ASAP to reduce the window for calling
port_associate within apr_pollset_add() */
- apr_atomic_dec32(&pollset->waiting);
+ apr_atomic_dec32(&pollset->p->waiting);
(*num) = nget;
if (nget) {
@@ -440,31 +392,38 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
pollset_lock_rings();
for (i = 0, j = 0; i < nget; i++) {
- fp = (((pfd_elem_t*)(pollset->port_set[i].portev_user))->pfd);
+ fp = (((pfd_elem_t*)(pollset->p->port_set[i].portev_user))->pfd);
if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
fp.desc_type == APR_POLL_FILE &&
fp.desc.f == pollset->wakeup_pipe[0]) {
- drain_wakeup_pipe(pollset);
+ apr_pollset_drain_wakeup_pipe(pollset);
rv = APR_EINTR;
}
else {
- pollset->result_set[j] = fp;
- pollset->result_set[j].rtnevents =
- get_revent(pollset->port_set[i].portev_events);
-
- APR_RING_REMOVE((pfd_elem_t*)pollset->port_set[i].portev_user,
- link);
- APR_RING_INSERT_TAIL(&(pollset->add_ring),
- (pfd_elem_t*)pollset->port_set[i].portev_user,
- pfd_elem_t, link);
+ pollset->p->result_set[j] = fp;
+ pollset->p->result_set[j].rtnevents =
+ get_revent(pollset->p->port_set[i].portev_events);
+
+ /* If the ring element is still on the query ring, move it
+ * to the add ring for re-association with the event port
+ * later. (It may have already been moved to the dead ring
+ * by a call to pollset_remove on another thread.)
+ */
+ ep = (pfd_elem_t *)pollset->p->port_set[i].portev_user;
+ if (ep->on_query_ring) {
+ APR_RING_REMOVE(ep, link);
+ ep->on_query_ring = 0;
+ APR_RING_INSERT_TAIL(&(pollset->p->add_ring), ep,
+ pfd_elem_t, link);
+ }
j++;
}
}
pollset_unlock_rings();
- if ((*num) = j) { /* any event besides wakeup pipe? */
+ if ((*num = j)) { /* any event besides wakeup pipe? */
rv = APR_SUCCESS;
if (descriptors) {
- *descriptors = pollset->result_set;
+ *descriptors = pollset->p->result_set;
}
}
}
@@ -472,72 +431,61 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
pollset_lock_rings();
/* Shift all PFDs in the Dead Ring to the Free Ring */
- APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link);
+ APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link);
pollset_unlock_rings();
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset)
-{
- if (pollset->flags & APR_POLLSET_WAKEABLE)
- return apr_file_putc(1, pollset->wakeup_pipe[1]);
- else
- return APR_EINIT;
-}
-
-struct apr_pollcb_t {
- apr_pool_t *pool;
- apr_uint32_t nalloc;
- port_event_t *port_set;
- int port_fd;
+static apr_pollset_provider_t impl = {
+ impl_pollset_create,
+ impl_pollset_add,
+ impl_pollset_remove,
+ impl_pollset_poll,
+ impl_pollset_cleanup,
+ "port"
};
+apr_pollset_provider_t *apr_pollset_provider_port = &impl;
+
static apr_status_t cb_cleanup(void *p_)
{
apr_pollcb_t *pollcb = (apr_pollcb_t *) p_;
- close(pollcb->port_fd);
+ close(pollcb->fd);
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
- apr_uint32_t size,
- apr_pool_t *p,
- apr_uint32_t flags)
+static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb,
+ apr_uint32_t size,
+ apr_pool_t *p,
+ apr_uint32_t flags)
{
- int fd;
-
- fd = port_create();
+ pollcb->fd = port_create();
- if (fd < 0) {
- *pollcb = NULL;
+ if (pollcb->fd < 0) {
return apr_get_netos_error();
}
{
int flags;
- if ((flags = fcntl(fd, F_GETFD)) == -1)
+ if ((flags = fcntl(pollcb->fd, F_GETFD)) == -1)
return errno;
flags |= FD_CLOEXEC;
- if (fcntl(fd, F_SETFD, flags) == -1)
+ if (fcntl(pollcb->fd, F_SETFD, flags) == -1)
return errno;
}
- *pollcb = apr_palloc(p, sizeof(**pollcb));
- (*pollcb)->nalloc = size;
- (*pollcb)->pool = p;
- (*pollcb)->port_fd = fd;
- (*pollcb)->port_set = apr_palloc(p, size * sizeof(port_event_t));
- apr_pool_cleanup_register(p, *pollcb, cb_cleanup, cb_cleanup);
+ pollcb->pollset.port = apr_palloc(p, size * sizeof(port_event_t));
+ apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null);
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
- apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb,
+ apr_pollfd_t *descriptor)
{
int ret, fd;
@@ -548,7 +496,7 @@ APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
fd = descriptor->desc.f->filedes;
}
- ret = port_associate(pollcb->port_fd, PORT_SOURCE_FD, fd,
+ ret = port_associate(pollcb->fd, PORT_SOURCE_FD, fd,
get_event(descriptor->reqevents), descriptor);
if (ret == -1) {
@@ -558,8 +506,8 @@ APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
- apr_pollfd_t *descriptor)
+static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb,
+ apr_pollfd_t *descriptor)
{
int fd, ret;
@@ -570,7 +518,7 @@ APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
fd = descriptor->desc.f->filedes;
}
- ret = port_dissociate(pollcb->port_fd, PORT_SOURCE_FD, fd);
+ ret = port_dissociate(pollcb->fd, PORT_SOURCE_FD, fd);
if (ret < 0) {
return APR_NOTFOUND;
@@ -579,22 +527,22 @@ APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
- apr_interval_time_t timeout,
- apr_pollcb_cb_t func,
- void *baton)
+static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb,
+ apr_interval_time_t timeout,
+ apr_pollcb_cb_t func,
+ void *baton)
{
apr_pollfd_t *pollfd;
apr_status_t rv;
unsigned int i, nget = pollcb->nalloc;
- rv = call_port_getn(pollcb->port_fd, pollcb->port_set, pollcb->nalloc,
+ rv = call_port_getn(pollcb->fd, pollcb->pollset.port, pollcb->nalloc,
&nget, timeout);
if (nget) {
for (i = 0; i < nget; i++) {
- pollfd = (apr_pollfd_t *)(pollcb->port_set[i].portev_user);
- pollfd->rtnevents = get_revent(pollcb->port_set[i].portev_events);
+ pollfd = (apr_pollfd_t *)(pollcb->pollset.port[i].portev_user);
+ pollfd->rtnevents = get_revent(pollcb->pollset.port[i].portev_events);
rv = func(baton, pollfd);
if (rv) {
@@ -607,4 +555,14 @@ APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
return rv;
}
-#endif /* POLLSET_USES_PORT */
+static apr_pollcb_provider_t impl_cb = {
+ impl_pollcb_create,
+ impl_pollcb_add,
+ impl_pollcb_remove,
+ impl_pollcb_poll,
+ "port"
+};
+
+apr_pollcb_provider_t *apr_pollcb_provider_port = &impl_cb;
+
+#endif /* HAVE_PORT_CREATE */
diff --git a/poll/unix/select.c b/poll/unix/select.c
index c3ad8cd7b..9288de00c 100644
--- a/poll/unix/select.c
+++ b/poll/unix/select.c
@@ -23,8 +23,8 @@
#include "apr_poll.h"
#include "apr_time.h"
#include "apr_portable.h"
-#include "apr_arch_networkio.h"
#include "apr_arch_file_io.h"
+#include "apr_arch_networkio.h"
#include "apr_arch_poll_private.h"
#ifdef POLL_USES_SELECT
@@ -167,191 +167,49 @@ APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, int num,
#endif /* POLL_USES_SELECT */
-#ifdef POLLSET_USES_SELECT
-
-struct apr_pollset_t
+struct apr_pollset_private_t
{
- apr_pool_t *pool;
-
- apr_uint32_t nelts;
- apr_uint32_t nalloc;
fd_set readset, writeset, exceptset;
int maxfd;
apr_pollfd_t *query_set;
apr_pollfd_t *result_set;
apr_uint32_t flags;
- /* Pipe descriptors used for wakeup */
- apr_file_t *wakeup_pipe[2];
#ifdef NETWARE
int set_type;
#endif
};
-#if !APR_FILES_AS_SOCKETS
-#if defined (WIN32)
-
-extern apr_status_t
-apr_file_socket_pipe_create(apr_file_t **in,
- apr_file_t **out,
- apr_pool_t *p);
-
-extern apr_status_t
-apr_file_socket_pipe_close(apr_file_t *file);
-
-/* Create a dummy wakeup socket pipe for interrupting the poller
- */
-static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
-{
- apr_status_t rv;
- apr_pollfd_t fd;
-
- if ((rv = apr_file_socket_pipe_create(&pollset->wakeup_pipe[0],
- &pollset->wakeup_pipe[1],
- pollset->pool)) != APR_SUCCESS)
- return rv;
- fd.reqevents = APR_POLLIN;
- fd.desc_type = APR_POLL_FILE;
- fd.desc.f = pollset->wakeup_pipe[0];
- /* Add the pipe to the pollset
- */
- return apr_pollset_add(pollset, &fd);
-}
-#else /* !WIN32 */
-static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
-{
- return APR_ENOTIMPL;
-}
-
-static apr_status_t apr_file_socket_pipe_close(apr_file_t *file)
-{
- return APR_ENOTIMPL;
-}
-
-#endif /* WIN32 */
-#else /* APR_FILES_AS_SOCKETS */
-
-/* Create a dummy wakeup pipe for interrupting the poller
- */
-static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
-{
- apr_status_t rv;
- apr_pollfd_t fd;
-
- if ((rv = apr_file_pipe_create(&pollset->wakeup_pipe[0],
- &pollset->wakeup_pipe[1],
- pollset->pool)) != APR_SUCCESS)
- return rv;
- fd.reqevents = APR_POLLIN;
- fd.desc_type = APR_POLL_FILE;
- fd.desc.f = pollset->wakeup_pipe[0];
- /* Add the pipe to the pollset
- */
- return apr_pollset_add(pollset, &fd);
-}
-#endif /* !APR_FILES_AS_SOCKETS */
-
-/* Read and discard what's ever in the wakeup pipe.
- */
-static void drain_wakeup_pipe(apr_pollset_t *pollset)
-{
- char rb[512];
- apr_size_t nr = sizeof(rb);
-
- while (apr_file_read(pollset->wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
- /* Although we write just one byte to the other end of the pipe
- * during wakeup, multiple treads could call the wakeup.
- * So simply drain out from the input side of the pipe all
- * the data.
- */
- if (nr != sizeof(rb))
- break;
- }
-}
-
-static apr_status_t wakeup_pipe_cleanup(void *p)
-{
- apr_pollset_t *pollset = (apr_pollset_t *) p;
- if (pollset->flags & APR_POLLSET_WAKEABLE) {
- /* Close both sides of the wakeup pipe */
- if (pollset->wakeup_pipe[0]) {
-#if APR_FILES_AS_SOCKETS
- apr_file_close(pollset->wakeup_pipe[0]);
-#else
- apr_file_socket_pipe_close(pollset->wakeup_pipe[0]);
-#endif
- pollset->wakeup_pipe[0] = NULL;
- }
- if (pollset->wakeup_pipe[1]) {
-#if APR_FILES_AS_SOCKETS
- apr_file_close(pollset->wakeup_pipe[1]);
-#else
- apr_file_socket_pipe_close(pollset->wakeup_pipe[1]);
-#endif
- pollset->wakeup_pipe[1] = NULL;
- }
- }
-
- return APR_SUCCESS;
-}
-
-APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
- apr_uint32_t size,
- apr_pool_t *p,
- apr_uint32_t flags)
+static apr_status_t impl_pollset_create(apr_pollset_t *pollset,
+ apr_uint32_t size,
+ apr_pool_t *p,
+ apr_uint32_t flags)
{
if (flags & APR_POLLSET_THREADSAFE) {
- *pollset = NULL;
+ pollset->p = NULL;
return APR_ENOTIMPL;
}
- if (flags & APR_POLLSET_WAKEABLE) {
- /* Add room for wakeup descriptor */
- size++;
- }
#ifdef FD_SETSIZE
if (size > FD_SETSIZE) {
- *pollset = NULL;
+ pollset->p = NULL;
return APR_EINVAL;
}
#endif
- *pollset = apr_palloc(p, sizeof(**pollset));
- (*pollset)->nelts = 0;
- (*pollset)->nalloc = size;
- (*pollset)->pool = p;
- (*pollset)->flags = flags;
- FD_ZERO(&((*pollset)->readset));
- FD_ZERO(&((*pollset)->writeset));
- FD_ZERO(&((*pollset)->exceptset));
- (*pollset)->maxfd = 0;
+ pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t));
+ FD_ZERO(&(pollset->p->readset));
+ FD_ZERO(&(pollset->p->writeset));
+ FD_ZERO(&(pollset->p->exceptset));
+ pollset->p->maxfd = 0;
#ifdef NETWARE
- (*pollset)->set_type = APR_NO_DESC;
+ pollset->p->set_type = APR_NO_DESC;
#endif
- (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
- (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
-
- if (flags & APR_POLLSET_WAKEABLE) {
- apr_status_t rv;
- /* Create wakeup pipe */
- if ((rv = create_wakeup_pipe(*pollset)) != APR_SUCCESS) {
- *pollset = NULL;
- return rv;
- }
- apr_pool_cleanup_register(p, *pollset, wakeup_pipe_cleanup,
- apr_pool_cleanup_null);
- }
- return APR_SUCCESS;
-}
+ pollset->p->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
+ pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t));
-APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset)
-{
- if (pollset->flags & APR_POLLSET_WAKEABLE)
- return apr_pool_cleanup_run(pollset->pool, pollset,
- wakeup_pipe_cleanup);
- else
- return APR_SUCCESS;
+ return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
- const apr_pollfd_t *descriptor)
+static apr_status_t impl_pollset_add(apr_pollset_t *pollset,
+ const apr_pollfd_t *descriptor)
{
apr_os_sock_t fd;
@@ -359,16 +217,16 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
return APR_ENOMEM;
}
- pollset->query_set[pollset->nelts] = *descriptor;
+ pollset->p->query_set[pollset->nelts] = *descriptor;
if (descriptor->desc_type == APR_POLL_SOCKET) {
#ifdef NETWARE
/* NetWare can't handle mixed descriptor types in select() */
- if (HAS_PIPES(pollset->set_type)) {
+ if (HAS_PIPES(pollset->p->set_type)) {
return APR_EBADF;
}
else {
- pollset->set_type = APR_POLL_SOCKET;
+ pollset->p->set_type = APR_POLL_SOCKET;
}
#endif
fd = descriptor->desc.s->socketdes;
@@ -376,16 +234,15 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
else {
#if !APR_FILES_AS_SOCKETS
if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
- descriptor->desc.f == pollset->wakeup_pipe[0]) {
+ descriptor->desc.f == pollset->wakeup_pipe[0])
fd = (apr_os_sock_t)descriptor->desc.f->filedes;
- }
else
return APR_EBADF;
#else
#ifdef NETWARE
/* NetWare can't handle mixed descriptor types in select() */
- if (descriptor->desc.f->is_pipe && !HAS_SOCKETS(pollset->set_type)) {
- pollset->set_type = APR_POLL_FILE;
+ if (descriptor->desc.f->is_pipe && !HAS_SOCKETS(pollset->p->set_type)) {
+ pollset->p->set_type = APR_POLL_FILE;
fd = descriptor->desc.f->filedes;
}
else {
@@ -403,24 +260,24 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
}
#endif
if (descriptor->reqevents & APR_POLLIN) {
- FD_SET(fd, &(pollset->readset));
+ FD_SET(fd, &(pollset->p->readset));
}
if (descriptor->reqevents & APR_POLLOUT) {
- FD_SET(fd, &(pollset->writeset));
+ FD_SET(fd, &(pollset->p->writeset));
}
if (descriptor->reqevents &
(APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) {
- FD_SET(fd, &(pollset->exceptset));
+ FD_SET(fd, &(pollset->p->exceptset));
}
- if ((int) fd > pollset->maxfd) {
- pollset->maxfd = (int) fd;
+ if ((int) fd > pollset->p->maxfd) {
+ pollset->p->maxfd = (int) fd;
}
pollset->nelts++;
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t * pollset,
- const apr_pollfd_t * descriptor)
+static apr_status_t impl_pollset_remove(apr_pollset_t * pollset,
+ const apr_pollfd_t * descriptor)
{
apr_uint32_t i;
apr_os_sock_t fd;
@@ -437,25 +294,25 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t * pollset,
}
for (i = 0; i < pollset->nelts; i++) {
- if (descriptor->desc.s == pollset->query_set[i].desc.s) {
+ if (descriptor->desc.s == pollset->p->query_set[i].desc.s) {
/* Found an instance of the fd: remove this and any other copies */
apr_uint32_t dst = i;
apr_uint32_t old_nelts = pollset->nelts;
pollset->nelts--;
for (i++; i < old_nelts; i++) {
- if (descriptor->desc.s == pollset->query_set[i].desc.s) {
+ if (descriptor->desc.s == pollset->p->query_set[i].desc.s) {
pollset->nelts--;
}
else {
- pollset->query_set[dst] = pollset->query_set[i];
+ pollset->p->query_set[dst] = pollset->p->query_set[i];
dst++;
}
}
- FD_CLR(fd, &(pollset->readset));
- FD_CLR(fd, &(pollset->writeset));
- FD_CLR(fd, &(pollset->exceptset));
- if (((int) fd == pollset->maxfd) && (pollset->maxfd > 0)) {
- pollset->maxfd--;
+ FD_CLR(fd, &(pollset->p->readset));
+ FD_CLR(fd, &(pollset->p->writeset));
+ FD_CLR(fd, &(pollset->p->exceptset));
+ if (((int) fd == pollset->p->maxfd) && (pollset->p->maxfd > 0)) {
+ pollset->p->maxfd--;
}
return APR_SUCCESS;
}
@@ -464,10 +321,10 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t * pollset,
return APR_NOTFOUND;
}
-APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
- apr_interval_time_t timeout,
- apr_int32_t *num,
- const apr_pollfd_t **descriptors)
+static apr_status_t impl_pollset_poll(apr_pollset_t *pollset,
+ apr_interval_time_t timeout,
+ apr_int32_t *num,
+ const apr_pollfd_t **descriptors)
{
int rs;
apr_uint32_t i, j;
@@ -495,18 +352,18 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
tvptr = &tv;
}
- memcpy(&readset, &(pollset->readset), sizeof(fd_set));
- memcpy(&writeset, &(pollset->writeset), sizeof(fd_set));
- memcpy(&exceptset, &(pollset->exceptset), sizeof(fd_set));
+ memcpy(&readset, &(pollset->p->readset), sizeof(fd_set));
+ memcpy(&writeset, &(pollset->p->writeset), sizeof(fd_set));
+ memcpy(&exceptset, &(pollset->p->exceptset), sizeof(fd_set));
#ifdef NETWARE
- if (HAS_PIPES(pollset->set_type)) {
- rs = pipe_select(pollset->maxfd + 1, &readset, &writeset, &exceptset,
+ if (HAS_PIPES(pollset->p->set_type)) {
+ rs = pipe_select(pollset->p->maxfd + 1, &readset, &writeset, &exceptset,
tvptr);
}
else
#endif
- rs = select(pollset->maxfd + 1, &readset, &writeset, &exceptset,
+ rs = select(pollset->p->maxfd + 1, &readset, &writeset, &exceptset,
tvptr);
(*num) = rs;
@@ -519,13 +376,13 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
j = 0;
for (i = 0; i < pollset->nelts; i++) {
apr_os_sock_t fd;
- if (pollset->query_set[i].desc_type == APR_POLL_SOCKET) {
- fd = pollset->query_set[i].desc.s->socketdes;
+ if (pollset->p->query_set[i].desc_type == APR_POLL_SOCKET) {
+ fd = pollset->p->query_set[i].desc.s->socketdes;
}
else {
if ((pollset->flags & APR_POLLSET_WAKEABLE) &&
- pollset->query_set[i].desc.f == pollset->wakeup_pipe[0]) {
- drain_wakeup_pipe(pollset);
+ pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) {
+ apr_pollset_drain_wakeup_pipe(pollset);
rv = APR_EINTR;
continue;
}
@@ -533,22 +390,22 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
#if !APR_FILES_AS_SOCKETS
return APR_EBADF;
#else
- fd = pollset->query_set[i].desc.f->filedes;
+ fd = pollset->p->query_set[i].desc.f->filedes;
#endif
}
}
if (FD_ISSET(fd, &readset) || FD_ISSET(fd, &writeset) ||
FD_ISSET(fd, &exceptset)) {
- pollset->result_set[j] = pollset->query_set[i];
- pollset->result_set[j].rtnevents = 0;
+ pollset->p->result_set[j] = pollset->p->query_set[i];
+ pollset->p->result_set[j].rtnevents = 0;
if (FD_ISSET(fd, &readset)) {
- pollset->result_set[j].rtnevents |= APR_POLLIN;
+ pollset->p->result_set[j].rtnevents |= APR_POLLIN;
}
if (FD_ISSET(fd, &writeset)) {
- pollset->result_set[j].rtnevents |= APR_POLLOUT;
+ pollset->p->result_set[j].rtnevents |= APR_POLLOUT;
}
if (FD_ISSET(fd, &exceptset)) {
- pollset->result_set[j].rtnevents |= APR_POLLERR;
+ pollset->p->result_set[j].rtnevents |= APR_POLLERR;
}
j++;
}
@@ -557,45 +414,17 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset,
rv = APR_SUCCESS;
if (descriptors)
- *descriptors = pollset->result_set;
+ *descriptors = pollset->p->result_set;
return rv;
}
-APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset)
-{
- if (pollset->flags & APR_POLLSET_WAKEABLE)
- return apr_file_putc(1, pollset->wakeup_pipe[1]);
- else
- return APR_EINIT;
-}
-
-APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb,
- apr_uint32_t size,
- apr_pool_t *p,
- apr_uint32_t flags)
-{
- return APR_ENOTIMPL;
-}
-
-APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb,
- apr_pollfd_t *descriptor)
-{
- return APR_ENOTIMPL;
-}
-
-APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb,
- apr_pollfd_t *descriptor)
-{
- return APR_ENOTIMPL;
-}
-
-
-APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb,
- apr_interval_time_t timeout,
- apr_pollcb_cb_t func,
- void *baton)
-{
- return APR_ENOTIMPL;
-}
+static apr_pollset_provider_t impl = {
+ impl_pollset_create,
+ impl_pollset_add,
+ impl_pollset_remove,
+ impl_pollset_poll,
+ NULL,
+ "select"
+};
-#endif /* POLLSET_USES_SELECT */
+apr_pollset_provider_t *apr_pollset_provider_select = &impl;