[PATCH xserver] dix: Allow secondary threads to use the work queue
Peter Hutterer
peter.hutterer at who-t.net
Thu Feb 23 21:31:32 UTC 2017
On Thu, Feb 23, 2017 at 04:25:35PM -0500, Adam Jackson wrote:
> The work queue code is reentrant with itself on a single thread, but not
> when the queue is modified from thread A while being run on thread B.
> We will only ever run it from the main thread, but the input thread
> wants to be able to queue work for event emission. Mutex the list so it
> can do so safely.
>
> This does mean queued work should be cheap to execute since if the lock
> is contended the input thread will block. That was always true though.
> If this contention turns out to be a problem, we can fix how we walk the
> work queue to hold the lock less.
>
> Signed-off-by: Adam Jackson <ajax at redhat.com>
> ---
> dix/dixutils.c | 22 ++++++++++++++++++++++
> dix/main.c | 2 ++
> include/dix.h | 3 +--
> 3 files changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/dix/dixutils.c b/dix/dixutils.c
> index 540023c..a282b15 100644
> --- a/dix/dixutils.c
> +++ b/dix/dixutils.c
> @@ -506,12 +506,29 @@ InitBlockAndWakeupHandlers(void)
>
> WorkQueuePtr workQueue;
> static WorkQueuePtr *workQueueLast = &workQueue;
> +static pthread_mutex_t wq_mutex;
I'm not a fan of changing the naming scheme here...
otherwise Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
Cheers,
Peter
> +
> +Bool
> +InitWorkQueue(void)
> +{
> + if (serverGeneration == 1) {
> + pthread_mutexattr_t attr;
> +
> + pthread_mutexattr_init(&attr);
> + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
> + if (pthread_mutex_init(&wq_mutex, &attr))
> + FatalError("Could not initialize work queue lock");
> + }
> +
> + return TRUE;
> +}
>
> void
> ProcessWorkQueue(void)
> {
> WorkQueuePtr q, *p;
>
> + pthread_mutex_lock(&wq_mutex);
> p = &workQueue;
> /*
> * Scan the work queue once, calling each function. Those
> @@ -530,6 +547,7 @@ ProcessWorkQueue(void)
> }
> }
> workQueueLast = p;
> + pthread_mutex_unlock(&wq_mutex);
> }
>
> void
> @@ -537,6 +555,7 @@ ProcessWorkQueueZombies(void)
> {
> WorkQueuePtr q, *p;
>
> + pthread_mutex_lock(&wq_mutex);
> p = &workQueue;
> while ((q = *p)) {
> if (q->client && q->client->clientGone) {
> @@ -550,6 +569,7 @@ ProcessWorkQueueZombies(void)
> }
> }
> workQueueLast = p;
> + pthread_mutex_unlock(&wq_mutex);
> }
>
> Bool
> @@ -565,8 +585,10 @@ QueueWorkProc(Bool (*function) (ClientPtr pClient, void *closure),
> q->client = client;
> q->closure = closure;
> q->next = NULL;
> + pthread_mutex_lock(&wq_mutex);
> *workQueueLast = q;
> workQueueLast = &q->next;
> + pthread_mutex_unlock(&wq_mutex);
> return TRUE;
> }
>
> diff --git a/dix/main.c b/dix/main.c
> index 4947062..0278bf5 100644
> --- a/dix/main.c
> +++ b/dix/main.c
> @@ -154,6 +154,8 @@ dix_main(int argc, char *argv[], char *envp[])
> DPMSPowerLevel = 0;
> #endif
> InitBlockAndWakeupHandlers();
> + InitWorkQueue();
> +
> /* Perform any operating system dependent initializations you'd like */
> OsInit();
> if (serverGeneration == 1) {
> diff --git a/include/dix.h b/include/dix.h
> index 240018b..3e3a672 100644
> --- a/include/dix.h
> +++ b/include/dix.h
> @@ -240,10 +240,9 @@ extern _X_EXPORT void RemoveBlockAndWakeupHandlers(ServerBlockHandlerProcPtr blo
>
> extern _X_EXPORT void InitBlockAndWakeupHandlers(void);
>
> +extern _X_EXPORT Bool InitWorkQueue(void);
> extern _X_EXPORT void ProcessWorkQueue(void);
> -
> extern _X_EXPORT void ProcessWorkQueueZombies(void);
> -
> extern _X_EXPORT Bool QueueWorkProc(Bool (*function)(ClientPtr clientUnused,
> void *closure),
> ClientPtr client,
> --
> 2.9.3
>
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: https://lists.x.org/mailman/listinfo/xorg-devel
>
More information about the xorg-devel
mailing list