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 ready_clients;
|
||||||
static struct xorg_list saved_ready_clients;
|
static struct xorg_list saved_ready_clients;
|
||||||
|
struct xorg_list output_pending_clients;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_client_ready(void)
|
init_client_ready(void)
|
||||||
{
|
{
|
||||||
xorg_list_init(&ready_clients);
|
xorg_list_init(&ready_clients);
|
||||||
xorg_list_init(&saved_ready_clients);
|
xorg_list_init(&saved_ready_clients);
|
||||||
|
xorg_list_init(&output_pending_clients);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool
|
Bool
|
||||||
|
@ -3411,6 +3413,7 @@ CloseDownClient(ClientPtr client)
|
||||||
UngrabServer(client);
|
UngrabServer(client);
|
||||||
}
|
}
|
||||||
mark_client_not_ready(client);
|
mark_client_not_ready(client);
|
||||||
|
xorg_list_del(&client->output_pending);
|
||||||
BITCLEAR(grabWaiters, client->index);
|
BITCLEAR(grabWaiters, client->index);
|
||||||
DeleteClientFromAnySelections(client);
|
DeleteClientFromAnySelections(client);
|
||||||
ReleaseActiveGrabs(client);
|
ReleaseActiveGrabs(client);
|
||||||
|
@ -3501,6 +3504,7 @@ InitClient(ClientPtr client, int i, void *ospriv)
|
||||||
{
|
{
|
||||||
client->index = i;
|
client->index = i;
|
||||||
xorg_list_init(&client->ready);
|
xorg_list_init(&client->ready);
|
||||||
|
xorg_list_init(&client->output_pending);
|
||||||
client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
|
client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
|
||||||
client->closeDownMode = i ? DestroyAll : RetainPermanent;
|
client->closeDownMode = i ? DestroyAll : RetainPermanent;
|
||||||
client->requestVector = InitialVector;
|
client->requestVector = InitialVector;
|
||||||
|
|
|
@ -77,6 +77,7 @@ typedef struct _Client {
|
||||||
void *requestBuffer;
|
void *requestBuffer;
|
||||||
void *osPrivate; /* for OS layer, including scheduler */
|
void *osPrivate; /* for OS layer, including scheduler */
|
||||||
struct xorg_list ready; /* List of clients ready to run */
|
struct xorg_list ready; /* List of clients ready to run */
|
||||||
|
struct xorg_list output_pending; /* List of clients with output queued */
|
||||||
Mask clientAsMask;
|
Mask clientAsMask;
|
||||||
short index;
|
short index;
|
||||||
unsigned char majorOp, minorOp;
|
unsigned char majorOp, minorOp;
|
||||||
|
@ -153,6 +154,25 @@ static inline Bool client_is_ready(ClientPtr client)
|
||||||
Bool
|
Bool
|
||||||
clients_are_ready(void);
|
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_MAX_PRIORITY (20)
|
||||||
#define SMART_MIN_PRIORITY (-20)
|
#define SMART_MIN_PRIORITY (-20)
|
||||||
|
|
||||||
|
|
133
os/WaitFor.c
133
os/WaitFor.c
|
@ -66,7 +66,6 @@ SOFTWARE.
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
#include "osdep.h"
|
#include "osdep.h"
|
||||||
#include <X11/Xpoll.h>
|
|
||||||
#include "dixstruct.h"
|
#include "dixstruct.h"
|
||||||
#include "opaque.h"
|
#include "opaque.h"
|
||||||
#ifdef DPMSExtension
|
#ifdef DPMSExtension
|
||||||
|
@ -146,22 +145,20 @@ Bool
|
||||||
WaitForSomething(Bool are_ready)
|
WaitForSomething(Bool are_ready)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct timeval waittime, *wt;
|
|
||||||
int timeout;
|
int timeout;
|
||||||
fd_set clientsReadable;
|
int pollerr;
|
||||||
fd_set clientsWritable;
|
static Bool were_ready;
|
||||||
int curclient;
|
Bool timer_is_running;
|
||||||
int selecterr;
|
|
||||||
static int nready;
|
|
||||||
CARD32 now = 0;
|
CARD32 now = 0;
|
||||||
Bool someNotifyWriteReady = FALSE;
|
|
||||||
|
|
||||||
FD_ZERO(&clientsReadable);
|
timer_is_running = were_ready;
|
||||||
FD_ZERO(&clientsWritable);
|
|
||||||
|
|
||||||
if (nready)
|
if (were_ready && !are_ready) {
|
||||||
|
timer_is_running = FALSE;
|
||||||
SmartScheduleStopTimer();
|
SmartScheduleStopTimer();
|
||||||
nready = 0;
|
}
|
||||||
|
|
||||||
|
were_ready = FALSE;
|
||||||
|
|
||||||
#ifdef BUSFAULT
|
#ifdef BUSFAULT
|
||||||
busfault_check();
|
busfault_check();
|
||||||
|
@ -176,8 +173,6 @@ WaitForSomething(Bool are_ready)
|
||||||
|
|
||||||
if (are_ready) {
|
if (are_ready) {
|
||||||
timeout = 0;
|
timeout = 0;
|
||||||
XFD_COPYSET(&AllSockets, &LastSelectMask);
|
|
||||||
XFD_UNSET(&LastSelectMask, &ClientsWithInput);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
timeout = -1;
|
timeout = -1;
|
||||||
|
@ -195,57 +190,39 @@ WaitForSomething(Bool are_ready)
|
||||||
timeout = 0;
|
timeout = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
XFD_COPYSET(&AllSockets, &LastSelectMask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockHandler(&timeout);
|
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)
|
if (NewOutputPending)
|
||||||
FlushAllOutput();
|
FlushAllOutput();
|
||||||
/* keep this check close to select() call to minimize race */
|
/* keep this check close to select() call to minimize race */
|
||||||
if (dispatchException)
|
if (dispatchException)
|
||||||
i = -1;
|
i = -1;
|
||||||
else if (AnyWritesPending) {
|
else
|
||||||
XFD_COPYSET(&ClientsWriteBlocked, &LastSelectWriteMask);
|
i = ospoll_wait(server_poll, timeout);
|
||||||
XFD_ORSET(&LastSelectWriteMask, &NotifyWriteFds, &LastSelectWriteMask);
|
pollerr = GetErrno();
|
||||||
i = Select(MaxClients, &LastSelectMask, &LastSelectWriteMask, NULL, wt);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt);
|
|
||||||
}
|
|
||||||
selecterr = GetErrno();
|
|
||||||
WakeupHandler(i);
|
WakeupHandler(i);
|
||||||
if (i <= 0) { /* An error or timeout occurred */
|
if (i <= 0) { /* An error or timeout occurred */
|
||||||
if (dispatchException)
|
if (dispatchException)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
if (selecterr == EBADF) { /* Some client disconnected */
|
if (pollerr == EBADF) { /* Some client disconnected */
|
||||||
CheckConnections();
|
CheckConnections();
|
||||||
if (!XFD_ANYSET(&AllClients))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else if (selecterr == EINVAL) {
|
else if (pollerr == EINVAL) {
|
||||||
FatalError("WaitForSomething(): select: %s\n",
|
FatalError("WaitForSomething(): poll: %s\n",
|
||||||
strerror(selecterr));
|
strerror(pollerr));
|
||||||
}
|
}
|
||||||
else if (selecterr != EINTR && selecterr != EAGAIN) {
|
else if (pollerr != EINTR && pollerr != EAGAIN) {
|
||||||
ErrorF("WaitForSomething(): select: %s\n",
|
ErrorF("WaitForSomething(): poll: %s\n",
|
||||||
strerror(selecterr));
|
strerror(pollerr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (are_ready) {
|
else if (are_ready) {
|
||||||
/*
|
/*
|
||||||
* If no-one else is home, bail quickly
|
* If no-one else is home, bail quickly
|
||||||
*/
|
*/
|
||||||
XFD_COPYSET(&ClientsWithInput, &LastSelectMask);
|
|
||||||
XFD_COPYSET(&ClientsWithInput, &clientsReadable);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (*checkForInput[0] != *checkForInput[1])
|
if (*checkForInput[0] != *checkForInput[1])
|
||||||
|
@ -269,9 +246,10 @@ WaitForSomething(Bool are_ready)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fd_set tmp_set;
|
/* check here for DDXes that queue events during Block/Wakeup */
|
||||||
|
if (*checkForInput[0] != *checkForInput[1])
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (*checkForInput[0] == *checkForInput[1]) {
|
|
||||||
if (timers) {
|
if (timers) {
|
||||||
int expired = 0;
|
int expired = 0;
|
||||||
|
|
||||||
|
@ -288,73 +266,18 @@ WaitForSomething(Bool are_ready)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (AnyWritesPending) {
|
are_ready = clients_are_ready();
|
||||||
XFD_ANDSET(&clientsWritable, &LastSelectWriteMask, &ClientsWriteBlocked);
|
if (are_ready)
|
||||||
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;
|
break;
|
||||||
|
|
||||||
/* check here for DDXes that queue events during Block/Wakeup */
|
|
||||||
if (*checkForInput[0] != *checkForInput[1])
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nready = 0;
|
if (are_ready) {
|
||||||
if (XFD_ANYSET(&clientsReadable)) {
|
were_ready = TRUE;
|
||||||
#ifndef WIN32
|
if (!timer_is_running)
|
||||||
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 (nready)
|
|
||||||
SmartScheduleStartTimer();
|
SmartScheduleStartTimer();
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
342
os/connection.c
342
os/connection.c
|
@ -78,6 +78,7 @@ SOFTWARE.
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -120,20 +121,10 @@ SOFTWARE.
|
||||||
#include "probes.h"
|
#include "probes.h"
|
||||||
|
|
||||||
static int lastfdesc; /* maximum file descriptor */
|
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 MaxClients = 0;
|
||||||
int NumNotifyWriteFd; /* Number of NotifyFd members with write set */
|
|
||||||
Bool NewOutputPending; /* not yet attempted to write some new output */
|
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 */
|
Bool NoListenAll; /* Don't establish any listening sockets */
|
||||||
|
|
||||||
static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
|
static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
|
||||||
|
@ -145,16 +136,17 @@ static Pid_t ParentProcess;
|
||||||
|
|
||||||
static Bool debug_conns = FALSE;
|
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;
|
int GrabInProgress = 0;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
QueueNewConnections(int curconn, int ready, void *data);
|
QueueNewConnections(int curconn, int ready, void *data);
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_poll_client(ClientPtr client);
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_poll_clients(void);
|
||||||
|
|
||||||
#if !defined(WIN32)
|
#if !defined(WIN32)
|
||||||
int *ConnectionTranslation = NULL;
|
int *ConnectionTranslation = NULL;
|
||||||
#else
|
#else
|
||||||
|
@ -392,11 +384,6 @@ CreateWellKnownSockets(void)
|
||||||
int i;
|
int i;
|
||||||
int partial;
|
int partial;
|
||||||
|
|
||||||
FD_ZERO(&AllSockets);
|
|
||||||
FD_ZERO(&AllClients);
|
|
||||||
FD_ZERO(&LastSelectMask);
|
|
||||||
FD_ZERO(&ClientsWithInput);
|
|
||||||
|
|
||||||
#if !defined(WIN32)
|
#if !defined(WIN32)
|
||||||
for (i = 0; i < MaxClients; i++)
|
for (i = 0; i < MaxClients; i++)
|
||||||
ConnectionTranslation[i] = 0;
|
ConnectionTranslation[i] = 0;
|
||||||
|
@ -751,6 +738,23 @@ ClientAuthorized(ClientPtr client,
|
||||||
return ((char *) NULL);
|
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
|
static ClientPtr
|
||||||
AllocNewConnection(XtransConnInfo trans_conn, int fd, CARD32 conn_time)
|
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->output = (ConnectionOutputPtr) NULL;
|
||||||
oc->auth_id = None;
|
oc->auth_id = None;
|
||||||
oc->conn_time = conn_time;
|
oc->conn_time = conn_time;
|
||||||
|
oc->flags = 0;
|
||||||
if (!(client = NextAvailableClient((void *) oc))) {
|
if (!(client = NextAvailableClient((void *) oc))) {
|
||||||
free(oc);
|
free(oc);
|
||||||
return NullClient;
|
return NullClient;
|
||||||
|
@ -784,14 +789,11 @@ AllocNewConnection(XtransConnInfo trans_conn, int fd, CARD32 conn_time)
|
||||||
#else
|
#else
|
||||||
SetConnectionTranslation(fd, client->index);
|
SetConnectionTranslation(fd, client->index);
|
||||||
#endif
|
#endif
|
||||||
if (GrabInProgress) {
|
ospoll_add(server_poll, fd,
|
||||||
FD_SET(fd, &SavedAllClients);
|
ospoll_trigger_edge,
|
||||||
FD_SET(fd, &SavedAllSockets);
|
ClientReady,
|
||||||
}
|
client);
|
||||||
else {
|
set_poll_client(client);
|
||||||
FD_SET(fd, &AllClients);
|
|
||||||
FD_SET(fd, &AllSockets);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
|
ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
|
||||||
|
@ -942,19 +944,7 @@ CloseDownFileDescriptor(OsCommPtr oc)
|
||||||
#else
|
#else
|
||||||
SetConnectionTranslation(connection, 0);
|
SetConnectionTranslation(connection, 0);
|
||||||
#endif
|
#endif
|
||||||
FD_CLR(connection, &AllSockets);
|
ospoll_remove(server_poll, connection);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************
|
/*****************
|
||||||
|
@ -969,53 +959,25 @@ CloseDownFileDescriptor(OsCommPtr oc)
|
||||||
void
|
void
|
||||||
CheckConnections(void)
|
CheckConnections(void)
|
||||||
{
|
{
|
||||||
#ifndef WIN32
|
|
||||||
fd_mask mask;
|
|
||||||
#endif
|
|
||||||
fd_set tmask;
|
|
||||||
int curclient, curoff;
|
|
||||||
int i;
|
int i;
|
||||||
struct timeval notime;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
#ifdef WIN32
|
for (i = 1; i < currentMaxClients; i++) {
|
||||||
fd_set savedAllClients;
|
ClientPtr client = clients[i];
|
||||||
#endif
|
if (!client->clientGone) {
|
||||||
|
OsCommPtr oc = (OsCommPtr) client->osPrivate;
|
||||||
|
struct pollfd poll_fd;
|
||||||
|
|
||||||
notime.tv_sec = 0;
|
poll_fd.fd = oc->fd;
|
||||||
notime.tv_usec = 0;
|
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 {
|
do {
|
||||||
r = Select(curclient + 1, &tmask, NULL, NULL, ¬ime);
|
r = poll(&poll_fd, 1, 0);
|
||||||
} while (r < 0 && (errno == EINTR || errno == EAGAIN));
|
} while (r < 0 && (errno == EINTR || errno == EAGAIN));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
if (ConnectionTranslation[curclient] > 0)
|
CloseDownClient(client);
|
||||||
CloseDownClient(clients[ConnectionTranslation[curclient]]);
|
|
||||||
mask &= ~((fd_mask) 1 << curoff);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#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 notify_fd {
|
||||||
struct xorg_list list;
|
|
||||||
int fd;
|
|
||||||
int mask;
|
int mask;
|
||||||
NotifyFdProcPtr notify;
|
NotifyFdProcPtr notify;
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct xorg_list notify_fds;
|
/*****************
|
||||||
|
* HandleNotifyFd
|
||||||
|
* A poll callback to be called when the registered
|
||||||
|
* file descriptor is ready.
|
||||||
|
*****************/
|
||||||
|
|
||||||
void
|
static void
|
||||||
InitNotifyFds(void)
|
HandleNotifyFd(int fd, int xevents, void *data)
|
||||||
{
|
{
|
||||||
struct notify_fd *s, *next;
|
struct notify_fd *n = data;
|
||||||
static int been_here;
|
n->notify(fd, xevents, n->data);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************
|
/*****************
|
||||||
|
@ -1079,56 +1035,32 @@ Bool
|
||||||
SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data)
|
SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data)
|
||||||
{
|
{
|
||||||
struct notify_fd *n;
|
struct notify_fd *n;
|
||||||
int changes;
|
|
||||||
|
|
||||||
xorg_list_for_each_entry(n, ¬ify_fds, list)
|
n = ospoll_data(server_poll, fd);
|
||||||
if (n->fd == fd)
|
if (!n) {
|
||||||
break;
|
|
||||||
|
|
||||||
if (&n->list == ¬ify_fds) {
|
|
||||||
if (mask == 0)
|
if (mask == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
n = calloc(1, sizeof (struct notify_fd));
|
n = calloc(1, sizeof (struct notify_fd));
|
||||||
if (!n)
|
if (!n)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
n->fd = fd;
|
ospoll_add(server_poll, fd,
|
||||||
xorg_list_add(&n->list, ¬ify_fds);
|
ospoll_trigger_level,
|
||||||
}
|
HandleNotifyFd,
|
||||||
|
n);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mask == 0) {
|
if (mask == 0) {
|
||||||
xorg_list_del(&n->list);
|
ospoll_remove(server_poll, fd);
|
||||||
free(n);
|
free(n);
|
||||||
} else {
|
} 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->mask = mask;
|
||||||
n->data = data;
|
n->data = data;
|
||||||
n->notify = notify;
|
n->notify = notify;
|
||||||
|
@ -1137,28 +1069,6 @@ SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data)
|
||||||
return TRUE;
|
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:
|
* OnlyListenToOneClient:
|
||||||
* Only accept requests from one client. Continue to handle new
|
* Only accept requests from one client. Continue to handle new
|
||||||
|
@ -1172,30 +1082,17 @@ HandleNotifyFds(void)
|
||||||
int
|
int
|
||||||
OnlyListenToOneClient(ClientPtr client)
|
OnlyListenToOneClient(ClientPtr client)
|
||||||
{
|
{
|
||||||
OsCommPtr oc = (OsCommPtr) client->osPrivate;
|
int rc;
|
||||||
int rc, connection = oc->fd;
|
|
||||||
|
|
||||||
rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess);
|
rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess);
|
||||||
if (rc != Success)
|
if (rc != Success)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (!GrabInProgress) {
|
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;
|
GrabInProgress = client->index;
|
||||||
|
set_poll_clients();
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1208,10 +1105,8 @@ void
|
||||||
ListenToAllClients(void)
|
ListenToAllClients(void)
|
||||||
{
|
{
|
||||||
if (GrabInProgress) {
|
if (GrabInProgress) {
|
||||||
XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
|
|
||||||
XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
|
|
||||||
XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
|
|
||||||
GrabInProgress = 0;
|
GrabInProgress = 0;
|
||||||
|
set_poll_clients();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1225,7 +1120,6 @@ void
|
||||||
IgnoreClient(ClientPtr client)
|
IgnoreClient(ClientPtr client)
|
||||||
{
|
{
|
||||||
OsCommPtr oc = (OsCommPtr) client->osPrivate;
|
OsCommPtr oc = (OsCommPtr) client->osPrivate;
|
||||||
int connection = oc->fd;
|
|
||||||
|
|
||||||
client->ignoreCount++;
|
client->ignoreCount++;
|
||||||
if (client->ignoreCount > 1)
|
if (client->ignoreCount > 1)
|
||||||
|
@ -1233,25 +1127,9 @@ IgnoreClient(ClientPtr client)
|
||||||
|
|
||||||
isItTimeToYield = TRUE;
|
isItTimeToYield = TRUE;
|
||||||
mark_client_not_ready(client);
|
mark_client_not_ready(client);
|
||||||
if (!GrabInProgress || FD_ISSET(connection, &AllClients)) {
|
|
||||||
if (FD_ISSET(connection, &ClientsWithInput))
|
oc->flags |= OS_COMM_IGNORED;
|
||||||
FD_SET(connection, &IgnoredClientsWithInput);
|
set_poll_client(client);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
|
@ -1263,28 +1141,15 @@ void
|
||||||
AttendClient(ClientPtr client)
|
AttendClient(ClientPtr client)
|
||||||
{
|
{
|
||||||
OsCommPtr oc = (OsCommPtr) client->osPrivate;
|
OsCommPtr oc = (OsCommPtr) client->osPrivate;
|
||||||
int connection = oc->fd;
|
|
||||||
|
|
||||||
client->ignoreCount--;
|
client->ignoreCount--;
|
||||||
if (client->ignoreCount)
|
if (client->ignoreCount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!GrabInProgress || GrabInProgress == client->index ||
|
oc->flags &= ~OS_COMM_IGNORED;
|
||||||
FD_ISSET(connection, &GrabImperviousClients)) {
|
set_poll_client(client);
|
||||||
FD_SET(connection, &AllClients);
|
if (listen_to_client(client))
|
||||||
FD_SET(connection, &AllSockets);
|
|
||||||
FD_SET(connection, &LastSelectMask);
|
|
||||||
if (FD_ISSET(connection, &IgnoredClientsWithInput)) {
|
|
||||||
FD_SET(connection, &ClientsWithInput);
|
|
||||||
mark_client_ready(client);
|
mark_client_ready(client);
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
FD_SET(connection, &SavedAllClients);
|
|
||||||
FD_SET(connection, &SavedAllSockets);
|
|
||||||
if (FD_ISSET(connection, &IgnoredClientsWithInput))
|
|
||||||
FD_SET(connection, &SavedClientsWithInput);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make client impervious to grabs; assume only executing client calls this */
|
/* make client impervious to grabs; assume only executing client calls this */
|
||||||
|
@ -1293,9 +1158,9 @@ void
|
||||||
MakeClientGrabImpervious(ClientPtr client)
|
MakeClientGrabImpervious(ClientPtr client)
|
||||||
{
|
{
|
||||||
OsCommPtr oc = (OsCommPtr) client->osPrivate;
|
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) {
|
if (ServerGrabCallback) {
|
||||||
ServerGrabInfoRec grabinfo;
|
ServerGrabInfoRec grabinfo;
|
||||||
|
@ -1312,18 +1177,10 @@ void
|
||||||
MakeClientGrabPervious(ClientPtr client)
|
MakeClientGrabPervious(ClientPtr client)
|
||||||
{
|
{
|
||||||
OsCommPtr oc = (OsCommPtr) client->osPrivate;
|
OsCommPtr oc = (OsCommPtr) client->osPrivate;
|
||||||
int connection = oc->fd;
|
|
||||||
|
|
||||||
FD_CLR(connection, &GrabImperviousClients);
|
oc->flags &= ~OS_COMM_GRAB_IMPERVIOUS;
|
||||||
if (GrabInProgress && (GrabInProgress != client->index)) {
|
set_poll_client(client);
|
||||||
if (FD_ISSET(connection, &ClientsWithInput)) {
|
|
||||||
FD_SET(connection, &SavedClientsWithInput);
|
|
||||||
FD_CLR(connection, &ClientsWithInput);
|
|
||||||
}
|
|
||||||
FD_CLR(connection, &AllSockets);
|
|
||||||
FD_CLR(connection, &AllClients);
|
|
||||||
isItTimeToYield = TRUE;
|
isItTimeToYield = TRUE;
|
||||||
}
|
|
||||||
|
|
||||||
if (ServerGrabCallback) {
|
if (ServerGrabCallback) {
|
||||||
ServerGrabInfoRec grabinfo;
|
ServerGrabInfoRec grabinfo;
|
||||||
|
@ -1405,3 +1262,46 @@ AddClientOnOpenFD(int fd)
|
||||||
|
|
||||||
return TRUE;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
95
os/io.c
95
os/io.c
|
@ -74,7 +74,6 @@ SOFTWARE.
|
||||||
#include <X11/Xproto.h>
|
#include <X11/Xproto.h>
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "osdep.h"
|
#include "osdep.h"
|
||||||
#include <X11/Xpoll.h>
|
|
||||||
#include "opaque.h"
|
#include "opaque.h"
|
||||||
#include "dixstruct.h"
|
#include "dixstruct.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
@ -188,7 +187,7 @@ static void
|
||||||
YieldControlNoInput(int fd)
|
YieldControlNoInput(int fd)
|
||||||
{
|
{
|
||||||
YieldControl();
|
YieldControl();
|
||||||
FD_CLR(fd, &ClientsWithInput);
|
ospoll_reset_events(server_poll, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -439,24 +438,8 @@ ReadRequestFromClient(ClientPtr client)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
gotnow -= needed;
|
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)
|
if (!gotnow)
|
||||||
AvailableInput = oc;
|
AvailableInput = oc;
|
||||||
FD_CLR(fd, &ClientsWithInput);
|
|
||||||
}
|
|
||||||
if (move_header) {
|
if (move_header) {
|
||||||
request = (xReq *) oci->bufptr;
|
request = (xReq *) oci->bufptr;
|
||||||
oci->bufptr += (sizeof(xBigReq) - sizeof(xReq));
|
oci->bufptr += (sizeof(xBigReq) - sizeof(xReq));
|
||||||
|
@ -549,7 +532,7 @@ InsertFakeRequest(ClientPtr client, char *data, int count)
|
||||||
gotnow += count;
|
gotnow += count;
|
||||||
if ((gotnow >= sizeof(xReq)) &&
|
if ((gotnow >= sizeof(xReq)) &&
|
||||||
(gotnow >= (int) (get_req_len((xReq *) oci->bufptr, client) << 2)))
|
(gotnow >= (int) (get_req_len((xReq *) oci->bufptr, client) << 2)))
|
||||||
FD_SET(fd, &ClientsWithInput);
|
mark_client_ready(client);
|
||||||
else
|
else
|
||||||
YieldControlNoInput(fd);
|
YieldControlNoInput(fd);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -589,12 +572,8 @@ ResetCurrentRequest(ClientPtr client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gotnow >= (needed << 2)) {
|
if (gotnow >= (needed << 2)) {
|
||||||
if (FD_ISSET(fd, &AllClients)) {
|
if (listen_to_client(client))
|
||||||
FD_SET(fd, &ClientsWithInput);
|
mark_client_ready(client);
|
||||||
}
|
|
||||||
else {
|
|
||||||
FD_SET(fd, &IgnoredClientsWithInput);
|
|
||||||
}
|
|
||||||
YieldControl();
|
YieldControl();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -615,16 +594,10 @@ ResetCurrentRequest(ClientPtr client)
|
||||||
void
|
void
|
||||||
FlushAllOutput(void)
|
FlushAllOutput(void)
|
||||||
{
|
{
|
||||||
register int index, base;
|
|
||||||
register fd_mask mask; /* raphael */
|
|
||||||
OsCommPtr oc;
|
OsCommPtr oc;
|
||||||
register ClientPtr client;
|
register ClientPtr client, tmp;
|
||||||
Bool newoutput = NewOutputPending;
|
Bool newoutput = NewOutputPending;
|
||||||
|
|
||||||
#if defined(WIN32)
|
|
||||||
fd_set newOutputPending;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (FlushCallback)
|
if (FlushCallback)
|
||||||
CallCallbacks(&FlushCallback, NULL);
|
CallCallbacks(&FlushCallback, NULL);
|
||||||
|
|
||||||
|
@ -639,48 +612,14 @@ FlushAllOutput(void)
|
||||||
CriticalOutputPending = FALSE;
|
CriticalOutputPending = FALSE;
|
||||||
NewOutputPending = FALSE;
|
NewOutputPending = FALSE;
|
||||||
|
|
||||||
#ifndef WIN32
|
xorg_list_for_each_entry_safe(client, tmp, &output_pending_clients, output_pending) {
|
||||||
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)
|
if (client->clientGone)
|
||||||
continue;
|
continue;
|
||||||
|
if (!client_is_ready(client)) {
|
||||||
oc = (OsCommPtr) client->osPrivate;
|
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);
|
(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];
|
|
||||||
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
|
|
||||||
(void) FlushClient(client, oc, (char *) NULL, 0);
|
|
||||||
}
|
|
||||||
XFD_COPYSET(&newOutputPending, &OutputPending);
|
|
||||||
#endif /* WIN32 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -822,8 +761,8 @@ WriteToClient(ClientPtr who, int count, const void *__buf)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (oco->count == 0 || oco->count + count + padBytes > oco->size) {
|
if (oco->count == 0 || oco->count + count + padBytes > oco->size) {
|
||||||
FD_CLR(oc->fd, &OutputPending);
|
output_pending_clear(who);
|
||||||
if (!XFD_ANYSET(&OutputPending)) {
|
if (!any_output_pending()) {
|
||||||
CriticalOutputPending = FALSE;
|
CriticalOutputPending = FALSE;
|
||||||
NewOutputPending = FALSE;
|
NewOutputPending = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -835,7 +774,7 @@ WriteToClient(ClientPtr who, int count, const void *__buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
NewOutputPending = TRUE;
|
NewOutputPending = TRUE;
|
||||||
FD_SET(oc->fd, &OutputPending);
|
output_pending_mark(who);
|
||||||
memmove((char *) oco->buf + oco->count, buf, count);
|
memmove((char *) oco->buf + oco->count, buf, count);
|
||||||
oco->count += count;
|
oco->count += count;
|
||||||
if (padBytes) {
|
if (padBytes) {
|
||||||
|
@ -859,7 +798,6 @@ int
|
||||||
FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount)
|
FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount)
|
||||||
{
|
{
|
||||||
ConnectionOutputPtr oco = oc->output;
|
ConnectionOutputPtr oco = oc->output;
|
||||||
int connection = oc->fd;
|
|
||||||
XtransConnInfo trans_conn = oc->trans_conn;
|
XtransConnInfo trans_conn = oc->trans_conn;
|
||||||
struct iovec iov[3];
|
struct iovec iov[3];
|
||||||
static char padBuffer[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
|
/* 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
|
and not ready to accept more. Make a note of it and buffer
|
||||||
the rest. */
|
the rest. */
|
||||||
FD_SET(connection, &ClientsWriteBlocked);
|
output_pending_mark(who);
|
||||||
AnyWritesPending = TRUE;
|
|
||||||
|
|
||||||
if (written < oco->count) {
|
if (written < oco->count) {
|
||||||
if (written > 0) {
|
if (written > 0) {
|
||||||
|
@ -973,6 +910,8 @@ FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount)
|
||||||
extraBuf + written, len);
|
extraBuf + written, len);
|
||||||
|
|
||||||
oco->count = notWritten; /* this will include the pad */
|
oco->count = notWritten; /* this will include the pad */
|
||||||
|
ospoll_listen(server_poll, oc->fd, X_NOTIFY_WRITE);
|
||||||
|
|
||||||
/* return only the amount explicitly requested */
|
/* return only the amount explicitly requested */
|
||||||
return extraCount;
|
return extraCount;
|
||||||
}
|
}
|
||||||
|
@ -995,12 +934,8 @@ FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount)
|
||||||
|
|
||||||
/* everything was flushed out */
|
/* everything was flushed out */
|
||||||
oco->count = 0;
|
oco->count = 0;
|
||||||
/* check to see if this client was write blocked */
|
output_pending_clear(who);
|
||||||
if (AnyWritesPending) {
|
|
||||||
FD_CLR(oc->fd, &ClientsWriteBlocked);
|
|
||||||
if (!XFD_ANYSET(&ClientsWriteBlocked) && NumNotifyWriteFd == 0)
|
|
||||||
AnyWritesPending = FALSE;
|
|
||||||
}
|
|
||||||
if (oco->size > BUFWATERMARK) {
|
if (oco->size > BUFWATERMARK) {
|
||||||
free(oco->buf);
|
free(oco->buf);
|
||||||
free(oco);
|
free(oco);
|
||||||
|
|
27
os/osdep.h
27
os/osdep.h
|
@ -162,8 +162,12 @@ typedef struct _osComm {
|
||||||
XID auth_id; /* authorization id */
|
XID auth_id; /* authorization id */
|
||||||
CARD32 conn_time; /* timestamp if not established, else 0 */
|
CARD32 conn_time; /* timestamp if not established, else 0 */
|
||||||
struct _XtransConnInfo *trans_conn; /* transport connection object */
|
struct _XtransConnInfo *trans_conn; /* transport connection object */
|
||||||
|
int flags;
|
||||||
} OsCommRec, *OsCommPtr;
|
} OsCommRec, *OsCommPtr;
|
||||||
|
|
||||||
|
#define OS_COMM_GRAB_IMPERVIOUS 1
|
||||||
|
#define OS_COMM_IGNORED 2
|
||||||
|
|
||||||
extern int FlushClient(ClientPtr /*who */ ,
|
extern int FlushClient(ClientPtr /*who */ ,
|
||||||
OsCommPtr /*oc */ ,
|
OsCommPtr /*oc */ ,
|
||||||
const void * /*extraBuf */ ,
|
const void * /*extraBuf */ ,
|
||||||
|
@ -173,24 +177,13 @@ extern int FlushClient(ClientPtr /*who */ ,
|
||||||
extern void FreeOsBuffers(OsCommPtr /*oc */
|
extern void FreeOsBuffers(OsCommPtr /*oc */
|
||||||
);
|
);
|
||||||
|
|
||||||
extern void InitNotifyFds(void);
|
|
||||||
|
|
||||||
extern void HandleNotifyFds(void);
|
|
||||||
|
|
||||||
#include "dix.h"
|
#include "dix.h"
|
||||||
|
#include "ospoll.h"
|
||||||
|
|
||||||
extern fd_set AllSockets;
|
extern struct ospoll *server_poll;
|
||||||
extern fd_set AllClients;
|
|
||||||
extern fd_set LastSelectMask;
|
Bool
|
||||||
extern fd_set LastSelectWriteMask;
|
listen_to_client(ClientPtr client);
|
||||||
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;
|
|
||||||
|
|
||||||
#if !defined(WIN32) || defined(__CYGWIN__)
|
#if !defined(WIN32) || defined(__CYGWIN__)
|
||||||
extern int *ConnectionTranslation;
|
extern int *ConnectionTranslation;
|
||||||
|
@ -201,8 +194,6 @@ extern void ClearConnectionTranslation(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern Bool NewOutputPending;
|
extern Bool NewOutputPending;
|
||||||
extern Bool AnyWritesPending;
|
|
||||||
extern Bool NumNotifyWriteFd;
|
|
||||||
|
|
||||||
extern WorkQueuePtr workQueue;
|
extern WorkQueuePtr workQueue;
|
||||||
|
|
||||||
|
|
|
@ -195,7 +195,9 @@ OsInit(void)
|
||||||
#ifdef BUSFAULT
|
#ifdef BUSFAULT
|
||||||
busfault_init();
|
busfault_init();
|
||||||
#endif
|
#endif
|
||||||
InitNotifyFds();
|
server_poll = ospoll_create();
|
||||||
|
if (!server_poll)
|
||||||
|
FatalError("failed to allocate poll structure");
|
||||||
|
|
||||||
#ifdef HAVE_BACKTRACE
|
#ifdef HAVE_BACKTRACE
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
#include <X11/Xmd.h>
|
#include <X11/Xmd.h>
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include <X11/Xpoll.h>
|
|
||||||
#include "osdep.h"
|
#include "osdep.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "dixstruct.h"
|
#include "dixstruct.h"
|
||||||
|
|
Loading…
Reference in New Issue