[PATCH xserver 12/25] dix: Use list for ready clients
Keith Packard
keithp at keithp.com
Wed May 25 05:38:49 UTC 2016
This converts the dispatch loop into using a list of ready clients
instead of an array. For now, that list is constructed from the array
returned by WaitForSomething.
Signed-off-by: Keith Packard <keithp at keithp.com>
---
dix/dispatch.c | 86 ++++++++++++++++++++++++++++++++++-------------------
include/dixstruct.h | 8 +++++
2 files changed, 64 insertions(+), 30 deletions(-)
diff --git a/dix/dispatch.c b/dix/dispatch.c
index 89c0a4e..f7ac931 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -241,23 +241,52 @@ long SmartLastPrint;
void Dispatch(void);
-static int
-SmartScheduleClient(int *clientReady, int nready)
+static struct xorg_list ready_clients;
+
+static void
+init_client_ready(void)
{
- ClientPtr pClient;
- int i;
- int client;
- int bestPrio, best = 0;
+ xorg_list_init(&ready_clients);
+}
+
+static Bool
+clients_are_ready(void)
+{
+ return !xorg_list_is_empty(&ready_clients);
+}
+
+/* Client has requests queued or data on the network */
+void
+mark_client_ready(ClientPtr client)
+{
+ if (xorg_list_is_empty(&client->ready))
+ xorg_list_append(&client->ready, &ready_clients);
+}
+
+/* Client has no requests queued and no data on network */
+void
+mark_client_not_ready(ClientPtr client)
+{
+ xorg_list_del(&client->ready);
+}
+
+static ClientPtr
+SmartScheduleClient(void)
+{
+ ClientPtr pClient, best = NULL;
+ int bestPrio;
int bestRobin, robin;
long now = SmartScheduleTime;
long idle;
+ int nready = 0;
bestPrio = -0x7fffffff;
bestRobin = 0;
idle = 2 * SmartScheduleSlice;
- for (i = 0; i < nready; i++) {
- client = clientReady[i];
- pClient = clients[client];
+
+ xorg_list_for_each_entry(pClient, &ready_clients, ready) {
+ nready++;
+
/* Praise clients which haven't run in a while */
if ((now - pClient->smart_stop_tick) >= idle) {
if (pClient->smart_priority < 0)
@@ -273,27 +302,26 @@ SmartScheduleClient(int *clientReady, int nready)
(pClient->smart_priority == bestPrio && robin > bestRobin)) {
bestPrio = pClient->smart_priority;
bestRobin = robin;
- best = client;
+ best = pClient;
}
#ifdef SMART_DEBUG
if ((now - SmartLastPrint) >= 5000)
- fprintf(stderr, " %2d: %3d", client, pClient->smart_priority);
+ fprintf(stderr, " %2d: %3d", pClient->index, pClient->smart_priority);
#endif
}
#ifdef SMART_DEBUG
if ((now - SmartLastPrint) >= 5000) {
- fprintf(stderr, " use %2d\n", best);
+ fprintf(stderr, " use %2d\n", best->index);
SmartLastPrint = now;
}
#endif
- pClient = clients[best];
- SmartLastIndex[bestPrio - SMART_MIN_PRIORITY] = pClient->index;
+ SmartLastIndex[bestPrio - SMART_MIN_PRIORITY] = best->index;
/*
* Set current client pointer
*/
- if (SmartLastClient != pClient) {
- pClient->smart_start_tick = now;
- SmartLastClient = pClient;
+ if (SmartLastClient != best) {
+ best->smart_start_tick = now;
+ SmartLastClient = best;
}
/*
* Adjust slice
@@ -358,25 +386,22 @@ Dispatch(void)
nready = WaitForSomething(clientReady);
- if (nready) {
- clientReady[0] = SmartScheduleClient(clientReady, nready);
- nready = 1;
- }
+ init_client_ready();
+ for (result = 0; result < nready; result++)
+ mark_client_ready(clients[clientReady[result]]);
+
/*****************
* Handle events in round robin fashion, doing input between
* each round
*****************/
- while (!dispatchException && (--nready >= 0)) {
- client = clients[clientReady[nready]];
- if (!client) {
- /* KillClient can cause this to happen */
- continue;
- }
+ if (!dispatchException && clients_are_ready()) {
+ client = SmartScheduleClient();
+
/* GrabServer activation can cause this to be true */
if (grabState == GrabKickout) {
grabState = GrabActive;
- break;
+ continue;
}
isItTimeToYield = FALSE;
@@ -450,8 +475,7 @@ Dispatch(void)
}
}
FlushAllOutput();
- client = clients[clientReady[nready]];
- if (client)
+ if (client == SmartLastClient)
client->smart_stop_tick = SmartScheduleTime;
}
dispatchException &= ~DE_PRIORITYCHANGE;
@@ -3370,6 +3394,7 @@ CloseDownClient(ClientPtr client)
if (grabState != GrabNone && grabClient == client) {
UngrabServer(client);
}
+ mark_client_not_ready(client);
BITCLEAR(grabWaiters, client->index);
DeleteClientFromAnySelections(client);
ReleaseActiveGrabs(client);
@@ -3459,6 +3484,7 @@ void
InitClient(ClientPtr client, int i, void *ospriv)
{
client->index = i;
+ xorg_list_init(&client->ready);
client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
client->closeDownMode = i ? DestroyAll : RetainPermanent;
client->requestVector = InitialVector;
diff --git a/include/dixstruct.h b/include/dixstruct.h
index 8e70ae1..ada45bd 100644
--- a/include/dixstruct.h
+++ b/include/dixstruct.h
@@ -76,6 +76,7 @@ typedef struct _saveSet {
typedef struct _Client {
void *requestBuffer;
void *osPrivate; /* for OS layer, including scheduler */
+ struct xorg_list ready; /* List of clients ready to run */
Mask clientAsMask;
short index;
unsigned char majorOp, minorOp;
@@ -138,6 +139,13 @@ extern Bool SmartScheduleSignalEnable;
extern void SmartScheduleStartTimer(void);
extern void SmartScheduleStopTimer(void);
+/* Client has requests queued or data on the network */
+void mark_client_ready(ClientPtr client);
+
+/* Client has no requests queued and no data on network */
+void mark_client_not_ready(ClientPtr client);
+
+
#define SMART_MAX_PRIORITY (20)
#define SMART_MIN_PRIORITY (-20)
--
2.8.0.rc3
More information about the xorg-devel
mailing list