Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 4 Jan 2010 04:26:02 +0000 (UTC)
From:      Kip Macy <kmacy@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r201470 - user/kmacy/releng_8_rump/lib/libunet
Message-ID:  <201001040426.o044Q2dW048977@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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@FreeBSD.org>
+ * Copyright (c) 2004, 2005 Bosko Milekic <bmilekic@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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001040426.o044Q2dW048977>