Source-Changes-HG archive

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

[src/trunk]: src/sys - sleepq_block(): Add a new LWP flag, LW_CATCHINTR, that...



details:   https://anonhg.NetBSD.org/src/rev/02bd544beb0d
branches:  trunk
changeset: 941494:02bd544beb0d
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Fri Oct 23 00:25:45 2020 +0000

description:
- sleepq_block(): Add a new LWP flag, LW_CATCHINTR, that is used to track
  the intent to catch signals while sleeping.  Initialize this flag based
  on the catch_p argument to sleepq_block(), and rather than test catch_p
  when awakened, test LW_CATCHINTR.  This allows the intent to change
  (based on whatever criteria the owner of the sleepq wishes) while the
  LWP is asleep.  This is separate from LW_SINTR in order to leave all
  other logic around LW_SINTR unaffected.
- In sleepq_transfer(), adjust also LW_CATCHINTR based on the catch_p
  argument.  Also allow the new LWP lock argument to be NULL, which
  will cause the lwp_setlock() call to be skipped; this allows transfer
  to another sleepq that is known to be protected by the same lock.
- Add a new function, sleepq_uncatch(), that will transition an LWP
  from "interruptible sleep" to "uninterruptible sleep" on its current
  sleepq.

diffstat:

 sys/kern/kern_sleepq.c |  48 +++++++++++++++++++++++++++++++++++++++++-------
 sys/sys/lwp.h          |   3 ++-
 sys/sys/sleepq.h       |   3 ++-
 3 files changed, 45 insertions(+), 9 deletions(-)

diffs (131 lines):

diff -r 5c6cebeb11de -r 02bd544beb0d sys/kern/kern_sleepq.c
--- a/sys/kern/kern_sleepq.c    Thu Oct 22 21:53:01 2020 +0000
+++ b/sys/kern/kern_sleepq.c    Fri Oct 23 00:25:45 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_sleepq.c,v 1.68 2020/05/21 00:39:04 thorpej Exp $ */
+/*     $NetBSD: kern_sleepq.c,v 1.69 2020/10/23 00:25:45 thorpej Exp $ */
 
 /*-
  * Copyright (c) 2006, 2007, 2008, 2009, 2019, 2020 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_sleepq.c,v 1.68 2020/05/21 00:39:04 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sleepq.c,v 1.69 2020/10/23 00:25:45 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -267,16 +267,32 @@
        l->l_wmesg = wmesg;
 
        if (catch_p)
-               l->l_flag |= LW_SINTR;
+               l->l_flag = LW_SINTR | LW_CATCHINTR;
        else
-               l->l_flag &= ~LW_SINTR;
+               l->l_flag = ~(LW_SINTR | LW_CATCHINTR);
 
-       lwp_setlock(l, mp);
+       /*
+        * This allows the transfer from one sleepq to another where
+        * it is known that they're both protected by the same lock.
+        */
+       if (mp != NULL)
+               lwp_setlock(l, mp);
 
        sleepq_insert(sq, l, sobj);
 }
 
 /*
+ * sleepq_uncatch:
+ *
+ *     Mark the LWP as no longer sleeping interruptibly.
+ */
+void
+sleepq_uncatch(lwp_t *l)
+{
+       l->l_flag = ~(LW_SINTR | LW_CATCHINTR);
+}
+
+/*
  * sleepq_block:
  *
  *     After any intermediate step such as releasing an interlock, switch.
@@ -299,6 +315,11 @@
        /*
         * If sleeping interruptably, check for pending signals, exits or
         * core dump events.
+        *
+        * Note the usage of LW_CATCHINTR.  This expresses our intent
+        * to catch or not catch sleep interruptions, which might change
+        * while we are sleeping.  It is independent from LW_SINTR because
+        * we don't want to leave LW_SINTR set when the LWP is not asleep.
         */
        if (catch_p) {
                if ((l->l_flag & (LW_CANCELLED|LW_WEXIT|LW_WCORE)) != 0) {
@@ -307,7 +328,9 @@
                        early = true;
                } else if ((l->l_flag & LW_PENDSIG) != 0 && sigispending(l, 0))
                        early = true;
-       }
+               l->l_flag |= LW_CATCHINTR;
+       } else
+               l->l_flag &= ~LW_CATCHINTR;
 
        if (early) {
                /* lwp_unsleep() will release the lock */
@@ -342,7 +365,18 @@
                }
        }
 
-       if (catch_p && error == 0) {
+       /*
+        * LW_CATCHINTR is only modified in this function OR when we
+        * are asleep (with the sleepq locked).  We can therefore safely
+        * test it unlocked here as it is guaranteed to be stable by
+        * virtue of us running.
+        *
+        * We do not bother clearing it if set; that would require us
+        * to take the LWP lock, and it doesn't seem worth the hassle
+        * considering it is only meaningful here inside this function,
+        * and is set to reflect intent upon entry.
+        */
+       if ((l->l_flag & LW_CATCHINTR) != 0 && error == 0) {
                p = l->l_proc;
                if ((l->l_flag & (LW_CANCELLED | LW_WEXIT | LW_WCORE)) != 0)
                        error = EINTR;
diff -r 5c6cebeb11de -r 02bd544beb0d sys/sys/lwp.h
--- a/sys/sys/lwp.h     Thu Oct 22 21:53:01 2020 +0000
+++ b/sys/sys/lwp.h     Fri Oct 23 00:25:45 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lwp.h,v 1.211 2020/08/01 02:04:55 riastradh Exp $      */
+/*     $NetBSD: lwp.h,v 1.212 2020/10/23 00:25:45 thorpej Exp $        */
 
 /*
  * Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010, 2019, 2020
@@ -255,6 +255,7 @@
 #define        LW_LWPCTL       0x00000002 /* Adjust lwpctl in userret */
 #define        LW_STIMO        0x00000040 /* Sleep timed out */
 #define        LW_SINTR        0x00000080 /* Sleep is interruptible. */
+#define        LW_CATCHINTR    0x00000100 /* LW_SINTR intent; see sleepq_block(). */
 #define        LW_SYSTEM       0x00000200 /* Kernel thread */
 #define        LW_SYSTEM_FPU   0x00000400 /* Kernel thread with vector/FP enabled */
 #define        LW_DBGSUSPEND   0x00010000 /* Suspend by debugger */
diff -r 5c6cebeb11de -r 02bd544beb0d sys/sys/sleepq.h
--- a/sys/sys/sleepq.h  Thu Oct 22 21:53:01 2020 +0000
+++ b/sys/sys/sleepq.h  Fri Oct 23 00:25:45 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sleepq.h,v 1.31 2020/05/23 20:45:11 ad Exp $   */
+/*     $NetBSD: sleepq.h,v 1.32 2020/10/23 00:25:45 thorpej Exp $      */
 
 /*-
  * Copyright (c) 2002, 2006, 2007, 2008, 2009, 2019, 2020
@@ -64,6 +64,7 @@
            bool);
 void   sleepq_transfer(lwp_t *, sleepq_t *, sleepq_t *, wchan_t, const char *,
            struct syncobj *, kmutex_t *, bool);
+void   sleepq_uncatch(lwp_t *);
 void   sleepq_unsleep(lwp_t *, bool);
 void   sleepq_timeout(void *);
 void   sleepq_wake(sleepq_t *, wchan_t, u_int, kmutex_t *);



Home | Main Index | Thread Index | Old Index