subr_kobj.c revision 59820
159093Sdfr/*- 259093Sdfr * Copyright (c) 2000 Doug Rabson 359093Sdfr * All rights reserved. 459093Sdfr * 559093Sdfr * Redistribution and use in source and binary forms, with or without 659093Sdfr * modification, are permitted provided that the following conditions 759093Sdfr * are met: 859093Sdfr * 1. Redistributions of source code must retain the above copyright 959093Sdfr * notice, this list of conditions and the following disclaimer. 1059093Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1159093Sdfr * notice, this list of conditions and the following disclaimer in the 1259093Sdfr * documentation and/or other materials provided with the distribution. 1359093Sdfr * 1459093Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1559093Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1659093Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1759093Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1859093Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1959093Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2059093Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2159093Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2259093Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2359093Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2459093Sdfr * SUCH DAMAGE. 2559093Sdfr * 2659093Sdfr * $FreeBSD: head/sys/kern/subr_kobj.c 59820 2000-05-01 10:45:15Z dfr $ 2759093Sdfr */ 2859093Sdfr 2959093Sdfr#include <sys/param.h> 3059093Sdfr#include <sys/queue.h> 3159093Sdfr#include <sys/malloc.h> 3259093Sdfr#include <sys/kernel.h> 3359093Sdfr#include <sys/module.h> 3459093Sdfr#include <sys/errno.h> 3559093Sdfr#ifndef TEST 3659093Sdfr#include <sys/systm.h> 3759093Sdfr#endif 3859093Sdfr#include <sys/kobj.h> 3959093Sdfr 4059093Sdfr#ifdef TEST 4159093Sdfr#include "usertest.h" 4259093Sdfr#endif 4359093Sdfr 4459093Sdfrstatic MALLOC_DEFINE(M_KOBJ, "kobj", "Kernel object structures"); 4559093Sdfr 4659093Sdfr#ifdef KOBJ_STATS 4759093Sdfr 4859093Sdfr#include <sys/sysctl.h> 4959093Sdfr 5059093Sdfrint kobj_lookup_hits; 5159093Sdfrint kobj_lookup_misses; 5259093Sdfr 5359093SdfrSYSCTL_INT(_kern, OID_AUTO, kobj_hits, CTLFLAG_RD, 5459093Sdfr &kobj_lookup_hits, 0, "") 5559093SdfrSYSCTL_INT(_kern, OID_AUTO, kobj_misses, CTLFLAG_RD, 5659093Sdfr &kobj_lookup_misses, 0, "") 5759093Sdfr 5859093Sdfr#endif 5959093Sdfr 6059093Sdfrstatic int kobj_next_id = 1; 6159093Sdfr 6259093Sdfrstatic int 6359093Sdfrkobj_error_method(void) 6459093Sdfr{ 6559093Sdfr return ENXIO; 6659093Sdfr} 6759093Sdfr 6859093Sdfrstatic void 6959093Sdfrkobj_register_method(struct kobjop_desc *desc) 7059093Sdfr{ 7159093Sdfr if (desc->id == 0) 7259093Sdfr desc->id = kobj_next_id++; 7359093Sdfr} 7459093Sdfr 7559093Sdfrstatic void 7659093Sdfrkobj_unregister_method(struct kobjop_desc *desc) 7759093Sdfr{ 7859093Sdfr} 7959093Sdfr 8059093Sdfrvoid 8159093Sdfrkobj_class_compile(kobj_class_t cls) 8259093Sdfr{ 8359093Sdfr kobj_ops_t ops; 8459093Sdfr kobj_method_t *m; 8559093Sdfr int i; 8659093Sdfr 8759093Sdfr /* 8859093Sdfr * Don't do anything if we are already compiled. 8959093Sdfr */ 9059093Sdfr if (cls->ops) 9159093Sdfr return; 9259093Sdfr 9359093Sdfr /* 9459093Sdfr * First register any methods which need it. 9559093Sdfr */ 9659093Sdfr for (i = 0, m = cls->methods; m->desc; i++, m++) 9759093Sdfr kobj_register_method(m->desc); 9859093Sdfr 9959093Sdfr /* 10059093Sdfr * Then allocate the compiled op table. 10159093Sdfr */ 10259093Sdfr ops = malloc(sizeof(struct kobj_ops), M_KOBJ, M_NOWAIT); 10359093Sdfr if (!ops) 10459093Sdfr panic("kobj_compile_methods: out of memory"); 10559093Sdfr bzero(ops, sizeof(struct kobj_ops)); 10659093Sdfr ops->cls = cls; 10759093Sdfr cls->ops = ops; 10859093Sdfr} 10959093Sdfr 11059093Sdfrvoid 11159093Sdfrkobj_lookup_method(kobj_method_t *methods, 11259093Sdfr kobj_method_t *ce, 11359093Sdfr kobjop_desc_t desc) 11459093Sdfr{ 11559093Sdfr ce->desc = desc; 11659093Sdfr for (; methods && methods->desc; methods++) { 11759093Sdfr if (methods->desc == desc) { 11859093Sdfr ce->func = methods->func; 11959093Sdfr return; 12059093Sdfr } 12159093Sdfr } 12259093Sdfr if (desc->deflt) 12359093Sdfr ce->func = desc->deflt; 12459093Sdfr else 12559093Sdfr ce->func = kobj_error_method; 12659093Sdfr return; 12759093Sdfr} 12859093Sdfr 12959093Sdfrvoid 13059093Sdfrkobj_class_free(kobj_class_t cls) 13159093Sdfr{ 13259093Sdfr int i; 13359093Sdfr kobj_method_t *m; 13459093Sdfr 13559093Sdfr /* 13659093Sdfr * Unregister any methods which are no longer used. 13759093Sdfr */ 13859093Sdfr for (i = 0, m = cls->methods; m->desc; i++, m++) 13959093Sdfr kobj_unregister_method(m->desc); 14059093Sdfr 14159093Sdfr /* 14259093Sdfr * Free memory and clean up. 14359093Sdfr */ 14459093Sdfr free(cls->ops, M_KOBJ); 14559093Sdfr cls->ops = 0; 14659093Sdfr} 14759093Sdfr 14859093Sdfrkobj_t 14959093Sdfrkobj_create(kobj_class_t cls, 15059093Sdfr struct malloc_type *mtype, 15159093Sdfr int mflags) 15259093Sdfr{ 15359093Sdfr kobj_t obj; 15459093Sdfr 15559093Sdfr /* 15659093Sdfr * Allocate and initialise the new object. 15759093Sdfr */ 15859093Sdfr obj = malloc(cls->size, mtype, mflags); 15959093Sdfr if (!obj) 16059093Sdfr return 0; 16159093Sdfr bzero(obj, cls->size); 16259093Sdfr kobj_init(obj, cls); 16359093Sdfr 16459093Sdfr return obj; 16559093Sdfr} 16659093Sdfr 16759093Sdfrvoid 16859093Sdfrkobj_init(kobj_t obj, kobj_class_t cls) 16959093Sdfr{ 17059093Sdfr /* 17159093Sdfr * Consider compiling the class' method table. 17259093Sdfr */ 17359093Sdfr if (!cls->ops) 17459093Sdfr kobj_class_compile(cls); 17559093Sdfr 17659093Sdfr obj->ops = cls->ops; 17759820Sdfr cls->refs++; 17859093Sdfr} 17959093Sdfr 18059093Sdfrvoid 18159093Sdfrkobj_delete(kobj_t obj, struct malloc_type *mtype) 18259093Sdfr{ 18359093Sdfr kobj_class_t cls = obj->ops->cls; 18459093Sdfr 18559093Sdfr /* 18659093Sdfr * Consider freeing the compiled method table for the class 18759093Sdfr * after its last instance is deleted. As an optimisation, we 18859093Sdfr * should defer this for a short while to avoid thrashing. 18959093Sdfr */ 19059820Sdfr cls->refs--; 19159820Sdfr if (!cls->refs) 19259093Sdfr kobj_class_free(cls); 19359093Sdfr 19459093Sdfr obj->ops = 0; 19559093Sdfr if (mtype) 19659093Sdfr free(obj, mtype); 19759093Sdfr} 198