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 <kei...@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 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel