[PATCH xserver 15/25] Modify ready_client list directly from WaitForSomething
Keith Packard
keithp at keithp.com
Wed May 25 05:38:52 UTC 2016
This changes the WaitForSomething API so that it only notifies DIX
when a client becomes ready to read. This avoids walking over all
existing ready clients to compute the total set each time.
Signed-off-by: Keith Packard <keithp at keithp.com>
---
dix/dispatch.c | 45 +++++++++++++++++++++++++++++++++------------
include/os.h | 3 +--
os/WaitFor.c | 36 +++++++++++++++++-------------------
os/connection.c | 5 ++++-
4 files changed, 55 insertions(+), 34 deletions(-)
diff --git a/dix/dispatch.c b/dix/dispatch.c
index 76e392b..e3dc9b2 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -241,11 +241,13 @@ long SmartLastPrint;
void Dispatch(void);
static struct xorg_list ready_clients;
+static struct xorg_list saved_ready_clients;
static void
init_client_ready(void)
{
xorg_list_init(&ready_clients);
+ xorg_list_init(&saved_ready_clients);
}
static Bool
@@ -269,6 +271,30 @@ mark_client_not_ready(ClientPtr client)
xorg_list_del(&client->ready);
}
+static void
+mark_client_grab(ClientPtr grab)
+{
+ ClientPtr client, tmp;
+
+ xorg_list_for_each_entry_safe(client, tmp, &ready_clients, ready) {
+ if (client != grab) {
+ xorg_list_del(&client->ready);
+ xorg_list_append(&client->ready, &saved_ready_clients);
+ }
+ }
+}
+
+static void
+mark_client_ungrab(void)
+{
+ ClientPtr client, tmp;
+
+ xorg_list_for_each_entry_safe(client, tmp, &saved_ready_clients, ready) {
+ xorg_list_del(&client->ready);
+ xorg_list_append(&client->ready, &ready_clients);
+ }
+}
+
static ClientPtr
SmartScheduleClient(void)
{
@@ -365,32 +391,25 @@ DisableLimitedSchedulingLatency(void)
void
Dispatch(void)
{
- int *clientReady; /* array of request ready clients */
int result;
ClientPtr client;
- int nready;
HWEventQueuePtr *icheck = checkForInput;
long start_tick;
nextFreeClientID = 1;
nClients = 0;
- clientReady = xallocarray(MaxClients, sizeof(int));
- if (!clientReady)
- return;
-
SmartScheduleSlice = SmartScheduleInterval;
+ init_client_ready();
+
while (!dispatchException) {
if (*icheck[0] != *icheck[1]) {
ProcessInputEvents();
FlushIfCriticalOutputPending();
}
- nready = WaitForSomething(clientReady);
-
- init_client_ready();
- for (result = 0; result < nready; result++)
- mark_client_ready(clients[clientReady[result]]);
+ if (!WaitForSomething(clients_are_ready()))
+ continue;
/*****************
* Handle events in round robin fashion, doing input between
@@ -419,6 +438,7 @@ Dispatch(void)
/* now, finally, deal with client requests */
result = ReadRequestFromClient(client);
if (result <= 0) {
+ mark_client_not_ready(client);
if (result < 0)
CloseDownClient(client);
break;
@@ -481,7 +501,6 @@ Dispatch(void)
ddxBeforeReset();
#endif
KillAllClients();
- free(clientReady);
dispatchException &= ~DE_RESET;
SmartScheduleLatencyLimited = 0;
ResetOsBuffers();
@@ -1081,6 +1100,7 @@ ProcGrabServer(ClientPtr client)
return rc;
grabState = GrabActive;
grabClient = client;
+ mark_client_grab(client);
if (ServerGrabCallback) {
ServerGrabInfoRec grabinfo;
@@ -1100,6 +1120,7 @@ UngrabServer(ClientPtr client)
grabState = GrabNone;
ListenToAllClients();
+ mark_client_ungrab();
for (i = mskcnt; --i >= 0 && !grabWaiters[i];);
if (i >= 0) {
i <<= 5;
diff --git a/include/os.h b/include/os.h
index 1ede9b9..aeb1034 100644
--- a/include/os.h
+++ b/include/os.h
@@ -93,8 +93,7 @@ extern _X_EXPORT void (*OsVendorVErrorFProc) (const char *,
_X_ATTRIBUTE_PRINTF(1, 0);
#endif
-extern _X_EXPORT int WaitForSomething(int * /*pClientsReady */
- );
+extern _X_EXPORT Bool WaitForSomething(Bool clients_are_ready);
extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ );
diff --git a/os/WaitFor.c b/os/WaitFor.c
index 26673e4..e78e358 100644
--- a/os/WaitFor.c
+++ b/os/WaitFor.c
@@ -142,8 +142,8 @@ static volatile OsTimerPtr timers = NULL;
* pClientsReady is an array to store ready client->index values into.
*****************/
-int
-WaitForSomething(int *pClientsReady)
+Bool
+WaitForSomething(Bool clients_are_ready)
{
int i;
struct timeval waittime, *wt;
@@ -154,7 +154,6 @@ WaitForSomething(int *pClientsReady)
int selecterr;
static int nready;
CARD32 now = 0;
- Bool someReady = FALSE;
Bool someNotifyWriteReady = FALSE;
FD_ZERO(&clientsReadable);
@@ -174,13 +173,11 @@ WaitForSomething(int *pClientsReady)
/* deal with any blocked jobs */
if (workQueue)
ProcessWorkQueue();
- if (XFD_ANYSET(&ClientsWithInput)) {
- someReady = TRUE;
+
+ if (clients_are_ready) {
waittime.tv_sec = 0;
waittime.tv_usec = 0;
wt = &waittime;
- }
- if (someReady) {
XFD_COPYSET(&AllSockets, &LastSelectMask);
XFD_UNSET(&LastSelectMask, &ClientsWithInput);
}
@@ -225,12 +222,12 @@ WaitForSomething(int *pClientsReady)
WakeupHandler(i);
if (i <= 0) { /* An error or timeout occurred */
if (dispatchException)
- return 0;
+ return FALSE;
if (i < 0) {
if (selecterr == EBADF) { /* Some client disconnected */
CheckConnections();
if (!XFD_ANYSET(&AllClients))
- return 0;
+ return FALSE;
}
else if (selecterr == EINVAL) {
FatalError("WaitForSomething(): select: %s\n",
@@ -241,7 +238,7 @@ WaitForSomething(int *pClientsReady)
strerror(selecterr));
}
}
- else if (someReady) {
+ else if (clients_are_ready) {
/*
* If no-one else is home, bail quickly
*/
@@ -250,7 +247,7 @@ WaitForSomething(int *pClientsReady)
break;
}
if (*checkForInput[0] != *checkForInput[1])
- return 0;
+ return FALSE;
if (timers) {
int expired = 0;
@@ -265,7 +262,7 @@ WaitForSomething(int *pClientsReady)
DoTimer(timers, now, &timers);
OsReleaseSignals();
- return 0;
+ return FALSE;
}
}
}
@@ -286,12 +283,11 @@ WaitForSomething(int *pClientsReady)
DoTimer(timers, now, &timers);
OsReleaseSignals();
- return 0;
+ return FALSE;
}
}
}
- if (someReady)
- XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask);
+
if (AnyWritesPending) {
XFD_ANDSET(&clientsWritable, &LastSelectWriteMask, &ClientsWriteBlocked);
if (XFD_ANYSET(&clientsWritable)) {
@@ -314,11 +310,12 @@ WaitForSomething(int *pClientsReady)
if (XFD_ANYSET(&tmp_set) || someNotifyWriteReady)
HandleNotifyFds();
- if (XFD_ANYSET(&clientsReadable))
+ if (clients_are_ready || XFD_ANYSET(&clientsReadable))
break;
+
/* check here for DDXes that queue events during Block/Wakeup */
if (*checkForInput[0] != *checkForInput[1])
- return 0;
+ return FALSE;
}
}
@@ -343,7 +340,8 @@ WaitForSomething(int *pClientsReady)
curclient = XFD_FD(&savedClientsReadable, i);
client_index = GetConnectionTranslation(curclient);
#endif
- pClientsReady[nready++] = client_index;
+ nready++;
+ mark_client_ready(clients[client_index]);
#ifndef WIN32
clientsReadable.fds_bits[i] &= ~(((fd_mask) 1L) << curclient);
}
@@ -356,7 +354,7 @@ WaitForSomething(int *pClientsReady)
if (nready)
SmartScheduleStartTimer();
- return nready;
+ return TRUE;
}
/* If time has rewound, re-run every affected timer.
diff --git a/os/connection.c b/os/connection.c
index b300025..d3fda35 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -1246,6 +1246,7 @@ IgnoreClient(ClientPtr client)
return;
isItTimeToYield = TRUE;
+ mark_client_not_ready(client);
if (!GrabInProgress || FD_ISSET(connection, &AllClients)) {
if (FD_ISSET(connection, &ClientsWithInput))
FD_SET(connection, &IgnoredClientsWithInput);
@@ -1287,8 +1288,10 @@ AttendClient(ClientPtr client)
FD_SET(connection, &AllClients);
FD_SET(connection, &AllSockets);
FD_SET(connection, &LastSelectMask);
- if (FD_ISSET(connection, &IgnoredClientsWithInput))
+ if (FD_ISSET(connection, &IgnoredClientsWithInput)) {
FD_SET(connection, &ClientsWithInput);
+ mark_client_ready(client);
+ }
}
else {
FD_SET(connection, &SavedAllClients);
--
2.8.0.rc3
More information about the xorg-devel
mailing list