Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-8]: src Pull up following revision(s) (requested by ozaki-r in ti...



details:   https://anonhg.NetBSD.org/src/rev/3fc112eae452
branches:  netbsd-8
changeset: 851301:3fc112eae452
user:      martin <martin%NetBSD.org@localhost>
date:      Tue Jan 16 13:01:10 2018 +0000

description:
Pull up following revision(s) (requested by ozaki-r in ticket #497):
        tests/rump/rumpkern/Makefile: revision 1.16
        tests/rump/kernspace/Makefile: revision 1.6
        tests/rump/kernspace/workqueue.c: revision 1.1
        tests/rump/kernspace/workqueue.c: revision 1.2
        tests/rump/kernspace/workqueue.c: revision 1.3
        tests/rump/kernspace/workqueue.c: revision 1.4
        tests/rump/kernspace/workqueue.c: revision 1.5
        tests/rump/kernspace/workqueue.c: revision 1.6
        tests/rump/rumpkern/t_workqueue.c: revision 1.1
        sys/sys/workqueue.h: revision 1.10
        tests/rump/rumpkern/t_workqueue.c: revision 1.2
        tests/rump/kernspace/kernspace.h: revision 1.5
        tests/rump/kernspace/kernspace.h: revision 1.6
        sys/net/if_bridge.c: revision 1.147
        distrib/sets/lists/debug/mi: revision 1.225
        sys/kern/subr_workqueue.c: revision 1.34
        share/man/man9/workqueue.9: revision 1.12
        sys/net/if_spppsubr.c: revision 1.178
        distrib/sets/lists/tests/mi: revision 1.763
Add simple test for workqueue(9)
Add declaration. build fix
sorry, I forgot to commit this file.
Tweak use of cv_timedwait
- Handle its return value
- Specify more appropriate time-out periods (2 ticks is too short)
Fix a race condition on taking the mutex
The workqueue worker can take the mutex before the tester tries to take it after
calling workqueue_enqueue. If it happens, the worker calls cv_broadcast before
the tester calls cv_timedwait and the tester will wait until the cv timed out
Take the mutex before calling workqueue_enqueue so that the tester surely calls
cv_timedwait before the worker calls cv_broadcast.
The fix stabilizes the test, t_workqueue/workqueue1.
Add workqueue_wait that waits for a specific work to finish
The caller must ensure that no new work is enqueued before calling
workqueue_wait. Note that Note that if the workqueue is WQ_PERCPU, the caller
can enqueue a new work to another queue other than the waiting queue.
Discussed on tech-kern@
Ensure the timer isn't running by using workqueue_wait
Functionalize some routines to add new tests easily (NFC)
Add a test case for workqueue_wait
Fix build

diffstat:

 distrib/sets/lists/debug/mi       |    3 +-
 distrib/sets/lists/tests/mi       |    3 +-
 share/man/man9/workqueue.9        |   21 +++++-
 sys/kern/subr_workqueue.c         |  105 +++++++++++++++++++++++-----
 sys/net/if_bridge.c               |    7 +-
 sys/net/if_spppsubr.c             |    5 +-
 sys/sys/workqueue.h               |    3 +-
 tests/rump/kernspace/Makefile     |    4 +-
 tests/rump/kernspace/kernspace.h  |    4 +-
 tests/rump/kernspace/workqueue.c  |  139 ++++++++++++++++++++++++++++++++++++++
 tests/rump/rumpkern/Makefile      |    3 +-
 tests/rump/rumpkern/t_workqueue.c |   81 ++++++++++++++++++++++
 12 files changed, 345 insertions(+), 33 deletions(-)

diffs (truncated from 611 to 300 lines):

diff -r e10ff110d400 -r 3fc112eae452 distrib/sets/lists/debug/mi
--- a/distrib/sets/lists/debug/mi       Tue Jan 16 12:03:44 2018 +0000
+++ b/distrib/sets/lists/debug/mi       Tue Jan 16 13:01:10 2018 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.216.2.7 2017/12/22 06:05:35 snj Exp $
+# $NetBSD: mi,v 1.216.2.8 2018/01/16 13:01:10 martin Exp $
 ./etc/mtree/set.debug                           comp-sys-root
 ./usr/lib                                      comp-sys-usr            compatdir
 ./usr/lib/i18n/libBIG5_g.a                     comp-c-debuglib         debuglib,compatfile
@@ -2305,6 +2305,7 @@
 ./usr/libdata/debug/usr/tests/rump/rumpkern/t_signals.debug            tests-syscall-debug     debug,atf,rump
 ./usr/libdata/debug/usr/tests/rump/rumpkern/t_threads.debug            tests-syscall-debug     debug,atf,rump
 ./usr/libdata/debug/usr/tests/rump/rumpkern/t_tsleep.debug             tests-syscall-debug     debug,atf,rump
+./usr/libdata/debug/usr/tests/rump/rumpkern/t_workqueue.debug          tests-syscall-debug     debug,atf,rump
 ./usr/libdata/debug/usr/tests/rump/rumpkern/t_vm.debug                 tests-syscall-debug     debug,atf,rump
 ./usr/libdata/debug/usr/tests/rump/rumpvfs/t_basic.debug               tests-syscall-debug     debug,atf,rump
 ./usr/libdata/debug/usr/tests/rump/rumpvfs/t_etfs.debug                tests-syscall-debug     debug,atf,rump
diff -r e10ff110d400 -r 3fc112eae452 distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi       Tue Jan 16 12:03:44 2018 +0000
+++ b/distrib/sets/lists/tests/mi       Tue Jan 16 13:01:10 2018 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.752.2.7 2017/12/21 21:08:13 snj Exp $
+# $NetBSD: mi,v 1.752.2.8 2018/01/16 13:01:10 martin Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -3417,6 +3417,7 @@
 ./usr/tests/rump/rumpkern/t_sp                 tests-rump-tests        atf,rump
 ./usr/tests/rump/rumpkern/t_threads            tests-rump-tests        atf,rump
 ./usr/tests/rump/rumpkern/t_tsleep             tests-rump-tests        atf,rump
+./usr/tests/rump/rumpkern/t_workqueue          tests-rump-tests        atf,rump
 ./usr/tests/rump/rumpkern/t_vm                 tests-rump-tests        atf,rump
 ./usr/tests/rump/rumpnet                       tests-rump-tests        compattestfile,atf
 ./usr/tests/rump/rumpnet/Atffile               tests-rump-tests        atf,rump
diff -r e10ff110d400 -r 3fc112eae452 share/man/man9/workqueue.9
--- a/share/man/man9/workqueue.9        Tue Jan 16 12:03:44 2018 +0000
+++ b/share/man/man9/workqueue.9        Tue Jan 16 13:01:10 2018 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: workqueue.9,v 1.11 2015/10/13 04:22:24 riastradh Exp $
+.\"    $NetBSD: workqueue.9,v 1.11.8.1 2018/01/16 13:01:10 martin Exp $
 .\"
 .\" Copyright (c)2005 YAMAMOTO Takashi,
 .\" All rights reserved.
@@ -25,7 +25,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\" ------------------------------------------------------------
-.Dd October 24, 2011
+.Dd December 28, 2017
 .Dt WORKQUEUE 9
 .Os
 .\" ------------------------------------------------------------
@@ -47,6 +47,10 @@
 "struct workqueue *wq" "struct work *wk" "struct cpu_info *ci"
 .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 .Ft void
+.Fn workqueue_wait \
+"struct workqueue *wq" "struct work *wk"
+.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+.Ft void
 .Fn workqueue_destroy \
 "struct workqueue *wq"
 .\" ------------------------------------------------------------
@@ -118,6 +122,19 @@
 framework.
 .Pp
 .\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+.Fn workqueue_wait
+waits for a specified work
+.Fa wk
+on the workqueue
+.Fa wq
+to finish.
+The caller must ensure that no new work will be enqueued to the workqueue
+beforehand.
+Note that if the workqueue is
+.Dv WQ_PERCPU ,
+the caller can enqueue a new work to another queue other than the waiting queue.
+.Pp
+.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 .Fn workqueue_destroy
 destroys a workqueue and frees associated resources.
 The caller should ensure that the workqueue has no work enqueued beforehand.
diff -r e10ff110d400 -r 3fc112eae452 sys/kern/subr_workqueue.c
--- a/sys/kern/subr_workqueue.c Tue Jan 16 12:03:44 2018 +0000
+++ b/sys/kern/subr_workqueue.c Tue Jan 16 13:01:10 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_workqueue.c,v 1.33 2012/10/07 22:16:21 matt Exp $ */
+/*     $NetBSD: subr_workqueue.c,v 1.33.30.1 2018/01/16 13:01:10 martin Exp $  */
 
 /*-
  * Copyright (c)2002, 2005, 2006, 2007 YAMAMOTO Takashi,
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_workqueue.c,v 1.33 2012/10/07 22:16:21 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_workqueue.c,v 1.33.30.1 2018/01/16 13:01:10 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
@@ -49,8 +49,10 @@
 struct workqueue_queue {
        kmutex_t q_mutex;
        kcondvar_t q_cv;
-       struct workqhead q_queue;
+       struct workqhead q_queue_pending;
+       struct workqhead q_queue_running;
        lwp_t *q_worker;
+       work_impl_t *q_waiter;
 };
 
 struct workqueue {
@@ -115,24 +117,29 @@
        q = workqueue_queue_lookup(wq, curlwp->l_cpu);
 
        for (;;) {
-               struct workqhead tmp;
-
                /*
                 * we violate abstraction of SIMPLEQ.
                 */
 
-#if defined(DIAGNOSTIC)
-               tmp.sqh_last = (void *)POISON;
-#endif /* defined(DIAGNOSTIC) */
+               mutex_enter(&q->q_mutex);
+               while (SIMPLEQ_EMPTY(&q->q_queue_pending))
+                       cv_wait(&q->q_cv, &q->q_mutex);
+               KASSERT(SIMPLEQ_EMPTY(&q->q_queue_running));
+               q->q_queue_running.sqh_first =
+                   q->q_queue_pending.sqh_first; /* XXX */
+               SIMPLEQ_INIT(&q->q_queue_pending);
+               mutex_exit(&q->q_mutex);
+
+               workqueue_runlist(wq, &q->q_queue_running);
 
                mutex_enter(&q->q_mutex);
-               while (SIMPLEQ_EMPTY(&q->q_queue))
-                       cv_wait(&q->q_cv, &q->q_mutex);
-               tmp.sqh_first = q->q_queue.sqh_first; /* XXX */
-               SIMPLEQ_INIT(&q->q_queue);
+               KASSERT(!SIMPLEQ_EMPTY(&q->q_queue_running));
+               SIMPLEQ_INIT(&q->q_queue_running);
+               if (__predict_false(q->q_waiter != NULL)) {
+                       /* Wake up workqueue_wait */
+                       cv_signal(&q->q_cv);
+               }
                mutex_exit(&q->q_mutex);
-
-               workqueue_runlist(wq, &tmp);
        }
 }
 
