* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: socket.c,v 1.207.2.19.2.48 2008/08/01 02:12:46 jinmei Exp $ */
+/* $Id: socket.c,v 1.207.2.19.2.49 2008/08/01 19:43:58 jinmei Exp $ */
#include <config.h>
INSIST(fd >= 0 && fd < (int)manager->maxsocks);
+ if (msg == SELECT_POKE_CLOSE) {
+ /* No one should be updating fdstate, so no need to lock it */
+ INSIST(manager->fdstate[fd] == CLOSE_PENDING);
+ manager->fdstate[fd] = CLOSED;
+ (void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+ (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+ (void)close(fd);
+ return;
+ }
+
LOCK(&manager->fdlock[lockid]);
if (manager->fdstate[fd] == CLOSE_PENDING) {
- manager->fdstate[fd] = CLOSED;
UNLOCK(&manager->fdlock[lockid]);
-
/*
* We accept (and ignore) any error from unwatch_fd() as we are
* closing the socket, hoping it doesn't leave dangling state in
*/
(void)unwatch_fd(manager, fd, SELECT_POKE_READ);
(void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
- (void)close(fd);
return;
}
if (manager->fdstate[fd] != MANAGED) {
intev_t *iev;
isc_socketevent_t *ev;
-#if 0
- /*
- * XXXJT: this assertion seems to strong, but leave it here for
- * reference.
- */
INSIST(!sock->pending_recv);
-#endif
- if (sock->pending_recv != 0)
- return;
ev = ISC_LIST_HEAD(sock->recv_list);
if (ev == NULL)
int lockid = FDLOCK_ID(fd);
/*
- * If we need to close the socket, do it now.
+ * If the socket is going to be closed, don't do more I/O.
*/
LOCK(&manager->fdlock[lockid]);
if (manager->fdstate[fd] == CLOSE_PENDING) {
- manager->fdstate[fd] = CLOSED;
UNLOCK(&manager->fdlock[lockid]);
(void)unwatch_fd(manager, fd, SELECT_POKE_READ);
(void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
- (void)close(fd);
return;
}
int i;
isc_boolean_t readable, writable;
isc_boolean_t done = ISC_FALSE;
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_boolean_t have_ctlevent = ISC_FALSE;
+#endif
if (nevents == manager->nevents) {
/*
REQUIRE(events[i].ident < manager->maxsocks);
#ifdef ISC_PLATFORM_USETHREADS
if (events[i].ident == (uintptr_t)manager->pipe_fds[0]) {
- done = process_ctlfd(manager);
+ have_ctlevent = ISC_TRUE;
continue;
}
#endif
process_fd(manager, events[i].ident, readable, writable);
}
+#ifdef ISC_PLATFORM_USETHREADS
+ if (have_ctlevent)
+ done = process_ctlfd(manager);
+#endif
+
return (done);
}
#elif defined(USE_EPOLL)
process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) {
int i;
isc_boolean_t done = ISC_FALSE;
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_boolean_t have_ctlevent = ISC_FALSE;
+#endif
if (nevents == manager->nevents) {
manager_log(manager, ISC_LOGCATEGORY_GENERAL,
REQUIRE(events[i].data.fd < (int)manager->maxsocks);
#ifdef ISC_PLATFORM_USETHREADS
if (events[i].data.fd == manager->pipe_fds[0]) {
- done = process_ctlfd(manager);
+ have_ctlevent = ISC_TRUE;
continue;
}
#endif
(events[i].events & EPOLLOUT) != 0);
}
+#ifdef ISC_PLATFORM_USETHREADS
+ if (have_ctlevent)
+ done = process_ctlfd(manager);
+#endif
+
return (done);
}
#elif defined(USE_DEVPOLL)
process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) {
int i;
isc_boolean_t done = ISC_FALSE;
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_boolean_t have_ctlevent = ISC_FALSE;
+#endif
if (nevents == manager->nevents) {
manager_log(manager, ISC_LOGCATEGORY_GENERAL,
REQUIRE(events[i].fd < (int)manager->maxsocks);
#ifdef ISC_PLATFORM_USETHREADS
if (events[i].fd == manager->pipe_fds[0]) {
- done = process_ctlfd(manager);
+ have_ctlevent = ISC_TRUE;
continue;
}
#endif
(events[i].events & POLLOUT) != 0);
}
+#ifdef ISC_PLATFORM_USETHREADS
+ if (have_ctlevent)
+ done = process_ctlfd(manager);
+#endif
+
return (done);
}
#elif defined(USE_SELECT)
#if defined(USE_KQUEUE) || defined (USE_EPOLL) || defined (USE_DEVPOLL)
done = process_fds(manager, manager->events, cc);
#elif defined(USE_SELECT)
+ process_fds(manager, maxfd, &readfds, &writefds);
+
/*
* Process reads on internal, control fd.
*/
if (FD_ISSET(ctlfd, &readfds))
done = process_ctlfd(manager);
-
- process_fds(manager, maxfd, &readfds, &writefds);
#endif
}
* Enqueue the request. If the socket was previously not being
* watched, poke the watcher to start paying attention to it.
*/
- if (ISC_LIST_EMPTY(sock->recv_list))
+ if (ISC_LIST_EMPTY(sock->recv_list) && !sock->pending_recv)
select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
ISC_LIST_ENQUEUE(sock->recv_list, dev, ev_link);
* not being watched, poke the watcher to start
* paying attention to it.
*/
- if (ISC_LIST_EMPTY(sock->send_list))
+ if (ISC_LIST_EMPTY(sock->send_list) &&
+ !sock->pending_send)
select_poke(sock->manager, sock->fd,
SELECT_POKE_WRITE);
ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link);