diff options
author | Keith Packard <keithp@keithp.com> | 2016-05-26 10:40:44 -0700 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2016-07-21 15:04:47 -0400 |
commit | f993091e7db81b0420e23c485378cba112278839 (patch) | |
tree | 1fa9dc096853f7a8c512f76e4d7f57c8a132e598 /os | |
parent | 8f1edf4bd3a1f050ce9eeb5eac45dd1a8f7a6d5e (diff) |
os: Switch server to poll(2) [v3]
Eliminates all of the fd_set mangling in the server main thread
v2: Listen for POLLOUT while writes are blocked.
v3: Only mark client not ready on EAGAIN return from read
Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Diffstat (limited to 'os')
-rw-r--r-- | os/WaitFor.c | 157 | ||||
-rw-r--r-- | os/connection.c | 346 | ||||
-rw-r--r-- | os/io.c | 103 | ||||
-rw-r--r-- | os/osdep.h | 27 | ||||
-rw-r--r-- | os/osinit.c | 4 | ||||
-rw-r--r-- | os/xdmcp.c | 1 |
6 files changed, 194 insertions, 444 deletions
diff --git a/os/WaitFor.c b/os/WaitFor.c index 8164c30dd..87f8abdd8 100644 --- a/os/WaitFor.c +++ b/os/WaitFor.c @@ -66,7 +66,6 @@ SOFTWARE. #include "misc.h" #include "osdep.h" -#include <X11/Xpoll.h> #include "dixstruct.h" #include "opaque.h" #ifdef DPMSExtension @@ -146,22 +145,20 @@ Bool WaitForSomething(Bool are_ready) { int i; - struct timeval waittime, *wt; int timeout; - fd_set clientsReadable; - fd_set clientsWritable; - int curclient; - int selecterr; - static int nready; + int pollerr; + static Bool were_ready; + Bool timer_is_running; CARD32 now = 0; - Bool someNotifyWriteReady = FALSE; - FD_ZERO(&clientsReadable); - FD_ZERO(&clientsWritable); + timer_is_running = were_ready; - if (nready) + if (were_ready && !are_ready) { + timer_is_running = FALSE; SmartScheduleStopTimer(); - nready = 0; + } + + were_ready = FALSE; #ifdef BUSFAULT busfault_check(); @@ -176,8 +173,6 @@ WaitForSomething(Bool are_ready) if (are_ready) { timeout = 0; - XFD_COPYSET(&AllSockets, &LastSelectMask); - XFD_UNSET(&LastSelectMask, &ClientsWithInput); } else { timeout = -1; @@ -195,57 +190,39 @@ WaitForSomething(Bool are_ready) timeout = 0; } } - XFD_COPYSET(&AllSockets, &LastSelectMask); } BlockHandler(&timeout); - if (timeout < 0) - wt = NULL; - else { - waittime.tv_sec = timeout / MILLI_PER_SECOND; - waittime.tv_usec = (timeout % MILLI_PER_SECOND) * - (1000000 / MILLI_PER_SECOND); - wt = &waittime; - } if (NewOutputPending) FlushAllOutput(); /* keep this check close to select() call to minimize race */ if (dispatchException) i = -1; - else if (AnyWritesPending) { - XFD_COPYSET(&ClientsWriteBlocked, &LastSelectWriteMask); - XFD_ORSET(&LastSelectWriteMask, &NotifyWriteFds, &LastSelectWriteMask); - i = Select(MaxClients, &LastSelectMask, &LastSelectWriteMask, NULL, wt); - } - else { - i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt); - } - selecterr = GetErrno(); + else + i = ospoll_wait(server_poll, timeout); + pollerr = GetErrno(); WakeupHandler(i); if (i <= 0) { /* An error or timeout occurred */ if (dispatchException) return FALSE; if (i < 0) { - if (selecterr == EBADF) { /* Some client disconnected */ + if (pollerr == EBADF) { /* Some client disconnected */ CheckConnections(); - if (!XFD_ANYSET(&AllClients)) - return FALSE; + return FALSE; } - else if (selecterr == EINVAL) { - FatalError("WaitForSomething(): select: %s\n", - strerror(selecterr)); + else if (pollerr == EINVAL) { + FatalError("WaitForSomething(): poll: %s\n", + strerror(pollerr)); } - else if (selecterr != EINTR && selecterr != EAGAIN) { - ErrorF("WaitForSomething(): select: %s\n", - strerror(selecterr)); + else if (pollerr != EINTR && pollerr != EAGAIN) { + ErrorF("WaitForSomething(): poll: %s\n", + strerror(pollerr)); } } else if (are_ready) { /* * If no-one else is home, bail quickly */ - XFD_COPYSET(&ClientsWithInput, &LastSelectMask); - XFD_COPYSET(&ClientsWithInput, &clientsReadable); break; } if (*checkForInput[0] != *checkForInput[1]) @@ -269,93 +246,39 @@ WaitForSomething(Bool are_ready) } } else { - fd_set tmp_set; - - if (*checkForInput[0] == *checkForInput[1]) { - if (timers) { - int expired = 0; + /* check here for DDXes that queue events during Block/Wakeup */ + if (*checkForInput[0] != *checkForInput[1]) + return FALSE; - now = GetTimeInMillis(); - if ((int) (timers->expires - now) <= 0) - expired = 1; + if (timers) { + int expired = 0; - if (expired) { - OsBlockSignals(); - while (timers && (int) (timers->expires - now) <= 0) - DoTimer(timers, now, &timers); - OsReleaseSignals(); + now = GetTimeInMillis(); + if ((int) (timers->expires - now) <= 0) + expired = 1; - return FALSE; - } - } - } + if (expired) { + OsBlockSignals(); + while (timers && (int) (timers->expires - now) <= 0) + DoTimer(timers, now, &timers); + OsReleaseSignals(); - if (AnyWritesPending) { - XFD_ANDSET(&clientsWritable, &LastSelectWriteMask, &ClientsWriteBlocked); - if (XFD_ANYSET(&clientsWritable)) { - NewOutputPending = TRUE; - XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending); - XFD_UNSET(&ClientsWriteBlocked, &clientsWritable); - if (!XFD_ANYSET(&ClientsWriteBlocked) && NumNotifyWriteFd == 0) - AnyWritesPending = FALSE; - } - if (NumNotifyWriteFd != 0) { - XFD_ANDSET(&tmp_set, &LastSelectWriteMask, &NotifyWriteFds); - if (XFD_ANYSET(&tmp_set)) - someNotifyWriteReady = TRUE; + return FALSE; } } - XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients); - - XFD_ANDSET(&tmp_set, &LastSelectMask, &NotifyReadFds); - if (XFD_ANYSET(&tmp_set) || someNotifyWriteReady) - HandleNotifyFds(); - - if (are_ready || XFD_ANYSET(&clientsReadable)) + are_ready = clients_are_ready(); + if (are_ready) break; - - /* check here for DDXes that queue events during Block/Wakeup */ - if (*checkForInput[0] != *checkForInput[1]) - return FALSE; } } - nready = 0; - if (XFD_ANYSET(&clientsReadable)) { -#ifndef WIN32 - for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) { - while (clientsReadable.fds_bits[i]) { - int client_index; - - curclient = mffs(clientsReadable.fds_bits[i]) - 1; - client_index = /* raphael: modified */ - ConnectionTranslation[curclient + - (i * (sizeof(fd_mask) * 8))]; -#else - fd_set savedClientsReadable; - - XFD_COPYSET(&clientsReadable, &savedClientsReadable); - for (i = 0; i < XFD_SETCOUNT(&savedClientsReadable); i++) { - int client_priority, client_index; - - curclient = XFD_FD(&savedClientsReadable, i); - client_index = GetConnectionTranslation(curclient); -#endif - nready++; - mark_client_ready(clients[client_index]); -#ifndef WIN32 - clientsReadable.fds_bits[i] &= ~(((fd_mask) 1L) << curclient); - } -#else - FD_CLR(curclient, &clientsReadable); -#endif - } + if (are_ready) { + were_ready = TRUE; + if (!timer_is_running) + SmartScheduleStartTimer(); } - if (nready) - SmartScheduleStartTimer(); - return TRUE; } diff --git a/os/connection.c b/os/connection.c index 9e0c97616..8c7f7130e 100644 --- a/os/connection.c +++ b/os/connection.c @@ -78,6 +78,7 @@ SOFTWARE. #include <signal.h> #include <stdio.h> #include <stdlib.h> +#include <poll.h> #ifndef WIN32 #include <sys/socket.h> @@ -120,20 +121,10 @@ SOFTWARE. #include "probes.h" static int lastfdesc; /* maximum file descriptor */ +struct ospoll *server_poll; -fd_set NotifyReadFds; /* mask for other file descriptors */ -fd_set NotifyWriteFds; /* mask for other write file descriptors */ -fd_set AllSockets; /* select on this */ -fd_set AllClients; /* available clients */ -fd_set LastSelectMask; /* mask returned from last select call */ -fd_set LastSelectWriteMask; /* mask returned from last select call */ -fd_set ClientsWithInput; /* clients with FULL requests in buffer */ -fd_set ClientsWriteBlocked; /* clients who cannot receive output */ -fd_set OutputPending; /* clients with reply/event data ready to go */ int MaxClients = 0; -int NumNotifyWriteFd; /* Number of NotifyFd members with write set */ Bool NewOutputPending; /* not yet attempted to write some new output */ -Bool AnyWritesPending; /* true if some client blocked on write or NotifyFd with write */ Bool NoListenAll; /* Don't establish any listening sockets */ static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */ @@ -145,16 +136,17 @@ static Pid_t ParentProcess; static Bool debug_conns = FALSE; -fd_set IgnoredClientsWithInput; -static fd_set GrabImperviousClients; -static fd_set SavedAllClients; -static fd_set SavedAllSockets; -static fd_set SavedClientsWithInput; int GrabInProgress = 0; static void QueueNewConnections(int curconn, int ready, void *data); +static void +set_poll_client(ClientPtr client); + +static void +set_poll_clients(void); + #if !defined(WIN32) int *ConnectionTranslation = NULL; #else @@ -392,11 +384,6 @@ CreateWellKnownSockets(void) int i; int partial; - FD_ZERO(&AllSockets); - FD_ZERO(&AllClients); - FD_ZERO(&LastSelectMask); - FD_ZERO(&ClientsWithInput); - #if !defined(WIN32) for (i = 0; i < MaxClients; i++) ConnectionTranslation[i] = 0; @@ -751,6 +738,23 @@ ClientAuthorized(ClientPtr client, return ((char *) NULL); } +static void +ClientReady(int fd, int xevents, void *data) +{ + ClientPtr client = data; + + if (xevents & X_NOTIFY_ERROR) { + CloseDownClient(client); + return; + } + if (xevents & X_NOTIFY_READ) + mark_client_ready(client); + if (xevents & X_NOTIFY_WRITE) { + ospoll_mute(server_poll, fd, X_NOTIFY_WRITE); + NewOutputPending = TRUE; + } +} + static ClientPtr AllocNewConnection(XtransConnInfo trans_conn, int fd, CARD32 conn_time) { @@ -774,6 +778,7 @@ AllocNewConnection(XtransConnInfo trans_conn, int fd, CARD32 conn_time) oc->output = (ConnectionOutputPtr) NULL; oc->auth_id = None; oc->conn_time = conn_time; + oc->flags = 0; if (!(client = NextAvailableClient((void *) oc))) { free(oc); return NullClient; @@ -784,14 +789,11 @@ AllocNewConnection(XtransConnInfo trans_conn, int fd, CARD32 conn_time) #else SetConnectionTranslation(fd, client->index); #endif - if (GrabInProgress) { - FD_SET(fd, &SavedAllClients); - FD_SET(fd, &SavedAllSockets); - } - else { - FD_SET(fd, &AllClients); - FD_SET(fd, &AllSockets); - } + ospoll_add(server_poll, fd, + ospoll_trigger_edge, + ClientReady, + client); + set_poll_client(client); #ifdef DEBUG ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n", @@ -942,19 +944,7 @@ CloseDownFileDescriptor(OsCommPtr oc) #else SetConnectionTranslation(connection, 0); #endif - FD_CLR(connection, &AllSockets); - FD_CLR(connection, &AllClients); - FD_CLR(connection, &ClientsWithInput); - FD_CLR(connection, &GrabImperviousClients); - if (GrabInProgress) { - FD_CLR(connection, &SavedAllSockets); - FD_CLR(connection, &SavedAllClients); - FD_CLR(connection, &SavedClientsWithInput); - } - FD_CLR(connection, &ClientsWriteBlocked); - if (!XFD_ANYSET(&ClientsWriteBlocked) && NumNotifyWriteFd == 0) - AnyWritesPending = FALSE; - FD_CLR(connection, &OutputPending); + ospoll_remove(server_poll, connection); } /***************** @@ -969,53 +959,25 @@ CloseDownFileDescriptor(OsCommPtr oc) void CheckConnections(void) { -#ifndef WIN32 - fd_mask mask; -#endif - fd_set tmask; - int curclient, curoff; int i; - struct timeval notime; int r; -#ifdef WIN32 - fd_set savedAllClients; -#endif + for (i = 1; i < currentMaxClients; i++) { + ClientPtr client = clients[i]; + if (!client->clientGone) { + OsCommPtr oc = (OsCommPtr) client->osPrivate; + struct pollfd poll_fd; - notime.tv_sec = 0; - notime.tv_usec = 0; + poll_fd.fd = oc->fd; + poll_fd.events = POLLIN|POLLOUT; -#ifndef WIN32 - for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) { - mask = AllClients.fds_bits[i]; - while (mask) { - curoff = mffs(mask) - 1; - curclient = curoff + (i * (sizeof(fd_mask) * 8)); - FD_ZERO(&tmask); - FD_SET(curclient, &tmask); do { - r = Select(curclient + 1, &tmask, NULL, NULL, ¬ime); + r = poll(&poll_fd, 1, 0); } while (r < 0 && (errno == EINTR || errno == EAGAIN)); if (r < 0) - if (ConnectionTranslation[curclient] > 0) - CloseDownClient(clients[ConnectionTranslation[curclient]]); - mask &= ~((fd_mask) 1 << curoff); + CloseDownClient(client); } } -#else - XFD_COPYSET(&AllClients, &savedAllClients); - for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++) { - curclient = XFD_FD(&savedAllClients, i); - FD_ZERO(&tmask); - FD_SET(curclient, &tmask); - do { - r = Select(curclient + 1, &tmask, NULL, NULL, ¬ime); - } while (r < 0 && (errno == EINTR || errno == EAGAIN)); - if (r < 0) - if (GetConnectionTranslation(curclient) > 0) - CloseDownClient(clients[GetConnectionTranslation(curclient)]); - } -#endif } /***************** @@ -1045,28 +1007,22 @@ CloseDownConnection(ClientPtr client) } struct notify_fd { - struct xorg_list list; - int fd; int mask; NotifyFdProcPtr notify; void *data; }; -static struct xorg_list notify_fds; +/***************** + * HandleNotifyFd + * A poll callback to be called when the registered + * file descriptor is ready. + *****************/ -void -InitNotifyFds(void) +static void +HandleNotifyFd(int fd, int xevents, void *data) { - struct notify_fd *s, *next; - static int been_here; - - if (been_here) - xorg_list_for_each_entry_safe(s, next, ¬ify_fds, list) - RemoveNotifyFd(s->fd); - - xorg_list_init(¬ify_fds); - NumNotifyWriteFd = 0; - been_here = 1; + struct notify_fd *n = data; + n->notify(fd, xevents, n->data); } /***************** @@ -1079,56 +1035,32 @@ Bool SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data) { struct notify_fd *n; - int changes; - - xorg_list_for_each_entry(n, ¬ify_fds, list) - if (n->fd == fd) - break; - if (&n->list == ¬ify_fds) { + n = ospoll_data(server_poll, fd); + if (!n) { if (mask == 0) return TRUE; n = calloc(1, sizeof (struct notify_fd)); if (!n) return FALSE; - n->fd = fd; - xorg_list_add(&n->list, ¬ify_fds); - } - - changes = n->mask ^ mask; - - if (changes & X_NOTIFY_READ) { - if (mask & X_NOTIFY_READ) { - FD_SET(fd, &NotifyReadFds); - FD_SET(fd, &AllSockets); - if (GrabInProgress) - FD_SET(fd, &SavedAllSockets); - } else { - FD_CLR(fd, &AllSockets); - if (GrabInProgress) - FD_CLR(fd, &SavedAllSockets); - FD_CLR(fd, &NotifyReadFds); - } - } - - if (changes & X_NOTIFY_WRITE) { - if (mask & X_NOTIFY_WRITE) { - FD_SET(fd, &NotifyWriteFds); - if (!NumNotifyWriteFd++) - AnyWritesPending = TRUE; - } else { - FD_CLR(fd, &NotifyWriteFds); - if (!--NumNotifyWriteFd) - if (!XFD_ANYSET(&ClientsWriteBlocked)) - AnyWritesPending = FALSE; - } + ospoll_add(server_poll, fd, + ospoll_trigger_level, + HandleNotifyFd, + n); } if (mask == 0) { - xorg_list_del(&n->list); + ospoll_remove(server_poll, fd); free(n); } else { + int listen = mask & ~n->mask; + int mute = n->mask & ~mask; + + if (listen) + ospoll_listen(server_poll, fd, listen); + if (mute) + ospoll_mute(server_poll, fd, mute); n->mask = mask; n->data = data; n->notify = notify; @@ -1138,28 +1070,6 @@ SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data) } /***************** - * HandlNotifyFds - * A WorkProc to be called when any of the registered - * file descriptors are readable. - *****************/ - -void -HandleNotifyFds(void) -{ - struct notify_fd *n, *next; - - xorg_list_for_each_entry_safe(n, next, ¬ify_fds, list) { - int ready = 0; - if ((n->mask & X_NOTIFY_READ) && FD_ISSET(n->fd, &LastSelectMask)) - ready |= X_NOTIFY_READ; - if ((n->mask & X_NOTIFY_WRITE) & FD_ISSET(n->fd, &LastSelectWriteMask)) - ready |= X_NOTIFY_WRITE; - if (ready != 0) - n->notify(n->fd, ready, n->data); - } -} - -/***************** * OnlyListenToOneClient: * Only accept requests from one client. Continue to handle new * connections, but don't take any protocol requests from the new @@ -1172,30 +1082,17 @@ HandleNotifyFds(void) int OnlyListenToOneClient(ClientPtr client) { - OsCommPtr oc = (OsCommPtr) client->osPrivate; - int rc, connection = oc->fd; + int rc; rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess); if (rc != Success) return rc; if (!GrabInProgress) { - XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput); - XFD_ANDSET(&ClientsWithInput, - &ClientsWithInput, &GrabImperviousClients); - if (FD_ISSET(connection, &SavedClientsWithInput)) { - FD_CLR(connection, &SavedClientsWithInput); - FD_SET(connection, &ClientsWithInput); - } - XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients); - XFD_COPYSET(&AllSockets, &SavedAllSockets); - XFD_COPYSET(&AllClients, &SavedAllClients); - XFD_UNSET(&AllSockets, &AllClients); - XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients); - FD_SET(connection, &AllClients); - XFD_ORSET(&AllSockets, &AllSockets, &AllClients); GrabInProgress = client->index; + set_poll_clients(); } + return rc; } @@ -1208,10 +1105,8 @@ void ListenToAllClients(void) { if (GrabInProgress) { - XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets); - XFD_ORSET(&AllClients, &AllClients, &SavedAllClients); - XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput); GrabInProgress = 0; + set_poll_clients(); } } @@ -1225,7 +1120,6 @@ void IgnoreClient(ClientPtr client) { OsCommPtr oc = (OsCommPtr) client->osPrivate; - int connection = oc->fd; client->ignoreCount++; if (client->ignoreCount > 1) @@ -1233,25 +1127,9 @@ IgnoreClient(ClientPtr client) isItTimeToYield = TRUE; mark_client_not_ready(client); - if (!GrabInProgress || FD_ISSET(connection, &AllClients)) { - if (FD_ISSET(connection, &ClientsWithInput)) - FD_SET(connection, &IgnoredClientsWithInput); - else - FD_CLR(connection, &IgnoredClientsWithInput); - FD_CLR(connection, &ClientsWithInput); - FD_CLR(connection, &AllSockets); - FD_CLR(connection, &AllClients); - FD_CLR(connection, &LastSelectMask); - } - else { - if (FD_ISSET(connection, &SavedClientsWithInput)) - FD_SET(connection, &IgnoredClientsWithInput); - else - FD_CLR(connection, &IgnoredClientsWithInput); - FD_CLR(connection, &SavedClientsWithInput); - FD_CLR(connection, &SavedAllSockets); - FD_CLR(connection, &SavedAllClients); - } + + oc->flags |= OS_COMM_IGNORED; + set_poll_client(client); } /**************** @@ -1263,28 +1141,15 @@ void AttendClient(ClientPtr client) { OsCommPtr oc = (OsCommPtr) client->osPrivate; - int connection = oc->fd; client->ignoreCount--; if (client->ignoreCount) return; - if (!GrabInProgress || GrabInProgress == client->index || - FD_ISSET(connection, &GrabImperviousClients)) { - FD_SET(connection, &AllClients); - FD_SET(connection, &AllSockets); - FD_SET(connection, &LastSelectMask); - if (FD_ISSET(connection, &IgnoredClientsWithInput)) { - FD_SET(connection, &ClientsWithInput); - mark_client_ready(client); - } - } - else { - FD_SET(connection, &SavedAllClients); - FD_SET(connection, &SavedAllSockets); - if (FD_ISSET(connection, &IgnoredClientsWithInput)) - FD_SET(connection, &SavedClientsWithInput); - } + oc->flags &= ~OS_COMM_IGNORED; + set_poll_client(client); + if (listen_to_client(client)) + mark_client_ready(client); } /* make client impervious to grabs; assume only executing client calls this */ @@ -1293,9 +1158,9 @@ void MakeClientGrabImpervious(ClientPtr client) { OsCommPtr oc = (OsCommPtr) client->osPrivate; - int connection = oc->fd; - FD_SET(connection, &GrabImperviousClients); + oc->flags |= OS_COMM_GRAB_IMPERVIOUS; + set_poll_client(client); if (ServerGrabCallback) { ServerGrabInfoRec grabinfo; @@ -1312,18 +1177,10 @@ void MakeClientGrabPervious(ClientPtr client) { OsCommPtr oc = (OsCommPtr) client->osPrivate; - int connection = oc->fd; - FD_CLR(connection, &GrabImperviousClients); - if (GrabInProgress && (GrabInProgress != client->index)) { - if (FD_ISSET(connection, &ClientsWithInput)) { - FD_SET(connection, &SavedClientsWithInput); - FD_CLR(connection, &ClientsWithInput); - } - FD_CLR(connection, &AllSockets); - FD_CLR(connection, &AllClients); - isItTimeToYield = TRUE; - } + oc->flags &= ~OS_COMM_GRAB_IMPERVIOUS; + set_poll_client(client); + isItTimeToYield = TRUE; if (ServerGrabCallback) { ServerGrabInfoRec grabinfo; @@ -1405,3 +1262,46 @@ AddClientOnOpenFD(int fd) return TRUE; } + +Bool +listen_to_client(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr) client->osPrivate; + + if (oc->flags & OS_COMM_IGNORED) + return FALSE; + + if (!GrabInProgress) + return TRUE; + + if (client->index == GrabInProgress) + return TRUE; + + if (oc->flags & OS_COMM_GRAB_IMPERVIOUS) + return TRUE; + + return FALSE; +} + +static void +set_poll_client(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr) client->osPrivate; + + if (listen_to_client(client)) + ospoll_listen(server_poll, oc->fd, X_NOTIFY_READ); + else + ospoll_mute(server_poll, oc->fd, X_NOTIFY_READ); +} + +static void +set_poll_clients(void) +{ + int i; + + for (i = 1; i < currentMaxClients; i++) { + ClientPtr client = clients[i]; + if (client && !client->clientGone) + set_poll_client(client); + } +} @@ -74,7 +74,6 @@ SOFTWARE. #include <X11/Xproto.h> #include "os.h" #include "osdep.h" -#include <X11/Xpoll.h> #include "opaque.h" #include "dixstruct.h" #include "misc.h" @@ -188,7 +187,7 @@ static void YieldControlNoInput(int fd) { YieldControl(); - FD_CLR(fd, &ClientsWithInput); + ospoll_reset_events(server_poll, fd); } static void @@ -439,24 +438,8 @@ ReadRequestFromClient(ClientPtr client) */ gotnow -= needed; - if (gotnow >= sizeof(xReq)) { - request = (xReq *) (oci->bufptr + needed); - if (gotnow >= (result = (get_req_len(request, client) << 2)) - && (result || - (client->big_requests && - (gotnow >= sizeof(xBigReq) && - gotnow >= (get_big_req_len(request, client) << 2)))) - ) - FD_SET(fd, &ClientsWithInput); - else { - FD_CLR(fd, &ClientsWithInput); - } - } - else { - if (!gotnow) - AvailableInput = oc; - FD_CLR(fd, &ClientsWithInput); - } + if (!gotnow) + AvailableInput = oc; if (move_header) { request = (xReq *) oci->bufptr; oci->bufptr += (sizeof(xBigReq) - sizeof(xReq)); @@ -549,7 +532,7 @@ InsertFakeRequest(ClientPtr client, char *data, int count) gotnow += count; if ((gotnow >= sizeof(xReq)) && (gotnow >= (int) (get_req_len((xReq *) oci->bufptr, client) << 2))) - FD_SET(fd, &ClientsWithInput); + mark_client_ready(client); else YieldControlNoInput(fd); return TRUE; @@ -589,12 +572,8 @@ ResetCurrentRequest(ClientPtr client) } } if (gotnow >= (needed << 2)) { - if (FD_ISSET(fd, &AllClients)) { - FD_SET(fd, &ClientsWithInput); - } - else { - FD_SET(fd, &IgnoredClientsWithInput); - } + if (listen_to_client(client)) + mark_client_ready(client); YieldControl(); } else @@ -615,16 +594,10 @@ ResetCurrentRequest(ClientPtr client) void FlushAllOutput(void) { - register int index, base; - register fd_mask mask; /* raphael */ OsCommPtr oc; - register ClientPtr client; + register ClientPtr client, tmp; Bool newoutput = NewOutputPending; -#if defined(WIN32) - fd_set newOutputPending; -#endif - if (FlushCallback) CallCallbacks(&FlushCallback, NULL); @@ -639,48 +612,14 @@ FlushAllOutput(void) CriticalOutputPending = FALSE; NewOutputPending = FALSE; -#ifndef WIN32 - for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++) { - mask = OutputPending.fds_bits[base]; - OutputPending.fds_bits[base] = 0; - while (mask) { - index = ffs(mask) - 1; - mask &= ~lowbit(mask); - if ((index = - ConnectionTranslation[(base * (sizeof(fd_mask) * 8)) + - index]) == 0) - continue; - client = clients[index]; - if (client->clientGone) - continue; - oc = (OsCommPtr) client->osPrivate; - if (FD_ISSET(oc->fd, &ClientsWithInput)) { - FD_SET(oc->fd, &OutputPending); /* set the bit again */ - NewOutputPending = TRUE; - } - else - (void) FlushClient(client, oc, (char *) NULL, 0); - } - } -#else /* WIN32 */ - FD_ZERO(&newOutputPending); - for (base = 0; base < XFD_SETCOUNT(&OutputPending); base++) { - index = XFD_FD(&OutputPending, base); - if ((index = GetConnectionTranslation(index)) == 0) - continue; - client = clients[index]; + xorg_list_for_each_entry_safe(client, tmp, &output_pending_clients, output_pending) { if (client->clientGone) continue; - oc = (OsCommPtr) client->osPrivate; - if (FD_ISSET(oc->fd, &ClientsWithInput)) { - FD_SET(oc->fd, &newOutputPending); /* set the bit again */ - NewOutputPending = TRUE; - } - else + if (!client_is_ready(client)) { + oc = (OsCommPtr) client->osPrivate; (void) FlushClient(client, oc, (char *) NULL, 0); + } } - XFD_COPYSET(&newOutputPending, &OutputPending); -#endif /* WIN32 */ } void @@ -822,8 +761,8 @@ WriteToClient(ClientPtr who, int count, const void *__buf) } #endif if (oco->count == 0 || oco->count + count + padBytes > oco->size) { - FD_CLR(oc->fd, &OutputPending); - if (!XFD_ANYSET(&OutputPending)) { + output_pending_clear(who); + if (!any_output_pending()) { CriticalOutputPending = FALSE; NewOutputPending = FALSE; } @@ -835,7 +774,7 @@ WriteToClient(ClientPtr who, int count, const void *__buf) } NewOutputPending = TRUE; - FD_SET(oc->fd, &OutputPending); + output_pending_mark(who); memmove((char *) oco->buf + oco->count, buf, count); oco->count += count; if (padBytes) { @@ -859,7 +798,6 @@ int FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount) { ConnectionOutputPtr oco = oc->output; - int connection = oc->fd; XtransConnInfo trans_conn = oc->trans_conn; struct iovec iov[3]; static char padBuffer[3]; @@ -932,8 +870,7 @@ FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount) /* If we've arrived here, then the client is stuffed to the gills and not ready to accept more. Make a note of it and buffer the rest. */ - FD_SET(connection, &ClientsWriteBlocked); - AnyWritesPending = TRUE; + output_pending_mark(who); if (written < oco->count) { if (written > 0) { @@ -973,6 +910,8 @@ FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount) extraBuf + written, len); oco->count = notWritten; /* this will include the pad */ + ospoll_listen(server_poll, oc->fd, X_NOTIFY_WRITE); + /* return only the amount explicitly requested */ return extraCount; } @@ -995,12 +934,8 @@ FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount) /* everything was flushed out */ oco->count = 0; - /* check to see if this client was write blocked */ - if (AnyWritesPending) { - FD_CLR(oc->fd, &ClientsWriteBlocked); - if (!XFD_ANYSET(&ClientsWriteBlocked) && NumNotifyWriteFd == 0) - AnyWritesPending = FALSE; - } + output_pending_clear(who); + if (oco->size > BUFWATERMARK) { free(oco->buf); free(oco); diff --git a/os/osdep.h b/os/osdep.h index 9dbf0fb89..df0abebb0 100644 --- a/os/osdep.h +++ b/os/osdep.h @@ -162,8 +162,12 @@ typedef struct _osComm { XID auth_id; /* authorization id */ CARD32 conn_time; /* timestamp if not established, else 0 */ struct _XtransConnInfo *trans_conn; /* transport connection object */ + int flags; } OsCommRec, *OsCommPtr; +#define OS_COMM_GRAB_IMPERVIOUS 1 +#define OS_COMM_IGNORED 2 + extern int FlushClient(ClientPtr /*who */ , OsCommPtr /*oc */ , const void * /*extraBuf */ , @@ -173,24 +177,13 @@ extern int FlushClient(ClientPtr /*who */ , extern void FreeOsBuffers(OsCommPtr /*oc */ ); -extern void InitNotifyFds(void); - -extern void HandleNotifyFds(void); - #include "dix.h" +#include "ospoll.h" + +extern struct ospoll *server_poll; -extern fd_set AllSockets; -extern fd_set AllClients; -extern fd_set LastSelectMask; -extern fd_set LastSelectWriteMask; -extern fd_set WellKnownConnections; -extern fd_set EnabledDevices; -extern fd_set NotifyReadFds; -extern fd_set NotifyWriteFds; -extern fd_set ClientsWithInput; -extern fd_set ClientsWriteBlocked; -extern fd_set OutputPending; -extern fd_set IgnoredClientsWithInput; +Bool +listen_to_client(ClientPtr client); #if !defined(WIN32) || defined(__CYGWIN__) extern int *ConnectionTranslation; @@ -201,8 +194,6 @@ extern void ClearConnectionTranslation(void); #endif extern Bool NewOutputPending; -extern Bool AnyWritesPending; -extern Bool NumNotifyWriteFd; extern WorkQueuePtr workQueue; diff --git a/os/osinit.c b/os/osinit.c index 629fef569..ab9c1d657 100644 --- a/os/osinit.c +++ b/os/osinit.c @@ -195,7 +195,9 @@ OsInit(void) #ifdef BUSFAULT busfault_init(); #endif - InitNotifyFds(); + server_poll = ospoll_create(); + if (!server_poll) + FatalError("failed to allocate poll structure"); #ifdef HAVE_BACKTRACE /* diff --git a/os/xdmcp.c b/os/xdmcp.c index 2cb8d76ec..906c95944 100644 --- a/os/xdmcp.c +++ b/os/xdmcp.c @@ -39,7 +39,6 @@ #include <X11/X.h> #include <X11/Xmd.h> #include "misc.h" -#include <X11/Xpoll.h> #include "osdep.h" #include "input.h" #include "dixstruct.h" |