@@ -159,7 +166,8 @@
 
        mutex_init(&q->q_mutex, MUTEX_DEFAULT, ipl);
        cv_init(&q->q_cv, wq->wq_name);
-       SIMPLEQ_INIT(&q->q_queue);
+       SIMPLEQ_INIT(&q->q_queue_pending);
+       SIMPLEQ_INIT(&q->q_queue_running);
        ktf = ((wq->wq_flags & WQ_MPSAFE) != 0 ? KTHREAD_MPSAFE : 0);
        if (wq->wq_prio < PRI_KERNEL)
                ktf |= KTHREAD_TS;
@@ -194,7 +202,7 @@
         */
 
        KASSERT(q->q_worker == curlwp);
-       KASSERT(SIMPLEQ_EMPTY(&q->q_queue));
+       KASSERT(SIMPLEQ_EMPTY(&q->q_queue_pending));
        mutex_enter(&q->q_mutex);
        q->q_worker = NULL;
        cv_signal(&q->q_cv);
@@ -210,10 +218,10 @@
        KASSERT(wq->wq_func == workqueue_exit);
 
        wqe.wqe_q = q;
-       KASSERT(SIMPLEQ_EMPTY(&q->q_queue));
+       KASSERT(SIMPLEQ_EMPTY(&q->q_queue_pending));
        KASSERT(q->q_worker != NULL);
        mutex_enter(&q->q_mutex);
