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>
This commit is contained in:
parent
8f1edf4bd3
commit
f993091e7d
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
167
os/WaitFor.c
167
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;
|
||||
|
||||
now = GetTimeInMillis();
|
||||
if ((int) (timers->expires - now) <= 0)
|
||||
expired = 1;
|
||||
|
||||
if (expired) {
|
||||
OsBlockSignals();
|
||||
while (timers && (int) (timers->expires - now) <= 0)
|
||||
DoTimer(timers, now, &timers);
|
||||
OsReleaseSignals();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients);
|
||||
|
||||
XFD_ANDSET(&tmp_set, &LastSelectMask, &NotifyReadFds);
|
||||
if (XFD_ANYSET(&tmp_set) || someNotifyWriteReady)
|
||||
HandleNotifyFds();
|
||||
|
||||
if (are_ready || XFD_ANYSET(&clientsReadable))
|
||||
break;
|
||||
|
||||
/* check here for DDXes that queue events during Block/Wakeup */
|
||||
if (*checkForInput[0] != *checkForInput[1])
|
||||
return FALSE;
|
||||
|
||||
if (timers) {
|
||||
int expired = 0;
|
||||
|
||||
now = GetTimeInMillis();
|
||||
if ((int) (timers->expires - now) <= 0)
|
||||
expired = 1;
|
||||
|
||||
if (expired) {
|
||||
OsBlockSignals();
|
||||
while (timers && (int) (timers->expires - now) <= 0)
|
||||
DoTimer(timers, now, &timers);
|
||||
OsReleaseSignals();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
are_ready = clients_are_ready();
|
||||
if (are_ready)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
346
os/connection.c
346
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;
|
||||
|
@ -1137,28 +1069,6 @@ SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************
|
||||
* 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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
103
os/io.c
103
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);
|
||||
|
|
27
os/osdep.h
27
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 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;
|
||||
extern struct ospoll *server_poll;
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -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
|
||||
/*
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue