summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2016-05-26 10:40:44 -0700
committerAdam Jackson <ajax@redhat.com>2016-07-21 15:04:47 -0400
commitf993091e7db81b0420e23c485378cba112278839 (patch)
tree1fa9dc096853f7a8c512f76e4d7f57c8a132e598
parent8f1edf4bd3a1f050ce9eeb5eac45dd1a8f7a6d5e (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>
-rw-r--r--dix/dispatch.c4
-rw-r--r--include/dixstruct.h20
-rw-r--r--os/WaitFor.c157
-rw-r--r--os/connection.c346
-rw-r--r--os/io.c103
-rw-r--r--os/osdep.h27
-rw-r--r--os/osinit.c4
-rw-r--r--os/xdmcp.c1
8 files changed, 218 insertions, 444 deletions
diff --git a/dix/dispatch.c b/dix/dispatch.c
index 3b9600e27..a3c2fbb31 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -242,12 +242,14 @@ void Dispatch(void);
static struct xorg_list ready_clients;
static struct xorg_list saved_ready_clients;
+struct xorg_list output_pending_clients;
static void
init_client_ready(void)
{
xorg_list_init(&ready_clients);
xorg_list_init(&saved_ready_clients);
+ xorg_list_init(&output_pending_clients);
}
Bool
@@ -3411,6 +3413,7 @@ CloseDownClient(ClientPtr client)
UngrabServer(client);
}
mark_client_not_ready(client);
+ xorg_list_del(&client->output_pending);
BITCLEAR(grabWaiters, client->index);
DeleteClientFromAnySelections(client);
ReleaseActiveGrabs(client);
@@ -3501,6 +3504,7 @@ InitClient(ClientPtr client, int i, void *ospriv)
{
client->index = i;
xorg_list_init(&client->ready);
+ xorg_list_init(&client->output_pending);
client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
client->closeDownMode = i ? DestroyAll : RetainPermanent;
client->requestVector = InitialVector;
diff --git a/include/dixstruct.h b/include/dixstruct.h
index 1f383497c..3b578f81a 100644
--- a/include/dixstruct.h
+++ b/include/dixstruct.h
@@ -77,6 +77,7 @@ typedef struct _Client {
void *requestBuffer;
void *osPrivate; /* for OS layer, including scheduler */
struct xorg_list ready; /* List of clients ready to run */
+ struct xorg_list output_pending; /* List of clients with output queued */
Mask clientAsMask;
short index;
unsigned char majorOp, minorOp;
@@ -153,6 +154,25 @@ static inline Bool client_is_ready(ClientPtr client)
Bool
clients_are_ready(void);
+extern struct xorg_list output_pending_clients;
+
+static inline void
+output_pending_mark(ClientPtr client)
+{
+ if (xorg_list_is_empty(&client->output_pending))
+ xorg_list_append(&client->output_pending, &output_pending_clients);
+}
+
+static inline void
+output_pending_clear(ClientPtr client)
+{
+ xorg_list_del(&client->output_pending);
+}
+
+static inline Bool any_output_pending(void) {
+ return !xorg_list_is_empty(&output_pending_clients);
+}
+
#define SMART_MAX_PRIORITY (20)
#define SMART_MIN_PRIORITY (-20)
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, &notime);
+ 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, &notime);
- } 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, &notify_fds, list)
- RemoveNotifyFd(s->fd);
-
- xorg_list_init(&notify_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, &notify_fds, list)
- if (n->fd == fd)
- break;
- if (&n->list == &notify_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, &notify_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, &notify_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);
+ }
+}
diff --git a/os/io.c b/os/io.c
index 36527dc56..88edf1272 100644
--- a/os/io.c
+++ b/os/io.c
@@ -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"