-       SIMPLEQ_INSERT_TAIL(&q->q_queue, &wqe.wqe_wk, wk_entry);
+       SIMPLEQ_INSERT_TAIL(&q->q_queue_pending, &wqe.wqe_wk, wk_entry);
        cv_signal(&q->q_cv);
        while (q->q_worker != NULL) {
                cv_wait(&q->q_cv, &q->q_mutex);
@@ -271,6 +279,64 @@
        return error;
 }
 
+static bool
+workqueue_q_wait(struct workqueue_queue *q, work_impl_t *wk_target)
+{
+       work_impl_t *wk;
+       bool found = false;
+
+       mutex_enter(&q->q_mutex);
+    again:
+       SIMPLEQ_FOREACH(wk, &q->q_queue_pending, wk_entry) {
+               if (wk == wk_target)
+                       goto found;
+       }
+       SIMPLEQ_FOREACH(wk, &q->q_queue_running, wk_entry) {
+               if (wk == wk_target)
+                       goto found;
+       }
+    found:
+       if (wk != NULL) {
+               found = true;
+               KASSERT(q->q_waiter == NULL);
+               q->q_waiter = wk;
+               cv_wait(&q->q_cv, &q->q_mutex);
+               goto again;
+       }
+       if (q->q_waiter != NULL)
+               q->q_waiter = NULL;
+       mutex_exit(&q->q_mutex);
+
+       return found;
+}
+
+/*
+ * Wait for a specified work to finish.  The caller must ensure that no new
+ * work will be enqueued before calling workqueue_wait.  Note that if the
+ * workqueue is WQ_PERCPU, the caller can enqueue a new work to another queue
+ * other than the waiting queue.
+ */
+void
+workqueue_wait(struct workqueue *wq, struct work *wk)
+{
+       struct workqueue_queue *q;
+       bool found;
+
+       if (ISSET(wq->wq_flags, WQ_PERCPU)) {
+               struct cpu_info *ci;
+               CPU_INFO_ITERATOR cii;
+               for (CPU_INFO_FOREACH(cii, ci)) {
+                       q = workqueue_queue_lookup(wq, ci);
+                       found = workqueue_q_wait(q, (work_impl_t *)wk);
+                       if (found)
+                               break;
+               }
+       } else {
+               q = workqueue_queue_lookup(wq, NULL);
+               (void) workqueue_q_wait(q, (work_impl_t *)wk);
+       }
+}
+
 void
 workqueue_destroy(struct workqueue *wq)
 {
@@ -298,7 +364,8 @@
        q = workqueue_queue_lookup(wq, ci);
 
        mutex_enter(&q->q_mutex);
-       SIMPLEQ_INSERT_TAIL(&q->q_queue, wk, wk_entry);
+       KASSERT(q->q_waiter == NULL);
+       SIMPLEQ_INSERT_TAIL(&q->q_queue_pending, wk, wk_entry);
        cv_signal(&q->q_cv);
        mutex_exit(&q->q_mutex);
 }
