aboutsummaryrefslogtreecommitdiff
path: root/sys/vm
diff options
context:
space:
mode:
authorJohn Dyson <dyson@FreeBSD.org>1997-08-05 22:24:31 +0000
committerJohn Dyson <dyson@FreeBSD.org>1997-08-05 22:24:31 +0000
commit0d65e566b9205b394757258c5ffc34d8b64e0998 (patch)
tree15a797f5e4c2280a999b7e900fa3f40ce4b824e2 /sys/vm
parentb79933ebfae10dd578fbb7bf77dfe50d766ff7c8 (diff)
Notes
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_map.c18
-rw-r--r--sys/vm/vm_zone.c134
-rw-r--r--sys/vm/vm_zone.h89
3 files changed, 166 insertions, 75 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 3ce7173ef2be6..cc4128a261e8c 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -61,7 +61,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_map.c,v 1.81 1997/08/05 01:32:52 dyson Exp $
+ * $Id: vm_map.c,v 1.82 1997/08/05 22:07:27 dyson Exp $
*/
/*
@@ -174,13 +174,13 @@ void
vm_map_startup()
{
mapzone = &mapzone_store;
- _zbootinit(mapzone, "MAP", sizeof (struct vm_map),
+ zbootinit(mapzone, "MAP", sizeof (struct vm_map),
map_init, MAX_KMAP);
kmapentzone = &kmapentzone_store;
- _zbootinit(kmapentzone, "KMAP ENTRY", sizeof (struct vm_map_entry),
+ zbootinit(kmapentzone, "KMAP ENTRY", sizeof (struct vm_map_entry),
kmap_entry_init, MAX_KMAPENT);
mapentzone = &mapentzone_store;
- _zbootinit(mapentzone, "MAP ENTRY", sizeof (struct vm_map_entry),
+ zbootinit(mapentzone, "MAP ENTRY", sizeof (struct vm_map_entry),
map_entry_init, MAX_MAPENT);
}
@@ -207,12 +207,12 @@ vmspace_alloc(min, max, pageable)
void
vm_init2(void) {
- _zinit(kmapentzone, &kmapentobj,
+ zinitna(kmapentzone, &kmapentobj,
NULL, 0, 4096, ZONE_INTERRUPT, 4);
- _zinit(mapentzone, &mapentobj,
- NULL, 0, 0, ZONE_WAIT, 4);
- _zinit(mapzone, &mapobj,
- NULL, 0, 0, ZONE_WAIT, 4);
+ zinitna(mapentzone, &mapentobj,
+ NULL, 0, 0, 0, 4);
+ zinitna(mapzone, &mapobj,
+ NULL, 0, 0, 0, 4);
}
void
diff --git a/sys/vm/vm_zone.c b/sys/vm/vm_zone.c
index 17a8500569442..539d68c64d905 100644
--- a/sys/vm/vm_zone.c
+++ b/sys/vm/vm_zone.c
@@ -6,19 +6,19 @@
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
- * notice immediately at the beginning of the file, without modification,
- * this list of conditions, and the following disclaimer.
+ * notice immediately at the beginning of the file, without modification,
+ * this list of conditions, and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
* 3. Absolutely no warranty of function or purpose is made by the author
- * John S. Dyson.
+ * John S. Dyson.
* 4. This work was done expressly for inclusion into FreeBSD. Other use
- * is allowed if this notation is included.
+ * is allowed if this notation is included.
* 5. Modifications may be freely made to this file if the above conditions
- * are met.
+ * are met.
*
- * $Id$
+ * $Id: vm_zone.c,v 1.1 1997/08/05 00:07:29 dyson Exp $
*/
#include <sys/param.h>
@@ -48,23 +48,44 @@
* Note that the initial implementation of this had coloring, and
* absolutely no improvement (actually perf degradation) occurred.
*
- * _zinit, zinit, _zbootinit are the initialization routines.
+ * zinitna, zinit, zbootinit are the initialization routines.
* zalloc, zfree, are the interrupt/lock unsafe allocation/free routines.
* zalloci, zfreei, are the interrupt/lock safe allocation/free routines.
*/
+/*
+ * Create a zone, but don't allocate the zone structure. If the
+ * zone had been previously created by the zone boot code, initialize
+ * various parts of the zone code.
+ *
+ * If waits are not allowed during allocation (e.g. during interrupt
+ * code), a-priori allocate the kernel virtual space, and allocate
+ * only pages when needed.
+ *
+ * Arguments:
+ * z pointer to zone structure.
+ * obj pointer to VM object (opt).
+ * name name of zone.
+ * size size of zone entries.
+ * nentries number of zone entries allocated (only ZONE_INTERRUPT.)
+ * flags ZONE_INTERRUPT -- items can be allocated at interrupt time.
+ * zalloc number of pages allocated when memory is needed.
+ *
+ * Note that when using ZONE_INTERRUPT, the size of the zone is limited
+ * by the nentries argument. The size of the memory allocatable is
+ * unlimited if ZONE_INTERRUPT is not set.
+ *
+ */
int
-_zinit(vm_zone_t z, vm_object_t obj, char *name, int size,
+zinitna(vm_zone_t z, vm_object_t obj, char *name, int size,
int nentries, int flags, int zalloc) {
int totsize;
if ((z->zflags & ZONE_BOOT) == 0) {
-
z->zsize = size;
simple_lock_init(&z->zlock);
z->zfreecnt = 0;
z->zname = name;
-
}
z->zflags |= flags;
@@ -73,7 +94,7 @@ _zinit(vm_zone_t z, vm_object_t obj, char *name, int size,
* If we cannot wait, allocate KVA space up front, and we will fill
* in pages as needed.
*/
- if ((z->zflags & ZONE_WAIT) == 0) {
+ if (z->zflags & ZONE_INTERRUPT) {
totsize = round_page(z->zsize * nentries);
@@ -89,6 +110,9 @@ _zinit(vm_zone_t z, vm_object_t obj, char *name, int size,
z->zobj = obj;
_vm_object_allocate(OBJT_DEFAULT, z->zpagemax, obj);
}
+ z->zallocflag = VM_ALLOC_INTERRUPT;
+ } else {
+ z->zallocflag = VM_ALLOC_SYSTEM;
}
if ( z->zsize > PAGE_SIZE)
@@ -96,10 +120,6 @@ _zinit(vm_zone_t z, vm_object_t obj, char *name, int size,
else
z->zfreemin = PAGE_SIZE / z->zsize;
- z->zallocflag = VM_ALLOC_SYSTEM;
- if (z->zflags & ZONE_INTERRUPT)
- z->zallocflag = VM_ALLOC_INTERRUPT;
-
z->zpagecount = 0;
if (zalloc)
z->zalloc = zalloc;
@@ -109,6 +129,13 @@ _zinit(vm_zone_t z, vm_object_t obj, char *name, int size,
return 1;
}
+/*
+ * Subroutine same as zinitna, except zone data structure is allocated
+ * automatically by malloc. This routine should normally be used, except
+ * in certain tricky startup conditions in the VM system -- then
+ * zbootinit and zinitna can be used. Zinit is the standard zone
+ * initialization call.
+ */
vm_zone_t
zinit(char *name, int size, int nentries, int flags, int zalloc) {
vm_zone_t z;
@@ -116,7 +143,8 @@ zinit(char *name, int size, int nentries, int flags, int zalloc) {
if (z == NULL)
return NULL;
- if (_zinit(z, NULL, name, size, nentries, flags, zalloc) == 0) {
+ z->zflags = 0;
+ if (zinitna(z, NULL, name, size, nentries, flags, zalloc) == 0) {
free(z, M_ZONE);
return NULL;
}
@@ -124,8 +152,12 @@ zinit(char *name, int size, int nentries, int flags, int zalloc) {
return z;
}
+/*
+ * Initialize a zone before the system is fully up. This routine should
+ * only be called before full VM startup.
+ */
void
-_zbootinit(vm_zone_t z, char *name, int size, void *item, int nitems) {
+zbootinit(vm_zone_t z, char *name, int size, void *item, int nitems) {
int i;
@@ -143,11 +175,14 @@ _zbootinit(vm_zone_t z, char *name, int size, void *item, int nitems) {
for (i = 0; i < nitems; i++) {
* (void **) item = z->zitems;
z->zitems = item;
- ++z->zfreecnt;
(char *) item += z->zsize;
}
+ z->zfreecnt += nitems;
}
+/*
+ * Zone critical region locks.
+ */
static inline int
zlock(vm_zone_t z) {
int s;
@@ -162,13 +197,32 @@ zunlock(vm_zone_t z, int s) {
splx(s);
}
+/*
+ * void *zalloc(vm_zone_t zone) --
+ * Returns an item from a specified zone.
+ *
+ * void zfree(vm_zone_t zone, void *item) --
+ * Frees an item back to a specified zone.
+ *
+ * void *zalloci(vm_zone_t zone) --
+ * Returns an item from a specified zone, interrupt safe.
+ *
+ * void zfreei(vm_zone_t zone, void *item) --
+ * Frees an item back to a specified zone, interrupt safe.
+ *
+ */
+
+/*
+ * Zone allocator/deallocator. These are interrupt / (or potentially SMP)
+ * safe. The raw zalloc/zfree routines are in the vm_zone header file,
+ * and are not interrupt safe, but are fast.
+ */
void *
zalloci(vm_zone_t z) {
int s;
void *item;
-
s = zlock(z);
- item = zalloc(z);
+ item = _zalloc(z);
zunlock(z, s);
return item;
}
@@ -176,21 +230,23 @@ zalloci(vm_zone_t z) {
void
zfreei(vm_zone_t z, void *item) {
int s;
-
s = zlock(z);
- zfree(z, item);
+ _zfree(z, item);
zunlock(z, s);
return;
}
+/*
+ * Internal zone routine. Not to be called from external (non vm_zone) code.
+ */
void *
-zget(vm_zone_t z, int s) {
+_zget(vm_zone_t z) {
int i;
vm_page_t m;
int nitems;
- void *item, *litem;
+ void *item;
- if ((z->zflags & ZONE_WAIT) == 0) {
+ if (z->zflags & ZONE_INTERRUPT) {
item = (char *) z->zkva + z->zpagecount * PAGE_SIZE;
for( i = 0; ((i < z->zalloc) && (z->zpagecount < z->zpagemax)); i++) {
@@ -200,7 +256,7 @@ zget(vm_zone_t z, int s) {
}
pmap_kenter(z->zkva + z->zpagecount * PAGE_SIZE, VM_PAGE_TO_PHYS(m));
- ++z->zpagecount;
+ z->zpagecount++;
}
nitems = (i * PAGE_SIZE) / z->zsize;
} else {
@@ -214,14 +270,22 @@ zget(vm_zone_t z, int s) {
/*
* Save one for immediate allocation
*/
- nitems -= 1;
- for (i = 0; i < nitems; i++) {
- * (void **) item = z->zitems;
- z->zitems = item;
- (char *) item += z->zsize;
- ++z->zfreecnt;
+ if (nitems != 0) {
+ nitems -= 1;
+ for (i = 0; i < nitems; i++) {
+ * (void **) item = z->zitems;
+ z->zitems = item;
+ (char *) item += z->zsize;
+ }
+ z->zfreecnt += nitems;
+ } else if (z->zfreecnt > 0) {
+ item = z->zitems;
+ z->zitems = *(void **) item;
+ z->zfreecnt--;
+ } else {
+ item = NULL;
}
-
+
return item;
}
diff --git a/sys/vm/vm_zone.h b/sys/vm/vm_zone.h
index 7f6630d3cd32e..a7aa802d72cca 100644
--- a/sys/vm/vm_zone.h
+++ b/sys/vm/vm_zone.h
@@ -1,25 +1,43 @@
+/*
+ * Copyright (c) 1997 John S. Dyson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice immediately at the beginning of the file, without modification,
+ * this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Absolutely no warranty of function or purpose is made by the author
+ * John S. Dyson.
+ * 4. This work was done expressly for inclusion into FreeBSD. Other use
+ * is allowed if this notation is included.
+ * 5. Modifications may be freely made to this file if the above conditions
+ * are met.
+ *
+ * $Id$
+ */
+
#if !defined(_SYS_ZONE_H)
#define _SYS_ZONE_H
-#define ZONE_COLOR 1
-#define ZONE_INTERRUPT 2
-#define ZONE_WAIT 4
-#define ZONE_PREALLOCATE 8
-#define ZONE_BOOT 16
+#define ZONE_INTERRUPT 1 /* Use this if you need to allocate at int time */
+#define ZONE_BOOT 16 /* This is an internal flag used by zbootinit */
#include <machine/param.h>
#include <sys/lock.h>
-#define CACHE_LINE_SIZE 32
-
typedef struct vm_zone {
struct simplelock zlock; /* lock for data structure */
void *zitems; /* linked list of items */
- int zfreemin; /* minimum number of free entries */
int zfreecnt; /* free entries */
+ int zfreemin; /* minimum number of free entries */
vm_offset_t zkva; /* Base kva of zone */
int zpagecount; /* Total # of allocated pages */
int zpagemax; /* Max address space */
@@ -33,50 +51,59 @@ typedef struct vm_zone {
vm_zone_t zinit(char *name, int size, int nentries, int flags, int zalloc);
-int _zinit(vm_zone_t z, struct vm_object *obj, char *name, int size,
+int zinitna(vm_zone_t z, struct vm_object *obj, char *name, int size,
int nentries, int flags, int zalloc);
static void * zalloc(vm_zone_t z);
static void zfree(vm_zone_t z, void *item);
void * zalloci(vm_zone_t z) __attribute__((regparm(1)));
void zfreei(vm_zone_t z, void *item) __attribute__((regparm(2)));
-void _zbootinit(vm_zone_t z, char *name, int size, void *item, int nitems) ;
-void * zget(vm_zone_t z, int s) __attribute__((regparm(2)));
-
-#if SMP > 1
-
-static __inline__ void *
-zalloc(vm_zone_t z) {
- return zalloci(z);
-}
-
-static __inline__ void
-zfree(vm_zone_t z, void *item) {
- zfreei(z, item);
-}
-
-#else
+void zbootinit(vm_zone_t z, char *name, int size, void *item, int nitems) ;
+void * _zget(vm_zone_t z) __attribute__((regparm(1)));
+/*
+ * void *zalloc(vm_zone_t zone) --
+ * Returns an item from a specified zone.
+ *
+ * void zfree(vm_zone_t zone, void *item) --
+ * Frees an item back to a specified zone.
+ */
static __inline__ void *
-zalloc(vm_zone_t z) {
- int s;
+_zalloc(vm_zone_t z) {
void *item;
if (z->zfreecnt <= z->zfreemin) {
- return zget(z, s);
+ return _zget(z);
}
item = z->zitems;
z->zitems = *(void **) item;
- --z->zfreecnt;
+ z->zfreecnt--;
return item;
}
static __inline__ void
-zfree(vm_zone_t z, void *item) {
+_zfree(vm_zone_t z, void *item) {
* (void **) item = z->zitems;
z->zitems = item;
- ++z->zfreecnt;
+ z->zfreecnt++;
+}
+
+static __inline__ void *
+zalloc(vm_zone_t z) {
+#if NCPU > 1
+ return zalloci(z);
+#else
+ return _zalloc(z);
+#endif
}
+
+static __inline__ void
+zfree(vm_zone_t z, void *item) {
+#if NCPU > 1
+ zfreei(z, item);
+#else
+ _zfree(z, item);
#endif
+}
#endif