/*
- * "$Id: select.c 7720 2008-07-11 22:46:21Z mike $"
+ * "$Id$"
*
- * Select abstraction functions for the Common UNIX Printing System (CUPS).
+ * Select abstraction functions for the CUPS scheduler.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2012 by Apple Inc.
* Copyright 2006-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
*/
#include "cupsd.h"
+#undef HAVE_KQUEUE
#ifdef HAVE_EPOLL
# include <sys/epoll.h>
-# include <sys/poll.h>
+# include <poll.h>
#elif defined(HAVE_KQUEUE)
# include <sys/event.h>
# include <sys/time.h>
#elif defined(HAVE_POLL)
-# include <sys/poll.h>
+# include <poll.h>
#elif defined(__hpux)
# include <sys/time.h>
#else
/*
* Design Notes for Poll/Select API in CUPSD
* -----------------------------------------
- *
+ *
* SUPPORTED APIS
- *
+ *
* OS select poll epoll kqueue /dev/poll
* -------------- ------ ------ ------ ------ ---------
* AIX YES YES NO NO NO
* FreeBSD YES YES NO YES NO
* HP-UX YES YES NO NO NO
- * IRIX YES YES NO NO NO
* Linux YES YES YES NO NO
* MacOS X YES YES NO YES NO
* NetBSD YES YES NO YES NO
* Solaris YES YES NO NO YES
* Tru64 YES YES NO NO NO
* Windows YES NO NO NO NO
- *
- *
+ *
+ *
* HIGH-LEVEL API
- *
+ *
* typedef void (*cupsd_selfunc_t)(void *data);
- *
+ *
* void cupsdStartSelect(void);
* void cupsdStopSelect(void);
* void cupsdAddSelect(int fd, cupsd_selfunc_t read_cb,
* cupsd_selfunc_t write_cb, void *data);
* void cupsdRemoveSelect(int fd);
* int cupsdDoSelect(int timeout);
- *
- *
+ *
+ *
* IMPLEMENTATION STRATEGY
- *
+ *
* 0. Common Stuff
* a. CUPS array of file descriptor to callback functions
* and data + temporary array of removed fd's.
* working sets.
* d. cupsdStopSelect() frees all of the memory used by the
* CUPS array and fd_set's.
- *
+ *
* 2. poll() - O(n log n)
* a. Regular array of pollfd, sorted the same as the CUPS
* array.
* e. cupsdRemoveSelect() flags the pollfd array as invalid.
* f. cupsdStopSelect() frees all of the memory used by the
* CUPS array and pollfd array.
- *
+ *
* 3. epoll() - O(n)
* a. cupsdStartSelect() creates epoll file descriptor using
* epoll_create() with the maximum fd count, and
* the callback record.
* d. cupsdStopSelect() closes the epoll file descriptor and
* frees all of the memory used by the event buffer.
- *
+ *
* 4. kqueue() - O(n)
* b. cupsdStartSelect() creates kqueue file descriptor
- * using kqyeue() function and allocates a global event
+ * using kqueue() function and allocates a global event
* buffer.
* c. cupsdAdd/RemoveSelect() uses EV_SET and kevent() to
* register the changes. The event user data field is a
* d. cupsdDoSelect() uses kevent() to poll for events and
* loops through the events, using the user data field to
* find the callback record.
- * e. cupsdStopSelect() closes the kqyeye() file descriptor
+ * e. cupsdStopSelect() closes the kqueue() file descriptor
* and frees all of the memory used by the event buffer.
- *
+ *
* 5. /dev/poll - O(n log n) - NOT YET IMPLEMENTED
* a. cupsdStartSelect() opens /dev/poll and allocates an
* array of pollfd structs; on failure to open /dev/poll,
* Range check input...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
"cupsdAddSelect(fd=%d, read_cb=%p, write_cb=%p, data=%p)",
fd, read_cb, write_cb, data);
if (fdptr->read_cb && event->filter == EVFILT_READ)
(*(fdptr->read_cb))(fdptr->data);
- if (fdptr->write_cb && event->filter == EVFILT_WRITE)
+ if (fdptr->use > 1 && fdptr->write_cb && event->filter == EVFILT_WRITE &&
+ !cupsArrayFind(cupsd_inactive_fds, fdptr))
(*(fdptr->write_cb))(fdptr->data);
release_fd(fdptr);
if (fdptr->read_cb && (event->events & (EPOLLIN | EPOLLERR | EPOLLHUP)))
(*(fdptr->read_cb))(fdptr->data);
- if (fdptr->write_cb && (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP)))
+ if (fdptr->use > 1 && fdptr->write_cb &&
+ (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) &&
+ !cupsArrayFind(cupsd_inactive_fds, fdptr))
(*(fdptr->write_cb))(fdptr->data);
release_fd(fdptr);
if (fdptr->read_cb && (pfd->revents & (POLLIN | POLLERR | POLLHUP)))
(*(fdptr->read_cb))(fdptr->data);
- if (fdptr->write_cb && (pfd->revents & (POLLOUT | POLLERR | POLLHUP)))
+ if (fdptr->use > 1 && fdptr->write_cb &&
+ (pfd->revents & (POLLOUT | POLLERR | POLLHUP)))
(*(fdptr->write_cb))(fdptr->data);
release_fd(fdptr);
if (fdptr->read_cb && FD_ISSET(fdptr->fd, &cupsd_current_input))
(*(fdptr->read_cb))(fdptr->data);
- if (fdptr->write_cb && FD_ISSET(fdptr->fd, &cupsd_current_output))
+ if (fdptr->use > 1 && fdptr->write_cb &&
+ FD_ISSET(fdptr->fd, &cupsd_current_output))
(*(fdptr->write_cb))(fdptr->data);
release_fd(fdptr);
* Range check input...
*/
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdRemoveSelect(fd=%d)", fd);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdRemoveSelect(fd=%d)", fd);
if (fd < 0)
return;
{
cupsdLogMessage(CUPSD_LOG_EMERG, "kevent() returned %s",
strerror(errno));
- return;
+ goto cleanup;
}
}
{
cupsdLogMessage(CUPSD_LOG_EMERG, "kevent() returned %s",
strerror(errno));
- return;
+ goto cleanup;
}
}
-
#elif defined(HAVE_POLL)
/*
* Update the pollfds array...
FD_CLR(fd, &cupsd_current_output);
#endif /* HAVE_EPOLL */
+#ifdef HAVE_KQUEUE
+ cleanup:
+#endif /* HAVE_KQUEUE */
+
/*
* Remove the file descriptor from the active array and add to the
* inactive array (or release, if we don't need the inactive array...)
void
cupsdStartSelect(void)
{
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartSelect()");
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdStartSelect()");
cupsd_fds = cupsArrayNew((cups_array_func_t)compare_fds, NULL);
_cupsd_fd_t *fdptr; /* Current file descriptor */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStopSelect()");
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdStopSelect()");
for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_fds);
fdptr;
/*
- * End of "$Id: select.c 7720 2008-07-11 22:46:21Z mike $".
+ * End of "$Id$".
*/