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