summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/vm/vm_zone.c579
-rw-r--r--sys/vm/vm_zone.h52
2 files changed, 0 insertions, 631 deletions
diff --git a/sys/vm/vm_zone.c b/sys/vm/vm_zone.c
deleted file mode 100644
index 31ec81cabcdc..000000000000
--- a/sys/vm/vm_zone.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * Copyright (c) 1997, 1998 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. Absolutely no warranty of function or purpose is made by the author
- * John S. Dyson.
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/proc.h>
-#include <sys/mutex.h>
-#include <sys/queue.h>
-#include <sys/sysctl.h>
-#include <sys/vmmeter.h>
-
-#include <vm/vm.h>
-#include <vm/vm_object.h>
-#include <vm/vm_page.h>
-#include <vm/vm_param.h>
-#include <vm/vm_map.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_zone.h>
-
-static MALLOC_DEFINE(M_ZONE, "ZONE", "Zone header");
-
-#define ZENTRY_FREE (void*)0x12342378
-
-#define ZONE_ROUNDING 32
-
-/*
- * This file comprises a very simple zone allocator. This is used
- * in lieu of the malloc allocator, where needed or more optimal.
- *
- * Note that the initial implementation of this had coloring, and
- * absolutely no improvement (actually perf degradation) occurred.
- *
- * Note also that the zones are type stable. The only restriction is
- * that the first two longwords of a data structure can be changed
- * between allocations. Any data that must be stable between allocations
- * must reside in areas after the first two longwords.
- *
- * zinitna, zinit, zbootinit are the initialization routines.
- * zalloc, zfree, are the allocation/free routines.
- */
-
-/*
- * Subsystem lock. Never grab it while holding a zone lock.
- */
-static struct mtx zone_mtx;
-
-/*
- * Singly-linked list of zones, for book-keeping purposes
- */
-static SLIST_HEAD(vm_zone_list, vm_zone) zlist;
-
-/*
- * Statistics
- */
-static int zone_kmem_pages; /* Number of interrupt-safe pages allocated */
-static int zone_kern_pages; /* Number of KVA pages allocated */
-static int zone_kmem_kvaspace; /* Number of non-intsafe pages allocated */
-
-/*
- * Subsystem initialization, called from vm_mem_init()
- */
-void
-vm_zone_init(void)
-{
- mtx_init(&zone_mtx, "zone subsystem", NULL, MTX_DEF);
- SLIST_INIT(&zlist);
-}
-
-void
-vm_zone_init2(void)
-{
- /*
- * LATER: traverse zlist looking for partially initialized
- * LATER: zones and finish initializing them.
- */
-}
-
-/*
- * 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
-zinitna(vm_zone_t z, vm_object_t obj, char *name, int size,
- int nentries, int flags, int zalloc)
-{
- int totsize, oldzflags;
-
- GIANT_REQUIRED;
-
- oldzflags = z->zflags;
- if ((z->zflags & ZONE_BOOT) == 0) {
- z->zsize = (size + ZONE_ROUNDING - 1) & ~(ZONE_ROUNDING - 1);
- z->zfreecnt = 0;
- z->ztotal = 0;
- z->zmax = 0;
- z->zname = name;
- z->znalloc = 0;
- z->zitems = NULL;
- }
-
- z->zflags |= flags;
-
- /*
- * If we cannot wait, allocate KVA space up front, and we will fill
- * in pages as needed.
- */
- if (z->zflags & ZONE_INTERRUPT) {
- totsize = round_page(z->zsize * nentries);
- atomic_add_int(&zone_kmem_kvaspace, totsize);
- z->zkva = kmem_alloc_pageable(kernel_map, totsize);
- if (z->zkva == 0)
- return 0;
-
- z->zpagemax = totsize / PAGE_SIZE;
- if (obj == NULL) {
- z->zobj = vm_object_allocate(OBJT_DEFAULT, z->zpagemax);
- } else {
- z->zobj = obj;
- _vm_object_allocate(OBJT_DEFAULT, z->zpagemax, obj);
- }
- z->zallocflag = VM_ALLOC_INTERRUPT;
- z->zmax += nentries;
- } else {
- z->zallocflag = VM_ALLOC_SYSTEM;
- z->zmax = 0;
- }
-
-
- if (z->zsize > PAGE_SIZE)
- z->zfreemin = 1;
- else
- z->zfreemin = PAGE_SIZE / z->zsize;
-
- z->zpagecount = 0;
- if (zalloc)
- z->zalloc = zalloc;
- else
- z->zalloc = 1;
-
- /* our zone is good and ready, add it to the list */
- if ((z->zflags & ZONE_BOOT) == 0) {
- mtx_init(&(z)->zmtx, "zone", NULL, MTX_DEF);
- mtx_lock(&zone_mtx);
- SLIST_INSERT_HEAD(&zlist, z, zent);
- mtx_unlock(&zone_mtx);
- }
-
- 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;
-
- z = (vm_zone_t) malloc(sizeof (struct vm_zone), M_ZONE, M_NOWAIT | M_ZERO);
- if (z == NULL)
- return NULL;
-
- if (zinitna(z, NULL, name, size, nentries, flags, zalloc) == 0) {
- free(z, M_ZONE);
- return NULL;
- }
-
- return z;
-}
-
-/*
- * Initialize a zone before the system is fully up.
- *
- * We can't rely on being able to allocate items dynamically, so we
- * kickstart the zone with a number of static items provided by the
- * caller.
- *
- * This routine should only be called before full VM startup.
- */
-void
-zbootinit(vm_zone_t z, char *name, int size, void *item, int nitems)
-{
- int i;
-
- z->zname = name;
- z->zsize = size;
- z->zpagemax = 0;
- z->zobj = NULL;
- z->zflags = ZONE_BOOT;
- z->zfreemin = 0;
- z->zallocflag = 0;
- z->zpagecount = 0;
- z->zalloc = 0;
- z->znalloc = 0;
- mtx_init(&(z)->zmtx, "zone", NULL, MTX_DEF);
-
- bzero(item, nitems * z->zsize);
- z->zitems = NULL;
- for (i = 0; i < nitems; i++) {
- ((void **) item)[0] = z->zitems;
-#ifdef INVARIANTS
- ((void **) item)[1] = ZENTRY_FREE;
-#endif
- z->zitems = item;
- (char *) item += z->zsize;
- }
- z->zfreecnt = nitems;
- z->zmax = nitems;
- z->ztotal = nitems;
-
- mtx_lock(&zone_mtx);
- SLIST_INSERT_HEAD(&zlist, z, zent);
- mtx_unlock(&zone_mtx);
-}
-
-/*
- * Destroy a zone, freeing the allocated memory.
- * This does not do any locking for the zone; make sure it is not used
- * any more before calling. All zalloc()'ated memory in the zone must have
- * been zfree()'d.
- * zdestroy() may not be used with zbootinit()'ed zones.
- */
-void
-zdestroy(vm_zone_t z)
-{
- int i, nitems, nbytes;
- void *item, *min, **itp;
- vm_map_t map;
- vm_map_entry_t entry;
- vm_object_t obj;
- vm_pindex_t pindex;
- vm_prot_t prot;
- boolean_t wired;
-
- GIANT_REQUIRED;
- KASSERT(z != NULL, ("invalid zone"));
- /*
- * This is needed, or the algorithm used for non-interrupt zones will
- * blow up badly.
- */
- KASSERT(z->ztotal == z->zfreecnt,
- ("zdestroy() used with an active zone"));
- KASSERT((z->zflags & ZONE_BOOT) == 0,
- ("zdestroy() used with a zbootinit()'ed zone"));
-
- if (z->zflags & ZONE_INTERRUPT) {
- kmem_free(kernel_map, z->zkva, z->zpagemax * PAGE_SIZE);
- vm_object_deallocate(z->zobj);
- atomic_subtract_int(&zone_kmem_kvaspace,
- z->zpagemax * PAGE_SIZE);
- atomic_subtract_int(&zone_kmem_pages,
- z->zpagecount);
- cnt.v_wire_count -= z->zpagecount;
- } else {
- /*
- * This is evil h0h0 magic:
- * The items may be in z->zitems in a random oder; we have to
- * free the start of an allocated area, but do not want to save
- * extra information. Additionally, we may not access items that
- * were in a freed area.
- * This is achieved in the following way: the smallest address
- * is selected, and, after removing all items that are in a
- * range of z->zalloc * PAGE_SIZE (one allocation unit) from
- * it, kmem_free is called on it (since it is the smallest one,
- * it must be the start of an area). This is repeated until all
- * items are gone.
- */
- nbytes = z->zalloc * PAGE_SIZE;
- nitems = nbytes / z->zsize;
- while (z->zitems != NULL) {
- /* Find minimal element. */
- item = min = z->zitems;
- while (item != NULL) {
- if (item < min)
- min = item;
- item = ((void **)item)[0];
- }
- /* Free. */
- itp = &z->zitems;
- i = 0;
- while (*itp != NULL && i < nitems) {
- if ((char *)*itp >= (char *)min &&
- (char *)*itp < (char *)min + nbytes) {
- *itp = ((void **)*itp)[0];
- i++;
- } else
- itp = &((void **)*itp)[0];
- }
- KASSERT(i == nitems, ("zdestroy(): corrupt zone"));
- /*
- * We can allocate from kmem_map (kmem_malloc) or
- * kernel_map (kmem_alloc).
- * kmem_map is a submap of kernel_map, so we can use
- * vm_map_lookup to retrieve the map we need to use.
- */
- map = kernel_map;
- if (vm_map_lookup(&map, (vm_offset_t)min, VM_PROT_NONE,
- &entry, &obj, &pindex, &prot, &wired) !=
- KERN_SUCCESS)
- panic("zalloc mapping lost");
- /* Need to unlock. */
- vm_map_lookup_done(map, entry);
- if (map == kmem_map) {
- atomic_subtract_int(&zone_kmem_pages,
- z->zalloc);
- } else if (map == kernel_map) {
- atomic_subtract_int(&zone_kern_pages,
- z->zalloc);
- } else
- panic("zdestroy(): bad map");
- kmem_free(map, (vm_offset_t)min, nbytes);
- }
- }
-
- mtx_lock(&zone_mtx);
- SLIST_REMOVE(&zlist, z, vm_zone, zent);
- mtx_unlock(&zone_mtx);
- mtx_destroy(&z->zmtx);
- free(z, M_ZONE);
-}
-
-/*
- * Grow the specified zone to accomodate more items.
- */
-static void *
-_zget(vm_zone_t z)
-{
- int i;
- vm_page_t m;
- int nitems, nbytes;
- void *item;
-
- KASSERT(z != NULL, ("invalid zone"));
-
- if (z->zflags & ZONE_INTERRUPT) {
- nbytes = z->zpagecount * PAGE_SIZE;
- nbytes -= nbytes % z->zsize;
- item = (char *) z->zkva + nbytes;
- for (i = 0; ((i < z->zalloc) && (z->zpagecount < z->zpagemax));
- i++) {
- vm_offset_t zkva;
-
- m = vm_page_alloc(z->zobj, z->zpagecount,
- z->zallocflag);
- if (m == NULL)
- break;
-
- zkva = z->zkva + z->zpagecount * PAGE_SIZE;
- pmap_qenter(zkva, &m, 1);
- bzero((caddr_t) zkva, PAGE_SIZE);
- z->zpagecount++;
- atomic_add_int(&zone_kmem_pages, 1);
- cnt.v_wire_count++;
- }
- nitems = ((z->zpagecount * PAGE_SIZE) - nbytes) / z->zsize;
- } else {
- /* Please check zdestroy() when changing this! */
- nbytes = z->zalloc * PAGE_SIZE;
-
- /*
- * Check to see if the kernel map is already locked. We could allow
- * for recursive locks, but that eliminates a valuable debugging
- * mechanism, and opens up the kernel map for potential corruption
- * by inconsistent data structure manipulation. We could also use
- * the interrupt allocation mechanism, but that has size limitations.
- * Luckily, we have kmem_map that is a submap of kernel map available
- * for memory allocation, and manipulation of that map doesn't affect
- * the kernel map structures themselves.
- *
- * We can wait, so just do normal map allocation in the appropriate
- * map.
- */
- mtx_unlock(&z->zmtx);
- if (lockstatus(&kernel_map->lock, NULL)) {
- item = (void *) kmem_malloc(kmem_map, nbytes, M_WAITOK);
- if (item != NULL)
- atomic_add_int(&zone_kmem_pages, z->zalloc);
- } else {
- item = (void *) kmem_alloc(kernel_map, nbytes);
- if (item != NULL)
- atomic_add_int(&zone_kern_pages, z->zalloc);
- }
- if (item != NULL) {
- bzero(item, nbytes);
- } else {
- nbytes = 0;
- }
- nitems = nbytes / z->zsize;
- mtx_lock(&z->zmtx);
- }
- z->ztotal += nitems;
-
- /*
- * Save one for immediate allocation
- */
- if (nitems != 0) {
- nitems -= 1;
- for (i = 0; i < nitems; i++) {
- ((void **) item)[0] = z->zitems;
-#ifdef INVARIANTS
- ((void **) item)[1] = ZENTRY_FREE;
-#endif
- z->zitems = item;
- (char *) item += z->zsize;
- }
- z->zfreecnt += nitems;
- z->znalloc++;
- } else if (z->zfreecnt > 0) {
- item = z->zitems;
- z->zitems = ((void **) item)[0];
-#ifdef INVARIANTS
- KASSERT(((void **) item)[1] == ZENTRY_FREE,
- ("item is not free"));
- ((void **) item)[1] = 0;
-#endif
- z->zfreecnt--;
- z->znalloc++;
- } else {
- item = NULL;
- }
-
- mtx_assert(&z->zmtx, MA_OWNED);
- return item;
-}
-
-/*
- * Allocates an item from the specified zone.
- */
-void *
-zalloc(vm_zone_t z)
-{
- void *item;
-
- KASSERT(z != NULL, ("invalid zone"));
- mtx_lock(&z->zmtx);
-
- if (z->zfreecnt <= z->zfreemin) {
- item = _zget(z);
- goto out;
- }
-
- item = z->zitems;
- z->zitems = ((void **) item)[0];
-#ifdef INVARIANTS
- KASSERT(((void **) item)[1] == ZENTRY_FREE,
- ("item is not free"));
- ((void **) item)[1] = 0;
-#endif
-
- z->zfreecnt--;
- z->znalloc++;
-
-out:
- mtx_unlock(&z->zmtx);
- return item;
-}
-
-/*
- * Frees an item back to the specified zone.
- */
-void
-zfree(vm_zone_t z, void *item)
-{
- KASSERT(z != NULL, ("invalid zone"));
- KASSERT(item != NULL, ("invalid item"));
- mtx_lock(&z->zmtx);
-
- ((void **) item)[0] = z->zitems;
-#ifdef INVARIANTS
- KASSERT(((void **) item)[1] != ZENTRY_FREE,
- ("item is already free"));
- ((void **) item)[1] = (void *) ZENTRY_FREE;
-#endif
- z->zitems = item;
- z->zfreecnt++;
-
- mtx_unlock(&z->zmtx);
-}
-
-/*
- * Sysctl handler for vm.zone
- */
-static int
-sysctl_vm_zone(SYSCTL_HANDLER_ARGS)
-{
- int error, len, cnt;
- const int linesize = 128; /* conservative */
- char *tmpbuf, *offset;
- vm_zone_t z;
- char *p;
-
- cnt = 0;
- mtx_lock(&zone_mtx);
- SLIST_FOREACH(z, &zlist, zent)
- cnt++;
- mtx_unlock(&zone_mtx);
- MALLOC(tmpbuf, char *, (cnt == 0 ? 1 : cnt) * linesize,
- M_TEMP, M_WAITOK);
- len = snprintf(tmpbuf, linesize,
- "\nITEM SIZE LIMIT USED FREE REQUESTS\n\n");
- if (cnt == 0)
- tmpbuf[len - 1] = '\0';
- error = SYSCTL_OUT(req, tmpbuf, cnt == 0 ? len-1 : len);
- if (error || cnt == 0)
- goto out;
- offset = tmpbuf;
- mtx_lock(&zone_mtx);
- SLIST_FOREACH(z, &zlist, zent) {
- if (cnt == 0) /* list may have changed size */
- break;
- mtx_lock(&z->zmtx);
- len = snprintf(offset, linesize,
- "%-12.12s %6.6u, %8.8u, %6.6u, %6.6u, %8.8u\n",
- z->zname, z->zsize, z->zmax, (z->ztotal - z->zfreecnt),
- z->zfreecnt, z->znalloc);
- mtx_unlock(&z->zmtx);
- for (p = offset + 12; p > offset && *p == ' '; --p)
- /* nothing */ ;
- p[1] = ':';
- cnt--;
- offset += len;
- }
- mtx_unlock(&zone_mtx);
- *offset++ = '\0';
- error = SYSCTL_OUT(req, tmpbuf, offset - tmpbuf);
-out:
- FREE(tmpbuf, M_TEMP);
- return (error);
-}
-
-SYSCTL_OID(_vm, OID_AUTO, zone, CTLTYPE_STRING|CTLFLAG_RD,
- NULL, 0, sysctl_vm_zone, "A", "Zone Info");
-
-SYSCTL_INT(_vm, OID_AUTO, zone_kmem_pages, CTLFLAG_RD, &zone_kmem_pages, 0,
- "Number of interrupt safe pages allocated by zone");
-SYSCTL_INT(_vm, OID_AUTO, zone_kmem_kvaspace, CTLFLAG_RD, &zone_kmem_kvaspace, 0,
- "KVA space allocated by zone");
-SYSCTL_INT(_vm, OID_AUTO, zone_kern_pages, CTLFLAG_RD, &zone_kern_pages, 0,
- "Number of non-interrupt safe pages allocated by zone");
diff --git a/sys/vm/vm_zone.h b/sys/vm/vm_zone.h
deleted file mode 100644
index a355051a362a..000000000000
--- a/sys/vm/vm_zone.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 1997, 1998 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. Absolutely no warranty of function or purpose is made by the author
- * John S. Dyson.
- *
- * $FreeBSD$
- */
-
-#ifndef _SYS_ZONE_H
-
-#define _SYS_ZONE_H
-
-#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 <sys/_lock.h>
-#include <sys/_mutex.h>
-#include <vm/uma.h>
-
-typedef uma_zone_t vm_zone_t;
-
-#if 0
-static void vm_zone_init(void);
-static void vm_zone_init2(void);
-
-static vm_zone_t zinit(char *name, int size, int nentries,
- int flags, int zalloc);
-int zinitna(vm_zone_t z, struct vm_object *obj, char *name,
- int size, int nentries, int flags, int zalloc);
-void zbootinit(vm_zone_t z, char *name, int size,
- void *item, int nitems);
-static void zdestroy(vm_zone_t z);
-static void *zalloc(vm_zone_t z);
-static void zfree(vm_zone_t z, void *item);
-#endif
-
-#define vm_zone_init2() uma_startup2()
-
-#define zinit(name, size, nentries, flags, zalloc) \
- uma_zcreate((name), (size), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE)
-#define zdestroy()
-#define zalloc(z) uma_zalloc((z), M_WAITOK)
-#define zfree(z, item) uma_zfree((z), (item))
-#endif /* _SYS_ZONE_H */