Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys - use list to keep track of free stacks.
details: https://anonhg.NetBSD.org/src/rev/9e22b1c1aa60
branches: trunk
changeset: 555447:9e22b1c1aa60
user: cl <cl%NetBSD.org@localhost>
date: Mon Nov 17 22:52:09 2003 +0000
description:
- use list to keep track of free stacks.
- use splay tree for the pagefault check if the thread was running on
an upcall stack.
=> removes the limitation that all upcall stacks need to be
adjoining and that all upcall stacks have to be loaded with the
1st sys_sa_stacks call.
=> enables keeping information associated with a stack in the kernel
which makes it simpler to find out which LWP is using a stack.
=> allows increasing the SA_MAXNUMSTACKS without having to
allocate an array of that size.
diffstat:
sys/kern/kern_exec.c | 12 +-
sys/kern/kern_exit.c | 14 +-
sys/kern/kern_proc.c | 8 +-
sys/kern/kern_sa.c | 235 ++++++++++++++++++++++++++++++--------------------
sys/sys/lwp.h | 4 +-
sys/sys/savar.h | 21 +++-
6 files changed, 171 insertions(+), 123 deletions(-)
diffs (truncated from 707 to 300 lines):
diff -r 2ecc9e7331b3 -r 9e22b1c1aa60 sys/kern/kern_exec.c
--- a/sys/kern/kern_exec.c Mon Nov 17 22:38:11 2003 +0000
+++ b/sys/kern/kern_exec.c Mon Nov 17 22:52:09 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_exec.c,v 1.175 2003/11/12 21:07:38 dsl Exp $ */
+/* $NetBSD: kern_exec.c,v 1.176 2003/11/17 22:52:09 cl Exp $ */
/*-
* Copyright (C) 1993, 1994, 1996 Christopher G. Demetriou
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.175 2003/11/12 21:07:38 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.176 2003/11/17 22:52:09 cl Exp $");
#include "opt_ktrace.h"
#include "opt_syscall_debug.h"
@@ -545,12 +545,8 @@
p->p_nlwpid = 1;
/* Release any SA state. */
- if (p->p_sa) {
- p->p_flag &= ~P_SA;
- free(p->p_sa->sa_stacks, M_SA);
- pool_put(&sadata_pool, p->p_sa);
- p->p_sa = NULL;
- }
+ if (p->p_sa)
+ sa_release(p);
/* Remove POSIX timers */
timers_free(p, TIMERS_POSIX);
diff -r 2ecc9e7331b3 -r 9e22b1c1aa60 sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c Mon Nov 17 22:38:11 2003 +0000
+++ b/sys/kern/kern_exit.c Mon Nov 17 22:52:09 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_exit.c,v 1.128 2003/11/12 21:07:38 dsl Exp $ */
+/* $NetBSD: kern_exit.c,v 1.129 2003/11/17 22:52:09 cl Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -74,7 +74,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.128 2003/11/12 21:07:38 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.129 2003/11/17 22:52:09 cl Exp $");
#include "opt_ktrace.h"
#include "opt_perfctrs.h"
@@ -858,13 +858,9 @@
if (p->p_textvp)
vrele(p->p_textvp);
- /*
- * Release any SA state
- */
- if (p->p_sa) {
- free(p->p_sa->sa_stacks, M_SA);
- pool_put(&sadata_pool, p->p_sa);
- }
+ /* Release any SA state. */
+ if (p->p_sa)
+ sa_release(p);
/* Free proc structure and let pid be reallocated */
proc_free_mem(p);
diff -r 2ecc9e7331b3 -r 9e22b1c1aa60 sys/kern/kern_proc.c
--- a/sys/kern/kern_proc.c Mon Nov 17 22:38:11 2003 +0000
+++ b/sys/kern/kern_proc.c Mon Nov 17 22:52:09 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_proc.c,v 1.68 2003/11/12 21:07:38 dsl Exp $ */
+/* $NetBSD: kern_proc.c,v 1.69 2003/11/17 22:52:09 cl Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -69,7 +69,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.68 2003/11/12 21:07:38 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.69 2003/11/17 22:52:09 cl Exp $");
#include "opt_kstack.h"
@@ -190,6 +190,7 @@
struct pool ras_pool;
struct pool sadata_pool;
struct pool saupcall_pool;
+struct pool sastack_pool;
struct pool ptimer_pool;
MALLOC_DEFINE(M_EMULDATA, "emuldata", "Per-process emulation data");
@@ -275,7 +276,8 @@
pool_init(&sadata_pool, sizeof(struct sadata), 0, 0, 0, "sadatapl",
&pool_allocator_nointr);
pool_init(&saupcall_pool, sizeof(struct sadata_upcall), 0, 0, 0,
- "saupcpl",
+ "saupcpl", &pool_allocator_nointr);
+ pool_init(&sastack_pool, sizeof(struct sastack), 0, 0, 0, "sastackpl",
&pool_allocator_nointr);
pool_init(&ptimer_pool, sizeof(struct ptimer), 0, 0, 0, "ptimerpl",
&pool_allocator_nointr);
diff -r 2ecc9e7331b3 -r 9e22b1c1aa60 sys/kern/kern_sa.c
--- a/sys/kern/kern_sa.c Mon Nov 17 22:38:11 2003 +0000
+++ b/sys/kern/kern_sa.c Mon Nov 17 22:52:09 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_sa.c,v 1.42 2003/11/12 21:27:46 cl Exp $ */
+/* $NetBSD: kern_sa.c,v 1.43 2003/11/17 22:52:09 cl Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.42 2003/11/12 21:27:46 cl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.43 2003/11/17 22:52:09 cl Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -53,11 +53,12 @@
#include <uvm/uvm_extern.h>
+static __inline int sast_compare(struct sastack *, struct sastack *);
static void sa_setwoken(struct lwp *);
static int sa_newcachelwp(struct lwp *);
static struct lwp *sa_vp_repossess(struct lwp *l);
-static int sa_pagefault(struct lwp *, ucontext_t *);
+static __inline int sa_pagefault(struct lwp *, ucontext_t *);
void sa_upcall_getstate(union sau_state *, struct lwp *);
@@ -84,6 +85,9 @@
(l)->l_flag |= (f) & L_SA; \
} while (/*CONSTCOND*/ 0)
+SPLAY_PROTOTYPE(sasttree, sastack, sast_node, sast_compare);
+SPLAY_GENERATE(sasttree, sastack, sast_node, sast_compare);
+
/*
* sadata_upcall_alloc:
@@ -152,13 +156,11 @@
sa->sa_vp = NULL;
sa->sa_wokenq_head = NULL;
sa->sa_concurrency = 1;
- sa->sa_stacks = malloc(sizeof(stack_t) * SA_NUMSTACKS,
- M_SA, M_WAITOK);
+ SPLAY_INIT(&sa->sa_stackstree);
+ SLIST_INIT(&sa->sa_stackslist);
sa->sa_nstacks = 0;
sa->sa_vp_faultaddr = 0;
sa->sa_vp_ofaultaddr = 0;
- sa->sa_vp_stacks_low = 0;
- sa->sa_vp_stacks_high = 0;
LIST_INIT(&sa->sa_lwpcache);
SIMPLEQ_INIT(&sa->sa_upcalls);
p->p_sa = sa;
@@ -177,6 +179,38 @@
return (0);
}
+void
+sa_release(struct proc *p)
+{
+ struct sadata *sa;
+ struct sastack *sast, *next;
+
+ sa = p->p_sa;
+ KDASSERT(sa != NULL);
+
+ for (sast = SPLAY_MIN(sasttree, &sa->sa_stackstree); sast != NULL;
+ sast = next) {
+ next = SPLAY_NEXT(sasttree, &sa->sa_stackstree, sast);
+ SPLAY_REMOVE(sasttree, &sa->sa_stackstree, sast);
+ pool_put(&sastack_pool, sast);
+ }
+
+ p->p_flag &= ~P_SA;
+ pool_put(&sadata_pool, sa);
+ p->p_sa = NULL;
+}
+
+static __inline int
+sast_compare(struct sastack *a, struct sastack *b)
+{
+ if ((vaddr_t)a->sast_stack.ss_sp + a->sast_stack.ss_size <=
+ (vaddr_t)b->sast_stack.ss_sp)
+ return (-1);
+ if ((vaddr_t)a->sast_stack.ss_sp >=
+ (vaddr_t)b->sast_stack.ss_sp + b->sast_stack.ss_size)
+ return (1);
+ return (0);
+}
int
sys_sa_stacks(struct lwp *l, void *v, register_t *retval)
@@ -187,6 +221,7 @@
} */ *uap = v;
struct sadata *sa = l->l_proc->p_sa;
struct lwp *l2;
+ struct sastack *sast, newsast;
int count, error, f, i;
/* We have to be using scheduler activations */
@@ -196,59 +231,59 @@
count = SCARG(uap, num);
if (count < 0)
return (EINVAL);
- count = min(count, SA_NUMSTACKS - sa->sa_nstacks);
SA_LWP_STATE_LOCK(l, f);
- error = copyin(SCARG(uap, stacks), sa->sa_stacks + sa->sa_nstacks,
- sizeof(stack_t) * count);
- SA_LWP_STATE_UNLOCK(l, f);
- if (error)
- return (error);
+
+ error = 0;
- for (i = sa->sa_nstacks; i < sa->sa_nstacks + count; i++) {
- LIST_FOREACH(l2, &l->l_proc->p_lwps, l_sibling) {
- if ((l2->l_upcallstack == sa->sa_stacks[i].ss_sp)) {
+ for (i = 0; i < count; i++) {
+ error = copyin(SCARG(uap, stacks) + i, &newsast.sast_stack,
+ sizeof(stack_t));
+ if (error) {
+ count = i;
+ break;
+ }
+ if ((sast = SPLAY_FIND(sasttree, &sa->sa_stackstree, &newsast))) {
+ DPRINTFN(9, ("sa_stacks(%d.%d) returning stack %p\n",
+ l->l_proc->p_pid, l->l_lid,
+ newsast.sast_stack.ss_sp));
+ if ((l2 = sast->sast_blocker)) {
l2->l_upcallstack = NULL;
+ sast->sast_blocker = NULL;
wakeup(&l2->l_upcallstack);
}
+ if (SLIST_NEXT(sast, sast_list) != (void *)-1) {
+ count = i;
+ error = EEXIST;
+ break;
+ }
+ } else if (sa->sa_nstacks >= SA_MAXNUMSTACKS * sa->sa_concurrency) {
+ DPRINTFN(9, ("sa_stacks(%d.%d) already using %d stacks\n",
+ l->l_proc->p_pid, l->l_lid,
+ SA_MAXNUMSTACKS * sa->sa_concurrency));
+ count = i;
+ error = ENOMEM;
+ break;
+ } else {
+ DPRINTFN(9, ("sa_stacks(%d.%d) adding stack %p\n",
+ l->l_proc->p_pid, l->l_lid,
+ newsast.sast_stack.ss_sp));
+ sast = pool_get(&sastack_pool, PR_WAITOK);
+ sast->sast_stack = newsast.sast_stack;
+ sast->sast_blocker = NULL;
+ SPLAY_INSERT(sasttree, &sa->sa_stackstree, sast);
+ sa->sa_nstacks++;
}
+ SLIST_INSERT_HEAD(&sa->sa_stackslist, sast, sast_list);
}
- if ((sa->sa_nstacks == 0) && (sa->sa_wokenq_head != NULL))
+ if (SLIST_EMPTY(&sa->sa_stackslist) && (sa->sa_wokenq_head != NULL))
l->l_flag |= L_SA_UPCALL;
- /*
- * Save addresses of the first and last stack on initial load
- * the pagefault code uses the saved address to detect threads
- * running on an upcall stack.
- * XXX assumes all stacks are adjoining
- * XXX assumes initial load includes all stacks ever used
- */
- if (sa->sa_vp_stacks_low == 0) {
- vaddr_t low = VM_MAXUSER_ADDRESS;
- vaddr_t high = 0;
-
- for (i = 0; i < count; i++) {
- stack_t *stackp = &sa->sa_stacks[sa->sa_nstacks + i];
-
- low = min(low, (vaddr_t)stackp->ss_sp);
- high = max(high,
- (vaddr_t)stackp->ss_sp + stackp->ss_size);
- }
- sa->sa_vp_stacks_low = low;
- sa->sa_vp_stacks_high = high;
- DPRINTFN(11,("sys_sa_stacks(%d.%d): low 0x%llx high 0x%llx\n",
- l->l_proc->p_pid, l->l_lid,
- (unsigned long long)sa->sa_vp_stacks_low,
- (unsigned long long)sa->sa_vp_stacks_high));
- }
-
- sa->sa_nstacks += count;
- DPRINTFN(9, ("sa_stacks(%d.%d) nstacks + %d = %2d\n",
Home |
Main Index |
Thread Index |
Old Index