Source-Changes-HG archive

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

[src/trunk]: src/sys/external/bsd/common/linux Factor out waiting for current...



details:   https://anonhg.NetBSD.org/src/rev/c63f1615baa6
branches:  trunk
changeset: 835444:c63f1615baa6
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Mon Aug 27 15:04:32 2018 +0000

description:
Factor out waiting for current work.

diffstat:

 sys/external/bsd/common/linux/linux_work.c |  44 +++++++++++++++++++----------
 1 files changed, 29 insertions(+), 15 deletions(-)

diffs (93 lines):

diff -r f9b91832b5c4 -r c63f1615baa6 sys/external/bsd/common/linux/linux_work.c
--- a/sys/external/bsd/common/linux/linux_work.c        Mon Aug 27 15:04:19 2018 +0000
+++ b/sys/external/bsd/common/linux/linux_work.c        Mon Aug 27 15:04:32 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_work.c,v 1.32 2018/08/27 15:04:19 riastradh Exp $        */
+/*     $NetBSD: linux_work.c,v 1.33 2018/08/27 15:04:32 riastradh Exp $        */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_work.c,v 1.32 2018/08/27 15:04:19 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_work.c,v 1.33 2018/08/27 15:04:32 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/atomic.h>
@@ -65,6 +65,8 @@
                            struct workqueue_struct *);
 static void            release_work(struct work_struct *,
                            struct workqueue_struct *);
+static void            wait_for_current_work(struct work_struct *,
+                           struct workqueue_struct *);
 static void            dw_callout_init(struct workqueue_struct *,
                            struct delayed_work *);
 static void            dw_callout_destroy(struct workqueue_struct *,
@@ -496,13 +498,9 @@
        } else if (wq->wq_current_work == work) {
                /*
                 * It has already begun execution, so it's too late to
-                * cancel now.  Wait for it to complete.  Don't wait
-                * more than one generation in case it gets requeued.
+                * cancel now.  Wait for it to complete.
                 */
-               uint64_t gen = wq->wq_gen;
-               do {
-                       cv_wait(&wq->wq_cv, &wq->wq_lock);
-               } while (wq->wq_current_work == work && wq->wq_gen == gen);
+               wait_for_current_work(work, wq);
                cancelled_p = false;
        } else {
                /*
@@ -516,6 +514,27 @@
 
 out:   return cancelled_p;
 }
+
+/*
+ * wait_for_current_work(work, wq)
+ *
+ *     wq must be currently executing work.  Wait for it to finish.
+ */
+static void
+wait_for_current_work(struct work_struct *work, struct workqueue_struct *wq)
+{
+       uint64_t gen;
+
+       KASSERT(mutex_owned(&wq->wq_lock));
+       KASSERT(work->work_queue == wq);
+       KASSERT(wq->wq_current_work == work);
+
+       /* Wait only one generation in case it gets requeued quickly.  */
+       gen = wq->wq_gen;
+       do {
+               cv_wait(&wq->wq_cv, &wq->wq_lock);
+       } while (wq->wq_current_work == work && wq->wq_gen == gen);
+}
 
 /*
  * Delayed work
@@ -993,19 +1012,14 @@
                                /*
                                 * Too late, it's already running.
                                 * First, make sure it's not requeued.
-                                * Then wait for it to complete, at
-                                * most one generation.
+                                * Then wait for it to complete.
                                 */
-                               uint64_t gen = wq->wq_gen;
                                if (wq->wq_requeued) {
                                        TAILQ_REMOVE(&wq->wq_queue, &dw->work,
                                            work_entry);
                                        wq->wq_requeued = false;
                                }
-                               do {
-                                       cv_wait(&wq->wq_cv, &wq->wq_lock);
-                               } while (wq->wq_current_work == &dw->work &&
-                                   wq->wq_gen == gen);
+                               wait_for_current_work(&dw->work, wq);
                                cancelled_p = false;
                        } else {
                                /* Got in before it started.  Remove it.  */



Home | Main Index | Thread Index | Old Index