summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_zone.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vm/vm_zone.c')
-rw-r--r--sys/vm/vm_zone.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/sys/vm/vm_zone.c b/sys/vm/vm_zone.c
index 4cddadc..30fadbe 100644
--- a/sys/vm/vm_zone.c
+++ b/sys/vm/vm_zone.c
@@ -137,6 +137,7 @@ zinitna(vm_zone_t z, vm_object_t obj, char *name, int size,
* in pages as needed.
*/
if (z->zflags & ZONE_INTERRUPT) {
+ int hadvmlock;
totsize = round_page(z->zsize * nentries);
atomic_add_int(&zone_kmem_kvaspace, totsize);
@@ -145,12 +146,17 @@ zinitna(vm_zone_t z, vm_object_t obj, char *name, int size,
return 0;
z->zpagemax = totsize / PAGE_SIZE;
+ hadvmlock = mtx_owned(&vm_mtx);
+ if (!hadvmlock)
+ mtx_lock(&vm_mtx);
if (obj == NULL) {
z->zobj = vm_object_allocate(OBJT_DEFAULT, z->zpagemax);
} else {
z->zobj = obj;
_vm_object_allocate(OBJT_DEFAULT, z->zpagemax, obj);
}
+ if (!hadvmlock)
+ mtx_unlock(&vm_mtx);
z->zallocflag = VM_ALLOC_INTERRUPT;
z->zmax += nentries;
} else {
@@ -262,7 +268,6 @@ _zget(vm_zone_t z)
void *item;
KASSERT(z != NULL, ("invalid zone"));
- mtx_assert(&z->zmtx, MA_OWNED);
if (z->zflags & ZONE_INTERRUPT) {
item = (char *) z->zkva + z->zpagecount * PAGE_SIZE;
@@ -299,16 +304,13 @@ _zget(vm_zone_t z)
* We can wait, so just do normal map allocation in the appropriate
* map.
*/
+ mtx_unlock(&z->zmtx);
if (lockstatus(&kernel_map->lock, NULL)) {
- mtx_unlock(&z->zmtx);
item = (void *) kmem_malloc(kmem_map, nbytes, M_WAITOK);
- mtx_lock(&z->zmtx);
if (item != NULL)
atomic_add_int(&zone_kmem_pages, z->zalloc);
} else {
- mtx_unlock(&z->zmtx);
item = (void *) kmem_alloc(kernel_map, nbytes);
- mtx_lock(&z->zmtx);
if (item != NULL)
atomic_add_int(&zone_kern_pages, z->zalloc);
}
@@ -318,6 +320,7 @@ _zget(vm_zone_t z)
nbytes = 0;
}
nitems = nbytes / z->zsize;
+ mtx_lock(&z->zmtx);
}
z->ztotal += nitems;
@@ -361,14 +364,17 @@ void *
zalloc(vm_zone_t z)
{
void *item;
+ int hadvmlock;
KASSERT(z != NULL, ("invalid zone"));
+ hadvmlock = mtx_owned(&vm_mtx);
+ if (!hadvmlock)
+ mtx_lock(&vm_mtx);
mtx_lock(&z->zmtx);
if (z->zfreecnt <= z->zfreemin) {
item = _zget(z);
- mtx_unlock(&z->zmtx);
- return item;
+ goto out;
}
item = z->zitems;
@@ -381,8 +387,11 @@ zalloc(vm_zone_t z)
z->zfreecnt--;
z->znalloc++;
-
+
+out:
mtx_unlock(&z->zmtx);
+ if (!hadvmlock)
+ mtx_unlock(&vm_mtx);
return item;
}
@@ -392,8 +401,13 @@ zalloc(vm_zone_t z)
void
zfree(vm_zone_t z, void *item)
{
+ int hadvmlock;
+
KASSERT(z != NULL, ("invalid zone"));
KASSERT(item != NULL, ("invalid item"));
+ hadvmlock = mtx_owned(&vm_mtx);
+ if (!hadvmlock)
+ mtx_lock(&vm_mtx);
mtx_lock(&z->zmtx);
((void **) item)[0] = z->zitems;
@@ -405,6 +419,8 @@ zfree(vm_zone_t z, void *item)
z->zitems = item;
z->zfreecnt++;
+ if (!hadvmlock)
+ mtx_unlock(&vm_mtx);
mtx_unlock(&z->zmtx);
}
OpenPOWER on IntegriCloud