svn commit: r201470 - user/kmacy/releng_8_rump/lib/libunet
Kip Macy
kmacy at FreeBSD.org
Mon Jan 4 04:26:03 UTC 2010
Author: kmacy
Date: Mon Jan 4 04:26:02 2010
New Revision: 201470
URL: http://svn.freebsd.org/changeset/base/201470
Log:
import zone allocator and further whittle down missing symbols
Added:
user/kmacy/releng_8_rump/lib/libunet/opt_kdtrace.h (contents, props changed)
user/kmacy/releng_8_rump/lib/libunet/opt_sched.h (contents, props changed)
user/kmacy/releng_8_rump/lib/libunet/opt_vm.h (contents, props changed)
user/kmacy/releng_8_rump/lib/libunet/unet_init_main.c (contents, props changed)
user/kmacy/releng_8_rump/lib/libunet/unet_kern_synch.c (contents, props changed)
user/kmacy/releng_8_rump/lib/libunet/unet_uma_core.c (contents, props changed)
Modified:
user/kmacy/releng_8_rump/lib/libunet/Makefile
user/kmacy/releng_8_rump/lib/libunet/unet_compat.c
user/kmacy/releng_8_rump/lib/libunet/unet_glue.c
Modified: user/kmacy/releng_8_rump/lib/libunet/Makefile
==============================================================================
--- user/kmacy/releng_8_rump/lib/libunet/Makefile Mon Jan 4 03:40:46 2010 (r201469)
+++ user/kmacy/releng_8_rump/lib/libunet/Makefile Mon Jan 4 04:26:02 2010 (r201470)
@@ -2,9 +2,9 @@
PREFIX= ${.CURDIR}/../../sys
.PATH: ${PREFIX}/kern
-.PATH: ${PREFIX}/libkern
.PATH: ${PREFIX}/net
.PATH: ${PREFIX}/netinet
+.PATH: ${PREFIX}/libkern
.PATH: ${PREFIX}/dev/random
LIB= unet
@@ -12,7 +12,9 @@ LIB= unet
UNET_KERN_COMMON_OBJS += \
kern_environment.o \
kern_event.o \
+ kern_malloc.o \
kern_mbuf.o \
+ kern_module.o \
kern_subr.o \
kern_sysctl.o \
md5c.o \
@@ -95,7 +97,11 @@ UNET_RANDOM_COMMON_OBJS = \
UNET_GLUE_COMMON_OBJS = \
unet_compat.o \
- unet_glue.o
+ unet_glue.o \
+ unet_init_main.c \
+ unet_uma_core.c \
+ unet_kern_synch.o
+
# unet_init.o \
# unet_uipc_syscalls.o
# unet_sys_generic.o
Added: user/kmacy/releng_8_rump/lib/libunet/opt_kdtrace.h
==============================================================================
Added: user/kmacy/releng_8_rump/lib/libunet/opt_sched.h
==============================================================================
Added: user/kmacy/releng_8_rump/lib/libunet/opt_vm.h
==============================================================================
Modified: user/kmacy/releng_8_rump/lib/libunet/unet_compat.c
==============================================================================
--- user/kmacy/releng_8_rump/lib/libunet/unet_compat.c Mon Jan 4 03:40:46 2010 (r201469)
+++ user/kmacy/releng_8_rump/lib/libunet/unet_compat.c Mon Jan 4 04:26:02 2010 (r201470)
@@ -6,7 +6,7 @@
#include <sys/ucred.h>
struct malloc_type;
-
+#if 0
void *
unet_malloc(unsigned long size, struct malloc_type *type, int flags)
{
@@ -20,7 +20,7 @@ unet_free(void *addr, struct malloc_type
free(addr);
}
-
+#endif
/*
* Claim another reference to a ucred structure.
*/
Modified: user/kmacy/releng_8_rump/lib/libunet/unet_glue.c
==============================================================================
--- user/kmacy/releng_8_rump/lib/libunet/unet_glue.c Mon Jan 4 03:40:46 2010 (r201469)
+++ user/kmacy/releng_8_rump/lib/libunet/unet_glue.c Mon Jan 4 04:26:02 2010 (r201470)
@@ -3,16 +3,24 @@
#include <sys/param.h>
#include <sys/types.h>
#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/event.h>
+#include <sys/jail.h>
#include <sys/limits.h>
#include <sys/malloc.h>
#include <sys/refcount.h>
#include <sys/resourcevar.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
-#include <sys/jail.h>
#include <sys/priv.h>
#include <sys/time.h>
+#include <sys/ucred.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_object.h>
+#include <vm/vm_map.h>
SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW, 0,
"Sysctl internal magic");
@@ -23,9 +31,16 @@ SYSCTL_NODE(, CTL_KERN, kern, CTLFLA
SYSCTL_NODE(, CTL_NET, net, CTLFLAG_RW, 0,
"Network, (see socket.h)");
+SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW, 0,
+ "Virtual memory");
+
MALLOC_DEFINE(M_IOV, "iov", "large iov's");
-MALLOC_DEFINE(M_DEVBUF, "devbuf", "device driver memory");
-MALLOC_DEFINE(M_TEMP, "temp", "misc temporary data buffers");
+
+
+int ticks;
+
+time_t time_second = 1;
+time_t time_uptime = 1;
/* This is used in modules that need to work in both SMP and UP. */
cpumask_t all_cpus;
@@ -37,6 +52,18 @@ int mp_maxcpus = MAXCPU;
volatile int smp_started;
u_int mp_maxid;
+long first_page = 0;
+
+struct vmmeter cnt;
+vm_map_t kernel_map=0;
+vm_map_t kmem_map=0;
+
+struct vm_object kernel_object_store;
+struct vm_object kmem_object_store;
+
+struct filterops fs_filtops;
+struct filterops sig_filtops;
+
int cold;
struct mtx Giant;
@@ -103,6 +130,18 @@ prison_remote_ip4(struct ucred *cred, st
return (0);
}
+
+/*
+ * Return 1 if the passed credential is in a jail and that jail does not
+ * have its own virtual network stack, otherwise 0.
+ */
+int
+jailed_without_vnet(struct ucred *cred)
+{
+
+ return (0);
+}
+
int
priv_check(struct thread *td, int priv)
{
@@ -454,10 +493,124 @@ chgsbsize(uip, hiwat, to, max)
return (1);
}
+
+/*
+ * Return the current (soft) limit for a particular system resource.
+ * The which parameter which specifies the index into the rlimit array
+ */
+rlim_t
+lim_cur(struct proc *p, int which)
+{
+ struct rlimit rl;
+
+ lim_rlimit(p, which, &rl);
+ return (rl.rlim_cur);
+}
+
+/*
+ * Return a copy of the entire rlimit structure for the system limit
+ * specified by 'which' in the rlimit structure pointed to by 'rlp'.
+ */
+void
+lim_rlimit(struct proc *p, int which, struct rlimit *rlp)
+{
+
+#if 0
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ KASSERT(which >= 0 && which < RLIM_NLIMITS,
+ ("request for invalid resource limit"));
+ *rlp = p->p_limit->pl_rlimit[which];
+ if (p->p_sysent->sv_fixlimit != NULL)
+ p->p_sysent->sv_fixlimit(rlp, which);
+#endif
+}
+
int
useracc(void *addr, int len, int rw)
{
return (1);
}
+
+struct proc *
+zpfind(pid_t pid)
+{
+
+ return (NULL);
+}
+
+int
+p_cansee(struct thread *td, struct proc *p)
+{
+
+ return (0);
+}
+
+struct proc *
+pfind(pid_t pid)
+{
+
+ return (NULL);
+}
+
+/*
+ * Fill in a struct xucred based on a struct ucred.
+ */
+void
+cru2x(struct ucred *cr, struct xucred *xcr)
+{
+#if 0
+ int ngroups;
+
+ bzero(xcr, sizeof(*xcr));
+ xcr->cr_version = XUCRED_VERSION;
+ xcr->cr_uid = cr->cr_uid;
+
+ ngroups = MIN(cr->cr_ngroups, XU_NGROUPS);
+ xcr->cr_ngroups = ngroups;
+ bcopy(cr->cr_groups, xcr->cr_groups,
+ ngroups * sizeof(*cr->cr_groups));
+#endif
+}
+
+int
+cr_cansee(struct ucred *u1, struct ucred *u2)
+{
+
+ return (0);
+}
+
+int
+cr_canseeinpcb(struct ucred *cred, struct inpcb *inp)
+{
+
+ return (0);
+}
+
+int
+securelevel_gt(struct ucred *cr, int level)
+{
+
+ return (0);
+}
+
+
+
+
+/**
+ * @brief Send a 'notification' to userland, using standard ways
+ */
+void
+devctl_notify(const char *system, const char *subsystem, const char *type,
+ const char *data)
+{
+ ;
+}
+
+void
+cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
+{
+ ;
+}
+
Added: user/kmacy/releng_8_rump/lib/libunet/unet_init_main.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/kmacy/releng_8_rump/lib/libunet/unet_init_main.c Mon Jan 4 04:26:02 2010 (r201470)
@@ -0,0 +1,273 @@
+/*-
+ * Copyright (c) 1995 Terrence R. Lambert
+ * All rights reserved.
+ *
+ * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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, 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)init_main.c 8.9 (Berkeley) 1/21/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/exec.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/jail.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/sysent.h>
+#include <sys/reboot.h>
+#include <sys/sched.h>
+#include <sys/sx.h>
+#include <sys/sysproto.h>
+#include <sys/vmmeter.h>
+#include <sys/unistd.h>
+#include <sys/malloc.h>
+#include <sys/conf.h>
+#include <sys/cpuset.h>
+
+#include <machine/cpu.h>
+
+#include <security/audit/audit.h>
+#include <security/mac/mac_framework.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <sys/copyright.h>
+
+#include <ddb/ddb.h>
+#include <ddb/db_sym.h>
+
+void mi_startup(void); /* Should be elsewhere */
+
+/* Components of the first process -- never freed. */
+static struct session session0;
+static struct pgrp pgrp0;
+struct proc proc0;
+struct thread thread0 __aligned(16);
+struct vmspace vmspace0;
+struct proc *initproc;
+#if 0
+int boothowto = 0; /* initialized so that it can be patched */
+SYSCTL_INT(_debug, OID_AUTO, boothowto, CTLFLAG_RD, &boothowto, 0, "");
+int bootverbose;
+SYSCTL_INT(_debug, OID_AUTO, bootverbose, CTLFLAG_RW, &bootverbose, 0, "");
+#endif
+/*
+ * This ensures that there is at least one entry so that the sysinit_set
+ * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never
+ * executed.
+ */
+SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL);
+
+/*
+ * The sysinit table itself. Items are checked off as the are run.
+ * If we want to register new sysinit types, add them to newsysinit.
+ */
+SET_DECLARE(sysinit_set, struct sysinit);
+struct sysinit **sysinit, **sysinit_end;
+struct sysinit **newsysinit, **newsysinit_end;
+
+/*
+ * Merge a new sysinit set into the current set, reallocating it if
+ * necessary. This can only be called after malloc is running.
+ */
+void
+sysinit_add(struct sysinit **set, struct sysinit **set_end)
+{
+ struct sysinit **newset;
+ struct sysinit **sipp;
+ struct sysinit **xipp;
+ int count;
+
+ count = set_end - set;
+ if (newsysinit)
+ count += newsysinit_end - newsysinit;
+ else
+ count += sysinit_end - sysinit;
+ newset = malloc(count * sizeof(*sipp), M_TEMP, M_NOWAIT);
+ if (newset == NULL)
+ panic("cannot malloc for sysinit");
+ xipp = newset;
+ if (newsysinit)
+ for (sipp = newsysinit; sipp < newsysinit_end; sipp++)
+ *xipp++ = *sipp;
+ else
+ for (sipp = sysinit; sipp < sysinit_end; sipp++)
+ *xipp++ = *sipp;
+ for (sipp = set; sipp < set_end; sipp++)
+ *xipp++ = *sipp;
+ if (newsysinit)
+ free(newsysinit, M_TEMP);
+ newsysinit = newset;
+ newsysinit_end = newset + count;
+}
+
+/*
+ * System startup; initialize the world, create process 0, mount root
+ * filesystem, and fork to create init and pagedaemon. Most of the
+ * hard work is done in the lower-level initialization routines including
+ * startup(), which does memory initialization and autoconfiguration.
+ *
+ * This allows simple addition of new kernel subsystems that require
+ * boot time initialization. It also allows substitution of subsystem
+ * (for instance, a scheduler, kernel profiler, or VM system) by object
+ * module. Finally, it allows for optional "kernel threads".
+ */
+void
+mi_startup(void)
+{
+
+ register struct sysinit **sipp; /* system initialization*/
+ register struct sysinit **xipp; /* interior loop of sort*/
+ register struct sysinit *save; /* bubble*/
+
+#if defined(VERBOSE_SYSINIT)
+ int last;
+ int verbose;
+#endif
+
+ if (sysinit == NULL) {
+ sysinit = SET_BEGIN(sysinit_set);
+ sysinit_end = SET_LIMIT(sysinit_set);
+ }
+
+restart:
+ /*
+ * Perform a bubble sort of the system initialization objects by
+ * their subsystem (primary key) and order (secondary key).
+ */
+ for (sipp = sysinit; sipp < sysinit_end; sipp++) {
+ for (xipp = sipp + 1; xipp < sysinit_end; xipp++) {
+ if ((*sipp)->subsystem < (*xipp)->subsystem ||
+ ((*sipp)->subsystem == (*xipp)->subsystem &&
+ (*sipp)->order <= (*xipp)->order))
+ continue; /* skip*/
+ save = *sipp;
+ *sipp = *xipp;
+ *xipp = save;
+ }
+ }
+
+#if defined(VERBOSE_SYSINIT)
+ last = SI_SUB_COPYRIGHT;
+ verbose = 0;
+#if !defined(DDB)
+ printf("VERBOSE_SYSINIT: DDB not enabled, symbol lookups disabled.\n");
+#endif
+#endif
+
+ /*
+ * Traverse the (now) ordered list of system initialization tasks.
+ * Perform each task, and continue on to the next task.
+ *
+ * The last item on the list is expected to be the scheduler,
+ * which will not return.
+ */
+ for (sipp = sysinit; sipp < sysinit_end; sipp++) {
+
+ if ((*sipp)->subsystem == SI_SUB_DUMMY)
+ continue; /* skip dummy task(s)*/
+
+ if ((*sipp)->subsystem == SI_SUB_DONE)
+ continue;
+
+#if defined(VERBOSE_SYSINIT)
+ if ((*sipp)->subsystem > last) {
+ verbose = 1;
+ last = (*sipp)->subsystem;
+ printf("subsystem %x\n", last);
+ }
+ if (verbose) {
+#if defined(DDB)
+ const char *name;
+ c_db_sym_t sym;
+ db_expr_t offset;
+
+ sym = db_search_symbol((vm_offset_t)(*sipp)->func,
+ DB_STGY_PROC, &offset);
+ db_symbol_values(sym, &name, NULL);
+ if (name != NULL)
+ printf(" %s(%p)... ", name, (*sipp)->udata);
+ else
+#endif
+ printf(" %p(%p)... ", (*sipp)->func,
+ (*sipp)->udata);
+ }
+#endif
+
+ /* Call function */
+ (*((*sipp)->func))((*sipp)->udata);
+
+#if defined(VERBOSE_SYSINIT)
+ if (verbose)
+ printf("done.\n");
+#endif
+
+ /* Check off the one we're just done */
+ (*sipp)->subsystem = SI_SUB_DONE;
+
+ /* Check if we've installed more sysinit items via KLD */
+ if (newsysinit != NULL) {
+ if (sysinit != SET_BEGIN(sysinit_set))
+ free(sysinit, M_TEMP);
+ sysinit = newsysinit;
+ sysinit_end = newsysinit_end;
+ newsysinit = NULL;
+ newsysinit_end = NULL;
+ goto restart;
+ }
+ }
+
+ panic("Shouldn't get here!");
+ /* NOTREACHED*/
+}
Added: user/kmacy/releng_8_rump/lib/libunet/unet_kern_synch.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/kmacy/releng_8_rump/lib/libunet/unet_kern_synch.c Mon Jan 4 04:26:02 2010 (r201470)
@@ -0,0 +1,53 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_ktrace.h"
+#include "opt_sched.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/condvar.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/sched.h>
+#include <sys/signalvar.h>
+#include <sys/sleepqueue.h>
+#include <sys/smp.h>
+#include <sys/sx.h>
+#include <sys/sysctl.h>
+#include <sys/sysproto.h>
+#include <sys/vmmeter.h>
+#ifdef KTRACE
+#include <sys/uio.h>
+#include <sys/ktrace.h>
+#endif
+
+int hogticks;
+
+/*
+ * General sleep call. Suspends the current thread until a wakeup is
+ * performed on the specified identifier. The thread will then be made
+ * runnable with the specified priority. Sleeps at most timo/hz seconds
+ * (0 means no timeout). If pri includes PCATCH flag, signals are checked
+ * before and after sleeping, else signals are not checked. Returns 0 if
+ * awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a
+ * signal needs to be delivered, ERESTART is returned if the current system
+ * call should be restarted if possible, and EINTR is returned if the system
+ * call should be interrupted by the signal (return EINTR).
+ *
+ * The lock argument is unlocked before the caller is suspended, and
+ * re-locked before _sleep() returns. If priority includes the PDROP
+ * flag the lock is not re-locked before returning.
+ */
+int
+_sleep(void *ident, struct lock_object *lock, int priority,
+ const char *wmesg, int timo)
+{
+
+ panic("");
+}
Added: user/kmacy/releng_8_rump/lib/libunet/unet_uma_core.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/kmacy/releng_8_rump/lib/libunet/unet_uma_core.c Mon Jan 4 04:26:02 2010 (r201470)
@@ -0,0 +1,2809 @@
+/*-
+ * Copyright (c) 2002-2005, 2009 Jeffrey Roberson <jeff at FreeBSD.org>
+ * Copyright (c) 2004, 2005 Bosko Milekic <bmilekic at FreeBSD.org>
+ * Copyright (c) 2004-2006 Robert N. M. Watson
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * uma_core.c Implementation of the Universal Memory allocator
+ *
+ * This allocator is intended to replace the multitude of similar object caches
+ * in the standard FreeBSD kernel. The intent is to be flexible as well as
+ * effecient. A primary design goal is to return unused memory to the rest of
+ * the system. This will make the system as a whole more flexible due to the
+ * ability to move memory to subsystems which most need it instead of leaving
+ * pools of reserved memory unused.
+ *
+ * The basic ideas stem from similar slab/zone based allocators whose algorithms
+ * are well known.
+ *
+ */
+
+/*
+ * TODO:
+ * - Improve memory usage for large allocations
+ * - Investigate cache size adjustments
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* I should really use ktr.. */
+/*
+#define UMA_DEBUG 1
+#define UMA_DEBUG_ALLOC 1
+#define UMA_DEBUG_ALLOC_1 1
+*/
+
+#include "opt_ddb.h"
+#include "opt_param.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/sysctl.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sbuf.h>
+#include <sys/smp.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/uma.h>
+#include <vm/uma_int.h>
+#include <vm/uma_dbg.h>
+
+#include <machine/vmparam.h>
+
+#include <ddb/ddb.h>
+
+#undef UMA_MD_SMALL_ALLOC
+
+/*
+ * This is the zone and keg from which all zones are spawned. The idea is that
+ * even the zone & keg heads are allocated from the allocator, so we use the
+ * bss section to bootstrap us.
+ */
+static struct uma_keg masterkeg;
+static struct uma_zone masterzone_k;
+static struct uma_zone masterzone_z;
+static uma_zone_t kegs = &masterzone_k;
+static uma_zone_t zones = &masterzone_z;
+
+/* This is the zone from which all of uma_slab_t's are allocated. */
+static uma_zone_t slabzone;
+static uma_zone_t slabrefzone; /* With refcounters (for UMA_ZONE_REFCNT) */
+
+/*
+ * The initial hash tables come out of this zone so they can be allocated
+ * prior to malloc coming up.
+ */
+static uma_zone_t hashzone;
+
+/* The boot-time adjusted value for cache line alignment. */
+static int uma_align_cache = 64 - 1;
+
+static MALLOC_DEFINE(M_UMAHASH, "UMAHash", "UMA Hash Buckets");
+
+/*
+ * Are we allowed to allocate buckets?
+ */
+static int bucketdisable = 1;
+
+/* Linked list of all kegs in the system */
+static LIST_HEAD(,uma_keg) uma_kegs = LIST_HEAD_INITIALIZER(&uma_kegs);
+
+/* This mutex protects the keg list */
+static struct mtx uma_mtx;
+
+/* Linked list of boot time pages */
+static LIST_HEAD(,uma_slab) uma_boot_pages =
+ LIST_HEAD_INITIALIZER(&uma_boot_pages);
+
+/* This mutex protects the boot time pages list */
+static struct mtx uma_boot_pages_mtx;
+
+/* Is the VM done starting up? */
+static int booted = 0;
+
+/* Maximum number of allowed items-per-slab if the slab header is OFFPAGE */
+static u_int uma_max_ipers;
+static u_int uma_max_ipers_ref;
+
+/*
+ * This is the handle used to schedule events that need to happen
+ * outside of the allocation fast path.
+ */
+static struct callout uma_callout;
+#define UMA_TIMEOUT 20 /* Seconds for callout interval. */
+
+/*
+ * This structure is passed as the zone ctor arg so that I don't have to create
+ * a special allocation function just for zones.
+ */
+struct uma_zctor_args {
+ char *name;
+ size_t size;
+ uma_ctor ctor;
+ uma_dtor dtor;
+ uma_init uminit;
+ uma_fini fini;
+ uma_keg_t keg;
+ int align;
+ u_int32_t flags;
+};
+
+struct uma_kctor_args {
+ uma_zone_t zone;
+ size_t size;
+ uma_init uminit;
+ uma_fini fini;
+ int align;
+ u_int32_t flags;
+};
+
+struct uma_bucket_zone {
+ uma_zone_t ubz_zone;
+ char *ubz_name;
+ int ubz_entries;
+};
+
+#define BUCKET_MAX 128
+
+struct uma_bucket_zone bucket_zones[] = {
+ { NULL, "16 Bucket", 16 },
+ { NULL, "32 Bucket", 32 },
+ { NULL, "64 Bucket", 64 },
+ { NULL, "128 Bucket", 128 },
+ { NULL, NULL, 0}
+};
+
+#define BUCKET_SHIFT 4
+#define BUCKET_ZONES ((BUCKET_MAX >> BUCKET_SHIFT) + 1)
+
+/*
+ * bucket_size[] maps requested bucket sizes to zones that allocate a bucket
+ * of approximately the right size.
+ */
+static uint8_t bucket_size[BUCKET_ZONES];
+
+/*
+ * Flags and enumerations to be passed to internal functions.
+ */
+enum zfreeskip { SKIP_NONE, SKIP_DTOR, SKIP_FINI };
+
+#define ZFREE_STATFAIL 0x00000001 /* Update zone failure statistic. */
+#define ZFREE_STATFREE 0x00000002 /* Update zone free statistic. */
+
+/* Prototypes.. */
+
+static void *obj_alloc(uma_zone_t, int, u_int8_t *, int);
+static void *page_alloc(uma_zone_t, int, u_int8_t *, int);
+static void *startup_alloc(uma_zone_t, int, u_int8_t *, int);
+static void page_free(void *, int, u_int8_t);
+static uma_slab_t keg_alloc_slab(uma_keg_t, uma_zone_t, int);
+static void cache_drain(uma_zone_t);
+static void bucket_drain(uma_zone_t, uma_bucket_t);
+static void bucket_cache_drain(uma_zone_t zone);
+static int keg_ctor(void *, int, void *, int);
+static void keg_dtor(void *, int, void *);
+static int zone_ctor(void *, int, void *, int);
+static void zone_dtor(void *, int, void *);
+static int zero_init(void *, int, int);
+static void keg_small_init(uma_keg_t keg);
+static void keg_large_init(uma_keg_t keg);
+static void zone_foreach(void (*zfunc)(uma_zone_t));
+static void zone_timeout(uma_zone_t zone);
+static int hash_alloc(struct uma_hash *);
+static int hash_expand(struct uma_hash *, struct uma_hash *);
+static void hash_free(struct uma_hash *hash);
+static void uma_timeout(void *);
+static void uma_startup3(void);
+static void *zone_alloc_item(uma_zone_t, void *, int);
+static void zone_free_item(uma_zone_t, void *, void *, enum zfreeskip,
+ int);
+static void bucket_enable(void);
+static void bucket_init(void);
+static uma_bucket_t bucket_alloc(int, int);
+static void bucket_free(uma_bucket_t);
+static void bucket_zone_drain(void);
+static int zone_alloc_bucket(uma_zone_t zone, int flags);
+static uma_slab_t zone_fetch_slab(uma_zone_t zone, uma_keg_t last, int flags);
+static uma_slab_t zone_fetch_slab_multi(uma_zone_t zone, uma_keg_t last, int flags);
+static void *slab_alloc_item(uma_zone_t zone, uma_slab_t slab);
+static uma_keg_t uma_kcreate(uma_zone_t zone, size_t size, uma_init uminit,
+ uma_fini fini, int align, u_int32_t flags);
+static inline void zone_relock(uma_zone_t zone, uma_keg_t keg);
+static inline void keg_relock(uma_keg_t keg, uma_zone_t zone);
+
+void uma_print_zone(uma_zone_t);
+void uma_print_stats(void);
+static int sysctl_vm_zone_count(SYSCTL_HANDLER_ARGS);
+static int sysctl_vm_zone_stats(SYSCTL_HANDLER_ARGS);
+
+SYSINIT(uma_startup3, SI_SUB_VM_CONF, SI_ORDER_SECOND, uma_startup3, NULL);
+
+SYSCTL_PROC(_vm, OID_AUTO, zone_count, CTLFLAG_RD|CTLTYPE_INT,
+ 0, 0, sysctl_vm_zone_count, "I", "Number of UMA zones");
+
+SYSCTL_PROC(_vm, OID_AUTO, zone_stats, CTLFLAG_RD|CTLTYPE_STRUCT,
+ 0, 0, sysctl_vm_zone_stats, "s,struct uma_type_header", "Zone Stats");
+
+/*
+ * This routine checks to see whether or not it's safe to enable buckets.
+ */
+
+static void
+bucket_enable(void)
+{
+ if (cnt.v_free_count < cnt.v_free_min)
+ bucketdisable = 1;
+ else
+ bucketdisable = 0;
+}
+
+/*
+ * Initialize bucket_zones, the array of zones of buckets of various sizes.
+ *
+ * For each zone, calculate the memory required for each bucket, consisting
+ * of the header and an array of pointers. Initialize bucket_size[] to point
+ * the range of appropriate bucket sizes at the zone.
+ */
+static void
+bucket_init(void)
+{
+ struct uma_bucket_zone *ubz;
+ int i;
+ int j;
+
+ for (i = 0, j = 0; bucket_zones[j].ubz_entries != 0; j++) {
+ int size;
+
+ ubz = &bucket_zones[j];
+ size = roundup(sizeof(struct uma_bucket), sizeof(void *));
+ size += sizeof(void *) * ubz->ubz_entries;
+ ubz->ubz_zone = uma_zcreate(ubz->ubz_name, size,
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,
+ UMA_ZFLAG_INTERNAL | UMA_ZFLAG_BUCKET);
+ for (; i <= ubz->ubz_entries; i += (1 << BUCKET_SHIFT))
+ bucket_size[i >> BUCKET_SHIFT] = j;
+ }
+}
+
+/*
+ * Given a desired number of entries for a bucket, return the zone from which
+ * to allocate the bucket.
+ */
+static struct uma_bucket_zone *
+bucket_zone_lookup(int entries)
+{
+ int idx;
+
+ idx = howmany(entries, 1 << BUCKET_SHIFT);
+ return (&bucket_zones[bucket_size[idx]]);
+}
+
+static uma_bucket_t
+bucket_alloc(int entries, int bflags)
+{
+ struct uma_bucket_zone *ubz;
+ uma_bucket_t bucket;
+
+ /*
+ * This is to stop us from allocating per cpu buckets while we're
+ * running out of vm.boot_pages. Otherwise, we would exhaust the
+ * boot pages. This also prevents us from allocating buckets in
+ * low memory situations.
+ */
+ if (bucketdisable)
+ return (NULL);
+
+ ubz = bucket_zone_lookup(entries);
+ bucket = zone_alloc_item(ubz->ubz_zone, NULL, bflags);
+ if (bucket) {
+#ifdef INVARIANTS
+ bzero(bucket->ub_bucket, sizeof(void *) * ubz->ubz_entries);
+#endif
+ bucket->ub_cnt = 0;
+ bucket->ub_entries = ubz->ubz_entries;
+ }
+
+ return (bucket);
+}
+
+static void
+bucket_free(uma_bucket_t bucket)
+{
+ struct uma_bucket_zone *ubz;
+
+ ubz = bucket_zone_lookup(bucket->ub_entries);
+ zone_free_item(ubz->ubz_zone, bucket, NULL, SKIP_NONE,
+ ZFREE_STATFREE);
+}
+
+static void
+bucket_zone_drain(void)
+{
+ struct uma_bucket_zone *ubz;
+
+ for (ubz = &bucket_zones[0]; ubz->ubz_entries != 0; ubz++)
+ zone_drain(ubz->ubz_zone);
+}
+
+static inline uma_keg_t
+zone_first_keg(uma_zone_t zone)
+{
+
+ return (LIST_FIRST(&zone->uz_kegs)->kl_keg);
+}
+
+static void
+zone_foreach_keg(uma_zone_t zone, void (*kegfn)(uma_keg_t))
+{
+ uma_klink_t klink;
+
+ LIST_FOREACH(klink, &zone->uz_kegs, kl_link)
+ kegfn(klink->kl_keg);
+}
+
+/*
+ * Routine called by timeout which is used to fire off some time interval
+ * based calculations. (stats, hash size, etc.)
+ *
+ * Arguments:
+ * arg Unused
+ *
+ * Returns:
+ * Nothing
+ */
+static void
+uma_timeout(void *unused)
+{
+ bucket_enable();
+ zone_foreach(zone_timeout);
+
+ /* Reschedule this event */
+ callout_reset(&uma_callout, UMA_TIMEOUT * hz, uma_timeout, NULL);
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-user
mailing list