Module Name: src
Committed By: thorpej
Date: Fri Oct 23 00:25:45 UTC 2020
Modified Files:
src/sys/kern: kern_sleepq.c
src/sys/sys: lwp.h sleepq.h
Log Message:
- 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.
To generate a diff of this commit:
cvs rdiff -u -r1.68 -r1.69 src/sys/kern/kern_sleepq.c
cvs rdiff -u -r1.211 -r1.212 src/sys/sys/lwp.h
cvs rdiff -u -r1.31 -r1.32 src/sys/sys/sleepq.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/kern_sleepq.c
diff -u src/sys/kern/kern_sleepq.c:1.68 src/sys/kern/kern_sleepq.c:1.69
--- src/sys/kern/kern_sleepq.c:1.68 Thu May 21 00:39:04 2020
+++ src/sys/kern/kern_sleepq.c Fri Oct 23 00:25:45 2020
@@ -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 @@ sleepq_transfer(lwp_t *l, sleepq_t *from
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 @@ sleepq_block(int timo, bool catch_p)
/*
* 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 @@ sleepq_block(int timo, bool catch_p)
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 @@ sleepq_block(int timo, bool catch_p)
}
}
- 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;
Index: src/sys/sys/lwp.h
diff -u src/sys/sys/lwp.h:1.211 src/sys/sys/lwp.h:1.212
--- src/sys/sys/lwp.h:1.211 Sat Aug 1 02:04:55 2020
+++ src/sys/sys/lwp.h Fri Oct 23 00:25:45 2020
@@ -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 @@ extern int maxlwp __read_mostly; /* max
#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 */
Index: src/sys/sys/sleepq.h
diff -u src/sys/sys/sleepq.h:1.31 src/sys/sys/sleepq.h:1.32
--- src/sys/sys/sleepq.h:1.31 Sat May 23 20:45:11 2020
+++ src/sys/sys/sleepq.h Fri Oct 23 00:25:45 2020
@@ -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 @@ void sleepq_enqueue(sleepq_t *, wchan_t,
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 *);