> Date: Wed, 12 Jun 2019 23:57:27 +0200 (CEST)
> From: Mark Kettenis <mark.kette...@xs4all.nl>
> 
> > From: "Sven M. Hallberg" <pe...@khjk.org>
> > Date: Wed, 12 Jun 2019 23:18:24 +0200
> > 
> > Mark Kettenis on Tue, Jun 11 2019:
> > > The drm(4) codebase really needs multi-threaded task queues [...]
> > >
> > > The diff also starts 4 threads for each workqueue that gets created by
> > > the drm(4) layer.  The number 4 is a bit arbitrary but it is the
> > > number of threads that Linux creates per CPU for a so-called "unbound"
> > > workqueue which hopefully is enough to always make progress.
> > > 
> > > Please test.
> > 
> > Looks good and appears to work fine with two displays (one internal, one
> > external). Will test with three at work tomorrow.
> > 
> > 
> > > - dev_priv->hotplug.poll_init_work.tq = systq;
> > 
> > Intentional?
> 
> Yes.  It removes a local modification that should no longer be necessary.
> 
> Unfortunately the diff doesn't work with amdgpu.  Some more thinking
> needed...

So here is a diff that fixes the problem as far as I can tell.
Jonathan, Sven, can you give this a go?

Index: dev/pci/drm/drm_linux.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/drm_linux.c,v
retrieving revision 1.38
diff -u -p -r1.38 drm_linux.c
--- dev/pci/drm/drm_linux.c     9 Jun 2019 12:58:30 -0000       1.38
+++ dev/pci/drm/drm_linux.c     13 Jun 2019 20:53:23 -0000
@@ -1399,15 +1399,15 @@ drm_linux_init(void)
 {
        if (system_wq == NULL) {
                system_wq = (struct workqueue_struct *)
-                   taskq_create("drmwq", 1, IPL_HIGH, 0);
+                   taskq_create("drmwq", 4, IPL_HIGH, 0);
        }
        if (system_unbound_wq == NULL) {
                system_unbound_wq = (struct workqueue_struct *)
-                   taskq_create("drmubwq", 1, IPL_HIGH, 0);
+                   taskq_create("drmubwq", 4, IPL_HIGH, 0);
        }
        if (system_long_wq == NULL) {
                system_long_wq = (struct workqueue_struct *)
-                   taskq_create("drmlwq", 1, IPL_HIGH, 0);
+                   taskq_create("drmlwq", 4, IPL_HIGH, 0);
        }
 
        if (taskletq == NULL)
Index: dev/pci/drm/i915/intel_hotplug.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/intel_hotplug.c,v
retrieving revision 1.2
diff -u -p -r1.2 intel_hotplug.c
--- dev/pci/drm/i915/intel_hotplug.c    14 Apr 2019 10:14:52 -0000      1.2
+++ dev/pci/drm/i915/intel_hotplug.c    13 Jun 2019 20:53:23 -0000
@@ -619,7 +619,6 @@ void intel_hpd_init_work(struct drm_i915
        INIT_WORK(&dev_priv->hotplug.hotplug_work, i915_hotplug_work_func);
        INIT_WORK(&dev_priv->hotplug.dig_port_work, i915_digport_work_func);
        INIT_WORK(&dev_priv->hotplug.poll_init_work, i915_hpd_poll_init_work);
-       dev_priv->hotplug.poll_init_work.tq = systq;
        INIT_DELAYED_WORK(&dev_priv->hotplug.reenable_work,
                          intel_hpd_irq_storm_reenable_work);
 }
Index: kern/kern_task.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_task.c,v
retrieving revision 1.25
diff -u -p -r1.25 kern_task.c
--- kern/kern_task.c    28 Apr 2019 04:20:40 -0000      1.25
+++ kern/kern_task.c    13 Jun 2019 20:53:23 -0000
@@ -43,6 +43,7 @@ struct taskq {
                TQ_S_DESTROYED
        }                        tq_state;
        unsigned int             tq_running;
+       unsigned int             tq_waiting;
        unsigned int             tq_nthreads;
        unsigned int             tq_flags;
        const char              *tq_name;
@@ -59,6 +60,7 @@ static const char taskq_sys_name[] = "sy
 struct taskq taskq_sys = {
        TQ_S_CREATED,
        0,
+       0,
        1,
        0,
        taskq_sys_name,
@@ -77,6 +79,7 @@ static const char taskq_sys_mp_name[] = 
 struct taskq taskq_sys_mp = {
        TQ_S_CREATED,
        0,
+       0,
        1,
        TASKQ_MPSAFE,
        taskq_sys_mp_name,
@@ -122,6 +125,7 @@ taskq_create(const char *name, unsigned 
 
        tq->tq_state = TQ_S_CREATED;
        tq->tq_running = 0;
+       tq->tq_waiting = 0;
        tq->tq_nthreads = nthreads;
        tq->tq_name = name;
        tq->tq_flags = flags;
@@ -223,6 +227,7 @@ taskq_barrier(struct taskq *tq)
 
        WITNESS_CHECKORDER(&tq->tq_lock_object, LOP_NEWORDER, NULL);
 
+       SET(t.t_flags, TASK_BARRIER);
        task_add(tq, &t);
        cond_wait(&c, "tqbar");
 }
@@ -238,6 +243,7 @@ taskq_del_barrier(struct taskq *tq, stru
        if (task_del(tq, del))
                return;
 
+       SET(t.t_flags, TASK_BARRIER);
        task_add(tq, &t);
        cond_wait(&c, "tqbar");
 }
@@ -304,13 +310,26 @@ taskq_next_work(struct taskq *tq, struct
        struct task *next;
 
        mtx_enter(&tq->tq_mtx);
+retry:
        while ((next = TAILQ_FIRST(&tq->tq_worklist)) == NULL) {
                if (tq->tq_state != TQ_S_RUNNING) {
                        mtx_leave(&tq->tq_mtx);
                        return (0);
                }
 
+               tq->tq_waiting++;
                msleep(tq, &tq->tq_mtx, PWAIT, "bored", 0);
+               tq->tq_waiting--;
+       }
+
+       if (ISSET(next->t_flags, TASK_BARRIER)) {
+               if (++tq->tq_waiting == tq->tq_nthreads) {
+                       tq->tq_waiting--;
+               } else {
+                       msleep(tq, &tq->tq_mtx, PWAIT, "tqblk", 0);
+                       tq->tq_waiting--;
+                       goto retry;
+               }
        }
 
        TAILQ_REMOVE(&tq->tq_worklist, next, t_entry);
Index: sys/task.h
===================================================================
RCS file: /cvs/src/sys/sys/task.h,v
retrieving revision 1.15
diff -u -p -r1.15 task.h
--- sys/task.h  28 Apr 2019 04:20:40 -0000      1.15
+++ sys/task.h  13 Jun 2019 20:53:23 -0000
@@ -31,6 +31,7 @@ struct task {
 };
 
 #define TASK_ONQUEUE           1
+#define TASK_BARRIER           2
 
 TAILQ_HEAD(task_list, task);
 

Reply via email to