Module Name: src
Committed By: mrg
Date: Sat Dec 16 03:13:29 UTC 2017
Modified Files:
src/sys/kern: subr_pool.c
src/sys/sys: pool.h
Log Message:
hopefully workaround the irregularly "fork fails in init" problem.
if a pool is growing, and the grower is PR_NOWAIT, mark this.
if another caller wants to grow the pool and is also PR_NOWAIT,
busy-wait for the original caller, which should either succeed
or hard-fail fairly quickly.
implement the busy-wait by unlocking and relocking this pools
mutex and returning ERESTART. other methods (such as having
the caller do this) were significantly more code and this hack
is fairly localised.
ok chs@ riastradh@
To generate a diff of this commit:
cvs rdiff -u -r1.218 -r1.219 src/sys/kern/subr_pool.c
cvs rdiff -u -r1.81 -r1.82 src/sys/sys/pool.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/subr_pool.c
diff -u src/sys/kern/subr_pool.c:1.218 src/sys/kern/subr_pool.c:1.219
--- src/sys/kern/subr_pool.c:1.218 Mon Dec 4 03:05:24 2017
+++ src/sys/kern/subr_pool.c Sat Dec 16 03:13:29 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_pool.c,v 1.218 2017/12/04 03:05:24 mrg Exp $ */
+/* $NetBSD: subr_pool.c,v 1.219 2017/12/16 03:13:29 mrg Exp $ */
/*-
* Copyright (c) 1997, 1999, 2000, 2002, 2007, 2008, 2010, 2014, 2015
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_pool.c,v 1.218 2017/12/04 03:05:24 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_pool.c,v 1.219 2017/12/16 03:13:29 mrg Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@@ -1073,10 +1073,23 @@ pool_grow(struct pool *pp, int flags)
} while (pp->pr_flags & PR_GROWING);
return ERESTART;
} else {
+ if (pp->pr_flags & PR_GROWINGNOWAIT) {
+ /*
+ * This needs an unlock/relock dance so
+ * that the other caller has a chance to
+ * run and actually do the thing. Note
+ * that this is effectively a busy-wait.
+ */
+ mutex_exit(&pp->pr_lock);
+ mutex_enter(&pp->pr_lock);
+ return ERESTART;
+ }
return EWOULDBLOCK;
}
}
pp->pr_flags |= PR_GROWING;
+ if ((flags & PR_WAITOK) == 0)
+ pp->pr_flags |= PR_GROWINGNOWAIT;
mutex_exit(&pp->pr_lock);
char *cp = pool_allocator_alloc(pp, flags);
@@ -1093,7 +1106,7 @@ pool_grow(struct pool *pp, int flags)
pool_prime_page(pp, cp, ph);
pp->pr_npagealloc++;
KASSERT(pp->pr_flags & PR_GROWING);
- pp->pr_flags &= ~PR_GROWING;
+ pp->pr_flags &= ~(PR_GROWING|PR_GROWINGNOWAIT);
/*
* If anyone was waiting for pool_grow, notify them that we
* may have just done it.
@@ -1102,7 +1115,7 @@ pool_grow(struct pool *pp, int flags)
return 0;
out:
KASSERT(pp->pr_flags & PR_GROWING);
- pp->pr_flags &= ~PR_GROWING;
+ pp->pr_flags &= ~(PR_GROWING|PR_GROWINGNOWAIT);
mutex_enter(&pp->pr_lock);
return ENOMEM;
}
Index: src/sys/sys/pool.h
diff -u src/sys/sys/pool.h:1.81 src/sys/sys/pool.h:1.82
--- src/sys/sys/pool.h:1.81 Sat Dec 2 08:15:43 2017
+++ src/sys/sys/pool.h Sat Dec 16 03:13:29 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: pool.h,v 1.81 2017/12/02 08:15:43 mrg Exp $ */
+/* $NetBSD: pool.h,v 1.82 2017/12/16 03:13:29 mrg Exp $ */
/*-
* Copyright (c) 1997, 1998, 1999, 2000, 2007 The NetBSD Foundation, Inc.
@@ -148,6 +148,7 @@ struct pool {
#define PR_NOALIGN 0x800 /* don't assume backend alignment */
#define PR_LARGECACHE 0x1000 /* use large cache groups */
#define PR_GROWING 0x2000 /* pool_grow in progress */
+#define PR_GROWINGNOWAIT 0x4000 /* pool_grow in progress by PR_NOWAIT alloc */
/*
* `pr_lock' protects the pool's data structures when removing