Prevent sa_newcachelwp() from creating new LWPs when the process is exiting.

This should fix PR 23418 which was also reported by Thomas Klausner and
Ian Fry (who also provided core dumps for analysis - thanks!).

Also g/c sa_yieldcall since it's now safe to put LWPs back into the cache.
Also return stacks in failure case.
This commit is contained in:
cl 2003-11-12 21:27:46 +00:00
parent 0342c9586a
commit e2c29624f5
2 changed files with 23 additions and 48 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_sa.c,v 1.41 2003/11/07 18:37:41 cl Exp $ */ /* $NetBSD: kern_sa.c,v 1.42 2003/11/12 21:27:46 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.41 2003/11/07 18:37:41 cl Exp $"); __KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.42 2003/11/12 21:27:46 cl Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -750,31 +750,34 @@ sa_switch(struct lwp *l, int type)
return; return;
} }
if (sa->sa_nstacks == 0) {
#ifdef DIAGNOSTIC
printf("sa_switch(%d.%d flag %x): Not enough stacks.\n",
p->p_pid, l->l_lid, l->l_flag);
#endif
sa_putcachelwp(p, l2); /* PHOLD from sa_getcachelwp */
mi_switch(l, NULL);
return;
}
/* /*
* XXX We need to allocate the sadata_upcall structure here, * XXX We need to allocate the sadata_upcall structure here,
* XXX since we can't sleep while waiting for memory inside * XXX since we can't sleep while waiting for memory inside
* XXX sa_upcall(). It would be nice if we could safely * XXX sa_upcall(). It would be nice if we could safely
* XXX allocate the sadata_upcall structure on the stack, here. * XXX allocate the sadata_upcall structure on the stack, here.
*/ */
if (sa->sa_nstacks == 0) {
#ifdef DIAGNOSTIC
printf("sa_switch(%d.%d flag %x): Not enough stacks.\n",
p->p_pid, l->l_lid, l->l_flag);
#endif
goto sa_upcall_failed;
}
sau = sadata_upcall_alloc(0); sau = sadata_upcall_alloc(0);
if (sau == NULL) { if (sau == NULL) {
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
printf("sa_switch(%d.%d): " printf("sa_switch(%d.%d): "
"couldn't allocate upcall data.\n", "couldn't allocate upcall data.\n",
p->p_pid, l->l_lid); p->p_pid, l->l_lid);
#endif #endif
goto sa_upcall_failed; sa_putcachelwp(p, l2); /* PHOLD from sa_getcachelwp */
mi_switch(l, NULL);
return;
} }
st = sa->sa_stacks[--sa->sa_nstacks]; st = sa->sa_stacks[--sa->sa_nstacks];
DPRINTFN(9,("sa_switch(%d.%d) nstacks-- = %2d\n", DPRINTFN(9,("sa_switch(%d.%d) nstacks-- = %2d\n",
l->l_proc->p_pid, l->l_lid, sa->sa_nstacks)); l->l_proc->p_pid, l->l_lid, sa->sa_nstacks));
@ -787,7 +790,10 @@ sa_switch(struct lwp *l, int type)
printf("sa_switch(%d.%d): Error %d from sa_upcall()\n", printf("sa_switch(%d.%d): Error %d from sa_upcall()\n",
p->p_pid, l->l_lid, error); p->p_pid, l->l_lid, error);
#endif #endif
goto sa_upcall_failed; sa->sa_stacks[sa->sa_nstacks++] = st;
sa_putcachelwp(p, l2); /* PHOLD from sa_getcachelwp */
mi_switch(l, NULL);
return;
} }
/* /*
@ -842,13 +848,6 @@ sa_switch(struct lwp *l, int type)
} else { } else {
/* NOTREACHED */ /* NOTREACHED */
panic("sa_vp empty"); panic("sa_vp empty");
sa_upcall_failed:
cpu_setfunc(l2, sa_yieldcall, l2);
l2->l_priority = l2->l_usrpri;
setrunnable(l2);
PRELE(l2); /* Remove the artificial hold-count */
} }
DPRINTFN(4,("sa_switch(%d.%d) switching to LWP %d.\n", DPRINTFN(4,("sa_switch(%d.%d) switching to LWP %d.\n",
@ -888,31 +887,6 @@ sa_switchcall(void *arg)
upcallret(l); upcallret(l);
} }
void
sa_yieldcall(void *arg)
{
struct lwp *l;
struct proc *p;
struct sadata *sa;
l = arg;
p = l->l_proc;
sa = p->p_sa;
sa->sa_vp = l;
DPRINTFN(6,("sa_yieldcall(%d.%d)\n", p->p_pid, l->l_lid));
if (LIST_EMPTY(&sa->sa_lwpcache)) {
/* Allocate the next cache LWP */
DPRINTFN(6,("sa_yieldcall(%d.%d) allocating LWP\n",
p->p_pid, l->l_lid));
sa_newcachelwp(l);
}
sa_yield(l);
upcallret(l);
}
static int static int
sa_newcachelwp(struct lwp *l) sa_newcachelwp(struct lwp *l)
{ {
@ -923,6 +897,8 @@ sa_newcachelwp(struct lwp *l)
int s; int s;
p = l->l_proc; p = l->l_proc;
if (p->p_flag & P_WEXIT)
return (0);
inmem = uvm_uarea_alloc(&uaddr); inmem = uvm_uarea_alloc(&uaddr);
if (__predict_false(uaddr == 0)) { if (__predict_false(uaddr == 0)) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: savar.h,v 1.11 2003/11/03 22:34:51 cl Exp $ */ /* $NetBSD: savar.h,v 1.12 2003/11/12 21:27:46 cl Exp $ */
/*- /*-
* Copyright (c) 2001 The NetBSD Foundation, Inc. * Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -116,7 +116,6 @@ void sa_switch(struct lwp *, int);
void sa_preempt(struct lwp *); void sa_preempt(struct lwp *);
void sa_yield(struct lwp *); void sa_yield(struct lwp *);
void sa_switchcall(void *); void sa_switchcall(void *);
void sa_yieldcall(void *);
int sa_upcall(struct lwp *, int, struct lwp *, struct lwp *, size_t, void *); int sa_upcall(struct lwp *, int, struct lwp *, struct lwp *, size_t, void *);
int sa_upcall0(struct lwp *, int, struct lwp *, struct lwp *, int sa_upcall0(struct lwp *, int, struct lwp *, struct lwp *,
size_t, void *, struct sadata_upcall *, stack_t *); size_t, void *, struct sadata_upcall *, stack_t *);