subr_kobj.c revision 69781
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 69781 2000-12-08 21:51:06Z dwmalone $ 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 8065173Sdfrstatic void 8165173Sdfrkobj_class_compile_common(kobj_class_t cls, kobj_ops_t ops) 8259093Sdfr{ 8359093Sdfr kobj_method_t *m; 8459093Sdfr int i; 8559093Sdfr 8659093Sdfr /* 8759093Sdfr * Don't do anything if we are already compiled. 8859093Sdfr */ 8959093Sdfr if (cls->ops) 9059093Sdfr return; 9159093Sdfr 9259093Sdfr /* 9359093Sdfr * First register any methods which need it. 9459093Sdfr */ 9559093Sdfr for (i = 0, m = cls->methods; m->desc; i++, m++) 9659093Sdfr kobj_register_method(m->desc); 9759093Sdfr 9859093Sdfr /* 9965173Sdfr * Then initialise the ops table. 10059093Sdfr */ 10159093Sdfr bzero(ops, sizeof(struct kobj_ops)); 10259093Sdfr ops->cls = cls; 10359093Sdfr cls->ops = ops; 10459093Sdfr} 10559093Sdfr 10659093Sdfrvoid 10765173Sdfrkobj_class_compile(kobj_class_t cls) 10865173Sdfr{ 10965173Sdfr kobj_ops_t ops; 11065173Sdfr 11165173Sdfr /* 11265173Sdfr * Allocate space for the compiled ops table. 11365173Sdfr */ 11465173Sdfr ops = malloc(sizeof(struct kobj_ops), M_KOBJ, M_NOWAIT); 11565173Sdfr if (!ops) 11665173Sdfr panic("kobj_compile_methods: out of memory"); 11765173Sdfr kobj_class_compile_common(cls, ops); 11865173Sdfr} 11965173Sdfr 12065173Sdfrvoid 12165173Sdfrkobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops) 12265173Sdfr{ 12365173Sdfr /* 12465173Sdfr * Increment refs to make sure that the ops table is not freed. 12565173Sdfr */ 12665173Sdfr cls->refs++; 12765173Sdfr kobj_class_compile_common(cls, ops); 12865173Sdfr} 12965173Sdfr 13065173Sdfrvoid 13159093Sdfrkobj_lookup_method(kobj_method_t *methods, 13259093Sdfr kobj_method_t *ce, 13359093Sdfr kobjop_desc_t desc) 13459093Sdfr{ 13559093Sdfr ce->desc = desc; 13659093Sdfr for (; methods && methods->desc; methods++) { 13759093Sdfr if (methods->desc == desc) { 13859093Sdfr ce->func = methods->func; 13959093Sdfr return; 14059093Sdfr } 14159093Sdfr } 14259093Sdfr if (desc->deflt) 14359093Sdfr ce->func = desc->deflt; 14459093Sdfr else 14559093Sdfr ce->func = kobj_error_method; 14659093Sdfr return; 14759093Sdfr} 14859093Sdfr 14959093Sdfrvoid 15059093Sdfrkobj_class_free(kobj_class_t cls) 15159093Sdfr{ 15259093Sdfr int i; 15359093Sdfr kobj_method_t *m; 15459093Sdfr 15559093Sdfr /* 15659093Sdfr * Unregister any methods which are no longer used. 15759093Sdfr */ 15859093Sdfr for (i = 0, m = cls->methods; m->desc; i++, m++) 15959093Sdfr kobj_unregister_method(m->desc); 16059093Sdfr 16159093Sdfr /* 16259093Sdfr * Free memory and clean up. 16359093Sdfr */ 16459093Sdfr free(cls->ops, M_KOBJ); 16559093Sdfr cls->ops = 0; 16659093Sdfr} 16759093Sdfr 16859093Sdfrkobj_t 16959093Sdfrkobj_create(kobj_class_t cls, 17059093Sdfr struct malloc_type *mtype, 17159093Sdfr int mflags) 17259093Sdfr{ 17359093Sdfr kobj_t obj; 17459093Sdfr 17559093Sdfr /* 17659093Sdfr * Allocate and initialise the new object. 17759093Sdfr */ 17869781Sdwmalone obj = malloc(cls->size, mtype, mflags | M_ZERO); 17959093Sdfr if (!obj) 18059093Sdfr return 0; 18159093Sdfr kobj_init(obj, cls); 18259093Sdfr 18359093Sdfr return obj; 18459093Sdfr} 18559093Sdfr 18659093Sdfrvoid 18759093Sdfrkobj_init(kobj_t obj, kobj_class_t cls) 18859093Sdfr{ 18959093Sdfr /* 19059093Sdfr * Consider compiling the class' method table. 19159093Sdfr */ 19259093Sdfr if (!cls->ops) 19359093Sdfr kobj_class_compile(cls); 19459093Sdfr 19559093Sdfr obj->ops = cls->ops; 19659820Sdfr cls->refs++; 19759093Sdfr} 19859093Sdfr 19959093Sdfrvoid 20059093Sdfrkobj_delete(kobj_t obj, struct malloc_type *mtype) 20159093Sdfr{ 20259093Sdfr kobj_class_t cls = obj->ops->cls; 20359093Sdfr 20459093Sdfr /* 20559093Sdfr * Consider freeing the compiled method table for the class 20659093Sdfr * after its last instance is deleted. As an optimisation, we 20759093Sdfr * should defer this for a short while to avoid thrashing. 20859093Sdfr */ 20959820Sdfr cls->refs--; 21059820Sdfr if (!cls->refs) 21159093Sdfr kobj_class_free(cls); 21259093Sdfr 21359093Sdfr obj->ops = 0; 21459093Sdfr if (mtype) 21559093Sdfr free(obj, mtype); 21659093Sdfr} 217