diff -r e10ff110d400 -r 3fc112eae452 sys/net/if_bridge.c
--- a/sys/net/if_bridge.c       Tue Jan 16 12:03:44 2018 +0000
+++ b/sys/net/if_bridge.c       Tue Jan 16 13:01:10 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_bridge.c,v 1.134.6.5 2018/01/02 10:20:33 snj Exp $  */
+/*     $NetBSD: if_bridge.c,v 1.134.6.6 2018/01/16 13:01:10 martin Exp $       */
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -80,7 +80,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.134.6.5 2018/01/02 10:20:33 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.134.6.6 2018/01/16 13:01:10 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_bridge_ipf.h"
@@ -1363,7 +1363,8 @@
        KASSERT((ifp->if_flags & IFF_RUNNING) != 0);
        ifp->if_flags &= ~IFF_RUNNING;
 
-       callout_stop(&sc->sc_brcallout);
+       callout_halt(&sc->sc_brcallout, NULL);
+       workqueue_wait(sc->sc_rtage_wq, &sc->sc_rtage_wk);
        bstp_stop(sc);
        bridge_rtflush(sc, IFBF_FLUSHDYN);
 }
diff -r e10ff110d400 -r 3fc112eae452 sys/net/if_spppsubr.c
--- a/sys/net/if_spppsubr.c     Tue Jan 16 12:03:44 2018 +0000
+++ b/sys/net/if_spppsubr.c     Tue Jan 16 13:01:10 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_spppsubr.c,v 1.169.6.3 2018/01/02 10:20:33 snj Exp $         */
+/*     $NetBSD: if_spppsubr.c,v 1.169.6.4 2018/01/16 13:01:10 martin Exp $      */
 
 /*
  * Synchronous PPP/Cisco link level subroutines.
@@ -41,7 +41,7 @@
  */



Home | Main Index | Thread Index | Old Index