subr_kobj.c revision 116182
11849Swollman/*- 21849Swollman * Copyright (c) 2000 Doug Rabson 31849Swollman * All rights reserved. 41849Swollman * 51849Swollman * Redistribution and use in source and binary forms, with or without 61849Swollman * modification, are permitted provided that the following conditions 71849Swollman * are met: 81849Swollman * 1. Redistributions of source code must retain the above copyright 91849Swollman * notice, this list of conditions and the following disclaimer. 101849Swollman * 2. Redistributions in binary form must reproduce the above copyright 111849Swollman * notice, this list of conditions and the following disclaimer in the 121849Swollman * documentation and/or other materials provided with the distribution. 131849Swollman * 141849Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151849Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161849Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171849Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181849Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191849Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201849Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211849Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221849Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231849Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241849Swollman * SUCH DAMAGE. 251849Swollman */ 261849Swollman 271849Swollman#include <sys/cdefs.h> 281849Swollman__FBSDID("$FreeBSD: head/sys/kern/subr_kobj.c 116182 2003-06-11 00:56:59Z obrien $"); 291849Swollman 301849Swollman#include <sys/param.h> 311849Swollman#include <sys/queue.h> 321849Swollman#include <sys/malloc.h> 3392999Sobrien#include <sys/kernel.h> 3492999Sobrien#include <sys/module.h> 3592999Sobrien#include <sys/errno.h> 3692999Sobrien#ifndef TEST 3792999Sobrien#include <sys/systm.h> 381849Swollman#endif 391849Swollman#include <sys/kobj.h> 401849Swollman 411849Swollman#ifdef TEST 421849Swollman#include "usertest.h" 431849Swollman#endif 441849Swollman 451849Swollmanstatic MALLOC_DEFINE(M_KOBJ, "kobj", "Kernel object structures"); 461849Swollman 471849Swollman#ifdef KOBJ_STATS 481849Swollman 491849Swollman#include <sys/sysctl.h> 501849Swollman 5156345Sjasoneu_int kobj_lookup_hits; 5252083Smarcelu_int kobj_lookup_misses; 5315634Speter 54229009SkibSYSCTL_UINT(_kern, OID_AUTO, kobj_hits, CTLFLAG_RD, 55229009Skib &kobj_lookup_hits, 0, "") 56229009SkibSYSCTL_UINT(_kern, OID_AUTO, kobj_misses, CTLFLAG_RD, 5751794Smarcel &kobj_lookup_misses, 0, "") 5851794Smarcel 5951794Smarcel#endif 6051794Smarcel 6171579Sdeischenstatic int kobj_next_id = 1; 62229009Skib 63229009Skibstatic int 64229009Skibkobj_error_method(void) 6551794Smarcel{ 66229009Skib return ENXIO; 6715634Speter} 6851794Smarcel 691849Swollmanstatic void 701849Swollmankobj_register_method(struct kobjop_desc *desc) 711849Swollman{ 721849Swollman if (desc->id == 0) 731849Swollman desc->id = kobj_next_id++; 741849Swollman} 751849Swollman 7651794Smarcelstatic void 771849Swollmankobj_unregister_method(struct kobjop_desc *desc) 781849Swollman{ 79184548Speter} 801849Swollman 8171579Sdeischenstatic void 8271579Sdeischenkobj_class_compile_common(kobj_class_t cls, kobj_ops_t ops) 8356345Sjasone{ 841849Swollman kobj_method_t *m; 8515634Speter int i; 86229009Skib 87229009Skib /* 88229009Skib * Don't do anything if we are already compiled. 8951794Smarcel */ 9051794Smarcel if (cls->ops) 9151794Smarcel return; 9251794Smarcel 9371579Sdeischen /* 94229009Skib * First register any methods which need it. 95229009Skib */ 96229009Skib for (i = 0, m = cls->methods; m->desc; i++, m++) 9751794Smarcel kobj_register_method(m->desc); 98229009Skib 9915634Speter /* 1001849Swollman * Then initialise the ops table. 1011849Swollman */ 1021849Swollman bzero(ops, sizeof(struct kobj_ops)); 1031849Swollman ops->cls = cls; 1041849Swollman cls->ops = ops; 1051849Swollman} 1061849Swollman 1071849Swollmanvoid 10851794Smarcelkobj_class_compile(kobj_class_t cls) 1091849Swollman{ 1101849Swollman kobj_ops_t ops; 1111849Swollman 1121849Swollman /* 1131849Swollman * Allocate space for the compiled ops table. 114184548Speter */ 115217106Skib ops = malloc(sizeof(struct kobj_ops), M_KOBJ, M_NOWAIT); 116217106Skib if (!ops) 117 panic("kobj_compile_methods: out of memory"); 118 kobj_class_compile_common(cls, ops); 119} 120 121void 122kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops) 123{ 124 /* 125 * Increment refs to make sure that the ops table is not freed. 126 */ 127 cls->refs++; 128 kobj_class_compile_common(cls, ops); 129} 130 131void 132kobj_lookup_method(kobj_method_t *methods, 133 kobj_method_t *ce, 134 kobjop_desc_t desc) 135{ 136 ce->desc = desc; 137 for (; methods && methods->desc; methods++) { 138 if (methods->desc == desc) { 139 ce->func = methods->func; 140 return; 141 } 142 } 143 if (desc->deflt) 144 ce->func = desc->deflt; 145 else 146 ce->func = kobj_error_method; 147 return; 148} 149 150void 151kobj_class_free(kobj_class_t cls) 152{ 153 int i; 154 kobj_method_t *m; 155 156 /* 157 * Unregister any methods which are no longer used. 158 */ 159 for (i = 0, m = cls->methods; m->desc; i++, m++) 160 kobj_unregister_method(m->desc); 161 162 /* 163 * Free memory and clean up. 164 */ 165 free(cls->ops, M_KOBJ); 166 cls->ops = 0; 167} 168 169kobj_t 170kobj_create(kobj_class_t cls, 171 struct malloc_type *mtype, 172 int mflags) 173{ 174 kobj_t obj; 175 176 /* 177 * Allocate and initialise the new object. 178 */ 179 obj = malloc(cls->size, mtype, mflags | M_ZERO); 180 if (!obj) 181 return 0; 182 kobj_init(obj, cls); 183 184 return obj; 185} 186 187void 188kobj_init(kobj_t obj, kobj_class_t cls) 189{ 190 /* 191 * Consider compiling the class' method table. 192 */ 193 if (!cls->ops) 194 kobj_class_compile(cls); 195 196 obj->ops = cls->ops; 197 cls->refs++; 198} 199 200void 201kobj_delete(kobj_t obj, struct malloc_type *mtype) 202{ 203 kobj_class_t cls = obj->ops->cls; 204 205 /* 206 * Consider freeing the compiled method table for the class 207 * after its last instance is deleted. As an optimisation, we 208 * should defer this for a short while to avoid thrashing. 209 */ 210 cls->refs--; 211 if (!cls->refs) 212 kobj_class_free(cls); 213 214 obj->ops = 0; 215 if (mtype) 216 free(obj, mtype); 217} 218