diff options
| author | John Dyson <dyson@FreeBSD.org> | 1997-08-05 22:24:31 +0000 |
|---|---|---|
| committer | John Dyson <dyson@FreeBSD.org> | 1997-08-05 22:24:31 +0000 |
| commit | 0d65e566b9205b394757258c5ffc34d8b64e0998 (patch) | |
| tree | 15a797f5e4c2280a999b7e900fa3f40ce4b824e2 /sys/vm | |
| parent | b79933ebfae10dd578fbb7bf77dfe50d766ff7c8 (diff) | |
Notes
Diffstat (limited to 'sys/vm')
| -rw-r--r-- | sys/vm/vm_map.c | 18 | ||||
| -rw-r--r-- | sys/vm/vm_zone.c | 134 | ||||
| -rw-r--r-- | sys/vm/vm_zone.h | 89 |
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 |
