diff --git a/sys/kern/kern_lwp.c b/sys/kern/kern_lwp.c index a29927cc5bee..a7aedbd0c960 100644 --- a/sys/kern/kern_lwp.c +++ b/sys/kern/kern_lwp.c @@ -1,7 +1,7 @@ -/* $NetBSD: kern_lwp.c,v 1.208 2019/11/14 16:23:52 maxv Exp $ */ +/* $NetBSD: kern_lwp.c,v 1.209 2019/11/21 18:17:36 ad Exp $ */ /*- - * Copyright (c) 2001, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc. + * Copyright (c) 2001, 2006, 2007, 2008, 2009, 2019 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -211,7 +211,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.208 2019/11/14 16:23:52 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.209 2019/11/21 18:17:36 ad Exp $"); #include "opt_ddb.h" #include "opt_lockdebug.h" @@ -1147,7 +1147,7 @@ lwp_exit(struct lwp *l) firstsig(&p->p_sigpend.sp_set) != 0) { LIST_FOREACH(l2, &p->p_lwps, l_sibling) { lwp_lock(l2); - l2->l_flag |= LW_PENDSIG; + signotify(l2); lwp_unlock(l2); } } @@ -1616,15 +1616,26 @@ lwp_userret(struct lwp *l) void lwp_need_userret(struct lwp *l) { + + KASSERT(!cpu_intr_p()); KASSERT(lwp_locked(l, NULL)); /* - * Since the tests in lwp_userret() are done unlocked, make sure - * that the condition will be seen before forcing the LWP to enter - * kernel mode. + * If the LWP is in any state other than LSONPROC, we know that it + * is executing in-kernel and will hit userret() on the way out. + * + * If the LWP is curlwp, then we know we'll be back out to userspace + * soon (can't be called from a hardware interrupt here). + * + * Otherwise, we can't be sure what the LWP is doing, so first make + * sure the update to l_flag will be globally visible, and then + * force the LWP to take a trip through trap() where it will do + * userret(). */ - membar_producer(); - cpu_signotify(l); + if (l->l_stat == LSONPROC && l != curlwp) { + membar_producer(); + cpu_signotify(l); + } } /* diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 1a9226de4854..f8d4f660fd43 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,7 +1,7 @@ -/* $NetBSD: kern_sig.c,v 1.379 2019/11/20 19:37:53 pgoyette Exp $ */ +/* $NetBSD: kern_sig.c,v 1.380 2019/11/21 18:17:36 ad Exp $ */ /*- - * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. + * Copyright (c) 2006, 2007, 2008, 2019 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -70,7 +70,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.379 2019/11/20 19:37:53 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.380 2019/11/21 18:17:36 ad Exp $"); #include "opt_ptrace.h" #include "opt_dtrace.h" @@ -710,6 +710,9 @@ sigclearall(struct proc *p, const sigset_t *mask, ksiginfoq_t *kq) * current LWP. May be called unlocked provided that LW_PENDSIG is set, * and that the signal has been posted to the appopriate queue before * LW_PENDSIG is set. + * + * This should only ever be called with (l == curlwp), unless the + * result does not matter (procfs, sysctl). */ int sigispending(struct lwp *l, int signo) @@ -1133,7 +1136,7 @@ sigpost(struct lwp *l, sig_t action, int prop, int sig) * Have the LWP check for signals. This ensures that even if no LWP * is found to take the signal immediately, it should be taken soon. */ - l->l_flag |= LW_PENDSIG; + signotify(l); /* * SIGCONT can be masked, but if LWP is stopped, it needs restart. @@ -1167,7 +1170,6 @@ sigpost(struct lwp *l, sig_t action, int prop, int sig) switch (l->l_stat) { case LSRUN: case LSONPROC: - lwp_need_userret(l); rv = 1; break;