Module Name: src
Committed By: para
Date: Fri Jan 4 08:28:39 UTC 2013
Modified Files:
src/sys/kern: subr_vmem.c
Log Message:
fix a lock order reversal during global boundary tag refill.
thanks to chuq@
xxx: request pullup
To generate a diff of this commit:
cvs rdiff -u -r1.76 -r1.77 src/sys/kern/subr_vmem.c
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_vmem.c
diff -u src/sys/kern/subr_vmem.c:1.76 src/sys/kern/subr_vmem.c:1.77
--- src/sys/kern/subr_vmem.c:1.76 Thu Sep 13 21:44:50 2012
+++ src/sys/kern/subr_vmem.c Fri Jan 4 08:28:38 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_vmem.c,v 1.76 2012/09/13 21:44:50 joerg Exp $ */
+/* $NetBSD: subr_vmem.c,v 1.77 2013/01/04 08:28:38 para Exp $ */
/*-
* Copyright (c)2006,2007,2008,2009 YAMAMOTO Takashi,
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_vmem.c,v 1.76 2012/09/13 21:44:50 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_vmem.c,v 1.77 2013/01/04 08:28:38 para Exp $");
#if defined(_KERNEL)
#include "opt_ddb.h"
@@ -273,6 +273,7 @@ static int static_qc_pool_count = STATIC
vmem_t *kmem_va_meta_arena;
vmem_t *kmem_meta_arena;
+static kmutex_t vmem_refill_lock;
static kmutex_t vmem_btag_lock;
static LIST_HEAD(, vmem_btag) vmem_btag_freelist;
static size_t vmem_btag_freelist_count = 0;
@@ -292,19 +293,26 @@ bt_refillglobal(vm_flag_t flags)
bt_t *bt;
int i;
+ mutex_enter(&vmem_refill_lock);
+
mutex_enter(&vmem_btag_lock);
if (vmem_btag_freelist_count > 0) {
mutex_exit(&vmem_btag_lock);
+ mutex_exit(&vmem_refill_lock);
return 0;
+ } else {
+ mutex_exit(&vmem_btag_lock);
}
if (vmem_alloc(kmem_meta_arena, PAGE_SIZE,
(flags & ~VM_FITMASK) | VM_INSTANTFIT | VM_POPULATING, &va) != 0) {
mutex_exit(&vmem_btag_lock);
+ mutex_exit(&vmem_refill_lock);
return ENOMEM;
}
VMEM_EVCNT_INCR(bt_pages);
+ mutex_enter(&vmem_btag_lock);
btp = (void *) va;
for (i = 0; i < (BT_PER_PAGE); i++) {
bt = btp;
@@ -318,9 +326,14 @@ bt_refillglobal(vm_flag_t flags)
}
mutex_exit(&vmem_btag_lock);
- bt_refill(kmem_arena, (flags & ~VM_FITMASK) | VM_INSTANTFIT);
- bt_refill(kmem_va_meta_arena, (flags & ~VM_FITMASK) | VM_INSTANTFIT);
- bt_refill(kmem_meta_arena, (flags & ~VM_FITMASK) | VM_INSTANTFIT);
+ bt_refill(kmem_arena, (flags & ~VM_FITMASK)
+ | VM_INSTANTFIT | VM_POPULATING);
+ bt_refill(kmem_va_meta_arena, (flags & ~VM_FITMASK)
+ | VM_INSTANTFIT | VM_POPULATING);
+ bt_refill(kmem_meta_arena, (flags & ~VM_FITMASK)
+ | VM_INSTANTFIT | VM_POPULATING);
+
+ mutex_exit(&vmem_refill_lock);
return 0;
}
@@ -330,7 +343,9 @@ bt_refill(vmem_t *vm, vm_flag_t flags)
{
bt_t *bt;
- bt_refillglobal(flags);
+ if (!(flags & VM_POPULATING)) {
+ bt_refillglobal(flags);
+ }
VMEM_LOCK(vm);
mutex_enter(&vmem_btag_lock);
@@ -701,6 +716,7 @@ vmem_bootstrap(void)
{
mutex_init(&vmem_list_lock, MUTEX_DEFAULT, IPL_VM);
+ mutex_init(&vmem_refill_lock, MUTEX_DEFAULT, IPL_VM);
mutex_init(&vmem_btag_lock, MUTEX_DEFAULT, IPL_VM);
while (static_bt_count-- > 0) {