Avoid sneaking past signal delivery in sa_upcall_userret():
generate unblocked upcalls in sa_unblock_userret(), before signal delivery/p_userret handling in userret(). Also defer getting state for preempted upcalls because on some ports preemption can happen between sa_unblock_userret() and sa_upcall_userret().
This commit is contained in:
parent
63bc27bf55
commit
b936d40f39
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: trap.c,v 1.58 2003/10/31 03:28:13 simonb Exp $ */
|
/* $NetBSD: trap.c,v 1.59 2003/11/01 01:38:46 cl Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1990 The Regents of the University of California.
|
* Copyright (c) 1990 The Regents of the University of California.
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.58 2003/10/31 03:28:13 simonb Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.59 2003/11/01 01:38:46 cl Exp $");
|
||||||
|
|
||||||
#include "opt_ddb.h"
|
#include "opt_ddb.h"
|
||||||
#include "opt_kgdb.h"
|
#include "opt_kgdb.h"
|
||||||
|
@ -147,6 +147,10 @@ userret(l, pc, oticks)
|
||||||
struct proc *p = l->l_proc;
|
struct proc *p = l->l_proc;
|
||||||
int sig;
|
int sig;
|
||||||
|
|
||||||
|
/* Generate UNBLOCKED upcall. */
|
||||||
|
if (l->l_flag & L_SA_BLOCKING)
|
||||||
|
sa_unblock_userret(l);
|
||||||
|
|
||||||
/* take pending signals */
|
/* take pending signals */
|
||||||
while ((sig = CURSIG(l)) != 0)
|
while ((sig = CURSIG(l)) != 0)
|
||||||
postsig(sig);
|
postsig(sig);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: trap.c,v 1.148 2003/10/31 03:28:13 simonb Exp $ */
|
/* $NetBSD: trap.c,v 1.149 2003/11/01 01:38:46 cl Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1996
|
* Copyright (c) 1996
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.148 2003/10/31 03:28:13 simonb Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.149 2003/11/01 01:38:46 cl Exp $");
|
||||||
|
|
||||||
#include "opt_ddb.h"
|
#include "opt_ddb.h"
|
||||||
#include "opt_ktrace.h"
|
#include "opt_ktrace.h"
|
||||||
|
@ -233,6 +233,10 @@ userret(l, pc, oticks)
|
||||||
struct proc *p = l->l_proc;
|
struct proc *p = l->l_proc;
|
||||||
int sig;
|
int sig;
|
||||||
|
|
||||||
|
/* Generate UNBLOCKED upcall. */
|
||||||
|
if (l->l_flag & L_SA_BLOCKING)
|
||||||
|
sa_unblock_userret(l);
|
||||||
|
|
||||||
/* take pending signals */
|
/* take pending signals */
|
||||||
while ((sig = CURSIG(l)) != 0)
|
while ((sig = CURSIG(l)) != 0)
|
||||||
postsig(sig);
|
postsig(sig);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: trap.c,v 1.97 2003/10/27 00:15:24 christos Exp $ */
|
/* $NetBSD: trap.c,v 1.98 2003/11/01 01:38:46 cl Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1996-2002 Eduardo Horvath. All rights reserved.
|
* Copyright (c) 1996-2002 Eduardo Horvath. All rights reserved.
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.97 2003/10/27 00:15:24 christos Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.98 2003/11/01 01:38:46 cl Exp $");
|
||||||
|
|
||||||
#define NEW_FPSTATE
|
#define NEW_FPSTATE
|
||||||
|
|
||||||
|
@ -443,6 +443,10 @@ userret(l, pc, oticks)
|
||||||
struct proc *p = l->l_proc;
|
struct proc *p = l->l_proc;
|
||||||
int sig;
|
int sig;
|
||||||
|
|
||||||
|
/* Generate UNBLOCKED upcall. */
|
||||||
|
if (l->l_flag & L_SA_BLOCKING)
|
||||||
|
sa_unblock_userret(l);
|
||||||
|
|
||||||
/* take pending signals */
|
/* take pending signals */
|
||||||
while ((sig = CURSIG(l)) != 0)
|
while ((sig = CURSIG(l)) != 0)
|
||||||
postsig(sig);
|
postsig(sig);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: trap.c,v 1.88 2003/10/31 03:28:14 simonb Exp $ */
|
/* $NetBSD: trap.c,v 1.89 2003/11/01 01:38:47 cl Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1994 Ludd, University of Lule}, Sweden.
|
* Copyright (c) 1994 Ludd, University of Lule}, Sweden.
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
/* All bugs are subject to removal without further notice */
|
/* All bugs are subject to removal without further notice */
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.88 2003/10/31 03:28:14 simonb Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.89 2003/11/01 01:38:47 cl Exp $");
|
||||||
|
|
||||||
#include "opt_ddb.h"
|
#include "opt_ddb.h"
|
||||||
#include "opt_ktrace.h"
|
#include "opt_ktrace.h"
|
||||||
|
@ -127,6 +127,10 @@ userret(struct lwp *l, struct trapframe *frame, u_quad_t oticks)
|
||||||
int sig;
|
int sig;
|
||||||
struct proc *p = l->l_proc;
|
struct proc *p = l->l_proc;
|
||||||
|
|
||||||
|
/* Generate UNBLOCKED upcall. */
|
||||||
|
if (l->l_flag & L_SA_BLOCKING)
|
||||||
|
sa_unblock_userret(l);
|
||||||
|
|
||||||
/* Take pending signals. */
|
/* Take pending signals. */
|
||||||
while ((sig = CURSIG(l)) != 0)
|
while ((sig = CURSIG(l)) != 0)
|
||||||
postsig(sig);
|
postsig(sig);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: kern_sa.c,v 1.33 2003/10/31 23:36:50 cl Exp $ */
|
/* $NetBSD: kern_sa.c,v 1.34 2003/11/01 01:38:47 cl Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.33 2003/10/31 23:36:50 cl Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.34 2003/11/01 01:38:47 cl Exp $");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
|
@ -440,8 +440,14 @@ sa_preempt(struct lwp *l)
|
||||||
struct proc *p = l->l_proc;
|
struct proc *p = l->l_proc;
|
||||||
struct sadata *sa = p->p_sa;
|
struct sadata *sa = p->p_sa;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defer saving the lwp's state because on some ports
|
||||||
|
* preemption can occur between generating an unblocked upcall
|
||||||
|
* and processing the upcall queue.
|
||||||
|
*/
|
||||||
if (sa->sa_flag & SA_FLAG_PREEMPT)
|
if (sa->sa_flag & SA_FLAG_PREEMPT)
|
||||||
sa_upcall(l, SA_UPCALL_PREEMPTED, l, NULL, 0, NULL);
|
sa_upcall(l, SA_UPCALL_PREEMPTED | SA_UPCALL_DEFER_EVENT,
|
||||||
|
l, NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1068,18 +1074,14 @@ sa_getcachelwp(struct proc *p)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sa_upcall_userret(struct lwp *l)
|
sa_unblock_userret(struct lwp *l)
|
||||||
{
|
{
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
|
struct lwp *l2;
|
||||||
struct sadata *sa;
|
struct sadata *sa;
|
||||||
struct sa_t **sapp, *sap;
|
|
||||||
struct sadata_upcall *sau;
|
struct sadata_upcall *sau;
|
||||||
struct sa_t self_sa;
|
|
||||||
struct sa_t *sas[3];
|
|
||||||
stack_t st;
|
stack_t st;
|
||||||
void *stack, *ap;
|
int f, s;
|
||||||
ucontext_t u, *up;
|
|
||||||
int f, i, nsas, nint, nevents, sig, s, type;
|
|
||||||
|
|
||||||
p = l->l_proc;
|
p = l->l_proc;
|
||||||
sa = p->p_sa;
|
sa = p->p_sa;
|
||||||
|
@ -1089,7 +1091,7 @@ sa_upcall_userret(struct lwp *l)
|
||||||
KERNEL_PROC_LOCK(l);
|
KERNEL_PROC_LOCK(l);
|
||||||
SA_LWP_STATE_LOCK(l, f);
|
SA_LWP_STATE_LOCK(l, f);
|
||||||
|
|
||||||
DPRINTFN(7,("sa_upcall_userret(%d.%d %x) \n", p->p_pid, l->l_lid,
|
DPRINTFN(7,("sa_unblock_userret(%d.%d %x) \n", p->p_pid, l->l_lid,
|
||||||
l->l_flag));
|
l->l_flag));
|
||||||
|
|
||||||
while (l->l_upcallstack != NULL) {
|
while (l->l_upcallstack != NULL) {
|
||||||
|
@ -1122,11 +1124,9 @@ sa_upcall_userret(struct lwp *l)
|
||||||
|
|
||||||
if (l->l_flag & L_SA_BLOCKING) {
|
if (l->l_flag & L_SA_BLOCKING) {
|
||||||
/* Invoke an "unblocked" upcall */
|
/* Invoke an "unblocked" upcall */
|
||||||
struct lwp *l2;
|
DPRINTFN(8,("sa_unblock_userret(%d.%d) unblocking\n",
|
||||||
DPRINTFN(8,("sa_upcall_userret(%d.%d) unblocking\n",
|
|
||||||
p->p_pid, l->l_lid));
|
p->p_pid, l->l_lid));
|
||||||
|
|
||||||
|
|
||||||
sau = sadata_upcall_alloc(1);
|
sau = sadata_upcall_alloc(1);
|
||||||
sau->sau_arg = NULL;
|
sau->sau_arg = NULL;
|
||||||
|
|
||||||
|
@ -1135,14 +1135,14 @@ sa_upcall_userret(struct lwp *l)
|
||||||
lwp_exit(l);
|
lwp_exit(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SCHED_ASSERT_UNLOCKED();
|
SCHED_ASSERT_UNLOCKED();
|
||||||
|
|
||||||
l2 = sa_vp_repossess(l);
|
l2 = sa_vp_repossess(l);
|
||||||
|
|
||||||
KDASSERT(sa->sa_nstacks > 0);
|
KDASSERT(sa->sa_nstacks > 0);
|
||||||
st = sa->sa_stacks[--sa->sa_nstacks];
|
st = sa->sa_stacks[--sa->sa_nstacks];
|
||||||
|
DPRINTFN(9,("sa_unblock_userret(%d.%d) nstacks-- = %2d\n",
|
||||||
|
l->l_proc->p_pid, l->l_lid, sa->sa_nstacks));
|
||||||
|
|
||||||
SCHED_ASSERT_UNLOCKED();
|
SCHED_ASSERT_UNLOCKED();
|
||||||
|
|
||||||
|
@ -1152,8 +1152,10 @@ sa_upcall_userret(struct lwp *l)
|
||||||
lwp_exit(l);
|
lwp_exit(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTFN(9,("sa_upcall_userret(%d.%d) nstacks-- = %2d\n",
|
/*
|
||||||
l->l_proc->p_pid, l->l_lid, sa->sa_nstacks));
|
* Defer saving the event lwp's state because a
|
||||||
|
* PREEMPT upcall could be on the queue already.
|
||||||
|
*/
|
||||||
if (sa_upcall0(l, SA_UPCALL_UNBLOCKED | SA_UPCALL_DEFER_EVENT,
|
if (sa_upcall0(l, SA_UPCALL_UNBLOCKED | SA_UPCALL_DEFER_EVENT,
|
||||||
l, l2, 0, NULL, sau, &st) != 0) {
|
l, l2, 0, NULL, sau, &st) != 0) {
|
||||||
/*
|
/*
|
||||||
|
@ -1161,7 +1163,7 @@ sa_upcall_userret(struct lwp *l)
|
||||||
* upcall, but don't have resources to do so.
|
* upcall, but don't have resources to do so.
|
||||||
*/
|
*/
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
printf("sa_upcall_userret: out of upcall resources"
|
printf("sa_unblock_userret: out of upcall resources"
|
||||||
" for %d.%d\n", p->p_pid, l->l_lid);
|
" for %d.%d\n", p->p_pid, l->l_lid);
|
||||||
#endif
|
#endif
|
||||||
sigexit(l, SIGABRT);
|
sigexit(l, SIGABRT);
|
||||||
|
@ -1173,22 +1175,35 @@ sa_upcall_userret(struct lwp *l)
|
||||||
SCHED_LOCK(s);
|
SCHED_LOCK(s);
|
||||||
sa_putcachelwp(p, l2); /* PHOLD from sa_vp_repossess */
|
sa_putcachelwp(p, l2); /* PHOLD from sa_vp_repossess */
|
||||||
SCHED_UNLOCK(s);
|
SCHED_UNLOCK(s);
|
||||||
|
}
|
||||||
/* We migth have sneaked past signal handling and userret */
|
|
||||||
SA_LWP_STATE_UNLOCK(l, f);
|
SA_LWP_STATE_UNLOCK(l, f);
|
||||||
KERNEL_PROC_UNLOCK(l);
|
KERNEL_PROC_UNLOCK(l);
|
||||||
|
}
|
||||||
|
|
||||||
/* take pending signals */
|
|
||||||
while ((sig = CURSIG(l)) != 0)
|
|
||||||
postsig(sig);
|
|
||||||
|
|
||||||
/* Invoke per-process kernel-exit handling, if any */
|
void
|
||||||
if (p->p_userret)
|
sa_upcall_userret(struct lwp *l)
|
||||||
(p->p_userret)(l, p->p_userret_arg);
|
{
|
||||||
|
struct proc *p;
|
||||||
|
struct sadata *sa;
|
||||||
|
struct sa_t **sapp, *sap;
|
||||||
|
struct sadata_upcall *sau;
|
||||||
|
struct sa_t self_sa;
|
||||||
|
struct sa_t *sas[3];
|
||||||
|
void *stack, *ap;
|
||||||
|
ucontext_t u, *up;
|
||||||
|
int f, i, nsas, nint, nevents, type;
|
||||||
|
|
||||||
|
p = l->l_proc;
|
||||||
|
sa = p->p_sa;
|
||||||
|
|
||||||
|
SCHED_ASSERT_UNLOCKED();
|
||||||
|
|
||||||
KERNEL_PROC_LOCK(l);
|
KERNEL_PROC_LOCK(l);
|
||||||
SA_LWP_STATE_LOCK(l, f);
|
SA_LWP_STATE_LOCK(l, f);
|
||||||
}
|
|
||||||
|
DPRINTFN(7,("sa_upcall_userret(%d.%d %x) \n", p->p_pid, l->l_lid,
|
||||||
|
l->l_flag));
|
||||||
|
|
||||||
KDASSERT(sa->sa_vp == l);
|
KDASSERT(sa->sa_vp == l);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: savar.h,v 1.8 2003/10/31 22:47:44 cl Exp $ */
|
/* $NetBSD: savar.h,v 1.9 2003/11/01 01:38:47 cl Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||||
|
@ -128,6 +128,7 @@ void sa_putcachelwp(struct proc *, struct lwp *);
|
||||||
struct lwp *sa_getcachelwp(struct proc *);
|
struct lwp *sa_getcachelwp(struct proc *);
|
||||||
|
|
||||||
|
|
||||||
|
void sa_unblock_userret(struct lwp *);
|
||||||
void sa_upcall_userret(struct lwp *);
|
void sa_upcall_userret(struct lwp *);
|
||||||
void cpu_upcall(struct lwp *, int, int, int, void *, void *, void *, sa_upcall_t);
|
void cpu_upcall(struct lwp *, int, int, int, void *, void *, void *, sa_upcall_t);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: userret.h,v 1.1 2003/10/31 16:44:35 cl Exp $ */
|
/* $NetBSD: userret.h,v 1.2 2003/11/01 01:38:47 cl Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1998, 2000, 2003 The NetBSD Foundation, Inc.
|
* Copyright (c) 1998, 2000, 2003 The NetBSD Foundation, Inc.
|
||||||
|
@ -84,11 +84,15 @@ mi_userret(struct lwp *l)
|
||||||
struct proc *p = l->l_proc;
|
struct proc *p = l->l_proc;
|
||||||
int sig;
|
int sig;
|
||||||
|
|
||||||
|
/* Generate UNBLOCKED upcall. */
|
||||||
|
if (l->l_flag & L_SA_BLOCKING)
|
||||||
|
sa_unblock_userret(l);
|
||||||
|
|
||||||
/* Take pending signals. */
|
/* Take pending signals. */
|
||||||
while ((sig = CURSIG(l)) != 0)
|
while ((sig = CURSIG(l)) != 0)
|
||||||
postsig(sig);
|
postsig(sig);
|
||||||
|
|
||||||
/* Invoke per-process kernel-exit handling, if any */
|
/* Invoke per-process kernel-exit handling, if any. */
|
||||||
if (p->p_userret)
|
if (p->p_userret)
|
||||||
(p->p_userret)(l, p->p_userret_arg);
|
(p->p_userret)(l, p->p_userret_arg);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue