> 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);