Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/kern ras_fork: don't do PR_WAITOK holding a spinlock.
details: https://anonhg.NetBSD.org/src/rev/834b787a7bf8
branches: trunk
changeset: 565192:834b787a7bf8
user: yamt <yamt%NetBSD.org@localhost>
date: Thu Apr 01 02:37:42 2004 +0000
description:
ras_fork: don't do PR_WAITOK holding a spinlock.
diffstat:
sys/kern/kern_ras.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 47 insertions(+), 6 deletions(-)
diffs (83 lines):
diff -r 92326d82dd2c -r 834b787a7bf8 sys/kern/kern_ras.c
--- a/sys/kern/kern_ras.c Thu Apr 01 02:37:24 2004 +0000
+++ b/sys/kern/kern_ras.c Thu Apr 01 02:37:42 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_ras.c,v 1.8 2004/04/01 01:49:04 yamt Exp $ */
+/* $NetBSD: kern_ras.c,v 1.9 2004/04/01 02:37:42 yamt Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_ras.c,v 1.8 2004/04/01 01:49:04 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_ras.c,v 1.9 2004/04/01 02:37:42 yamt Exp $");
#include <sys/param.h>
#include <sys/lock.h>
@@ -108,19 +108,60 @@
ras_fork(struct proc *p1, struct proc *p2)
{
struct ras *rp, *nrp;
- int nras = 0;
+ int nras;
+
+again:
+ /*
+ * first, try to shortcut.
+ */
+ if (LIST_EMPTY(&p1->p_raslist))
+ return (0);
+
+ /*
+ * count entries.
+ */
+
+ nras = 0;
simple_lock(&p1->p_lock);
- LIST_FOREACH(rp, &p1->p_raslist, ras_list) {
+ LIST_FOREACH(rp, &p1->p_raslist, ras_list)
nras++;
+ simple_unlock(&p1->p_lock);
+
+ /*
+ * allocate entries.
+ */
+
+ for ( ; nras > 0; nras--) {
nrp = pool_get(&ras_pool, PR_WAITOK);
- nrp->ras_startaddr = rp->ras_startaddr;
- nrp->ras_endaddr = rp->ras_endaddr;
nrp->ras_hits = 0;
LIST_INSERT_HEAD(&p2->p_raslist, nrp, ras_list);
}
+
+ /*
+ * copy entries.
+ */
+
+ simple_lock(&p1->p_lock);
+ nrp = LIST_FIRST(&p2->p_raslist);
+ LIST_FOREACH(rp, &p1->p_raslist, ras_list) {
+ if (nrp == NULL)
+ break;
+ nrp->ras_startaddr = rp->ras_startaddr;
+ nrp->ras_endaddr = rp->ras_endaddr;
+ nrp = LIST_NEXT(nrp, ras_list);
+ }
simple_unlock(&p1->p_lock);
+ /*
+ * if we lose a race, retry.
+ */
+
+ if (rp != NULL || nrp != NULL) {
+ ras_purgeall(p2);
+ goto again;
+ }
+
DPRINTF(("ras_fork: p1=%p, p2=%p, nras=%d\n", p1, p2, nras));
return (0);
Home |
Main Index |
Thread Index |
Old Index