kobj.h revision 59820
1272343Sngie/*-
2272343Sngie * Copyright (c) 2000 Doug Rabson
3272343Sngie * All rights reserved.
4272343Sngie *
5272343Sngie * Redistribution and use in source and binary forms, with or without
6272343Sngie * modification, are permitted provided that the following conditions
7272343Sngie * are met:
8272343Sngie * 1. Redistributions of source code must retain the above copyright
9272343Sngie *    notice, this list of conditions and the following disclaimer.
10272343Sngie * 2. Redistributions in binary form must reproduce the above copyright
11272343Sngie *    notice, this list of conditions and the following disclaimer in the
12272343Sngie *    documentation and/or other materials provided with the distribution.
13272343Sngie *
14272343Sngie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15272343Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16272343Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17272343Sngie * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18272343Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20272343Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22272343Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23272343Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24272343Sngie * SUCH DAMAGE.
25272343Sngie *
26272343Sngie *	$FreeBSD: head/sys/sys/kobj.h 59820 2000-05-01 10:45:15Z dfr $
27272343Sngie */
28272343Sngie
29272343Sngie#ifndef _SYS_KOBJ_H_
30272343Sngie#define _SYS_KOBJ_H_
31272343Sngie
32272343Sngie/*
33272343Sngie * Forward declarations
34272343Sngie */
35272343Sngietypedef struct kobj		*kobj_t;
36272343Sngietypedef struct kobj_class	*kobj_class_t;
37272343Sngietypedef struct kobj_method	kobj_method_t;
38272343Sngietypedef int			(*kobjop_t)(void);
39272343Sngietypedef struct kobj_ops		*kobj_ops_t;
40272343Sngietypedef struct kobjop_desc	*kobjop_desc_t;
41272343Sngiestruct malloc_type;
42272343Sngie
43272343Sngiestruct kobj_method {
44272343Sngie	kobjop_desc_t	desc;
45272343Sngie	kobjop_t	func;
46272343Sngie};
47272343Sngie
48272343Sngie/*
49272343Sngie * A class is simply a method table and a sizeof value. When the first
50272343Sngie * instance of the class is created, the method table will be compiled
51272343Sngie * into a form more suited to efficient method dispatch. This compiled
52272343Sngie * method table is always the first field of the object.
53272343Sngie */
54272343Sngie#define KOBJ_CLASS_FIELDS						\
55272343Sngie	const char	*name;		/* class name */		\
56272343Sngie	kobj_method_t	*methods;	/* method table */		\
57272343Sngie	size_t		size;		/* object size */		\
58272343Sngie	u_int		refs;		/* reference count */		\
59272343Sngie	kobj_ops_t	ops		/* compiled method table */
60272343Sngie
61272343Sngiestruct kobj_class {
62272343Sngie	KOBJ_CLASS_FIELDS;
63272343Sngie};
64272343Sngie
65272343Sngie/*
66272343Sngie * Implementation of kobj.
67272343Sngie */
68272343Sngie#define KOBJ_FIELDS				\
69272343Sngie	kobj_ops_t	ops;
70272343Sngie
71272343Sngiestruct kobj {
72272343Sngie	KOBJ_FIELDS;
73272343Sngie};
74272343Sngie
75272343Sngie/*
76272343Sngie * The ops table is used as a cache of results from kobj_lookup_method().
77272343Sngie */
78272343Sngie
79272343Sngie#define KOBJ_CACHE_SIZE	256
80272343Sngie
81272343Sngiestruct kobj_ops {
82272343Sngie	kobj_method_t	cache[KOBJ_CACHE_SIZE];
83272343Sngie	kobj_class_t	cls;
84272343Sngie};
85272343Sngie
86272343Sngiestruct kobjop_desc {
87272343Sngie	unsigned int	id;	/* unique ID */
88272343Sngie	kobjop_t	deflt;	/* default implementation */
89272343Sngie};
90272343Sngie
91272343Sngie/*
92272343Sngie * Shorthand for constructing method tables.
93272343Sngie */
94272343Sngie#define KOBJMETHOD(NAME, FUNC) { &NAME##_desc, (kobjop_t) FUNC }
95272343Sngie
96272343Sngie#define DEFINE_CLASS(name, methods, size)	\
97272343Sngie						\
98272343Sngiestruct kobj_class name ## _class = {		\
99272343Sngie	#name, methods, size			\
100272343Sngie}
101272343Sngie
102272343Sngie/*
103272343Sngie * Compile the method table in a class.
104272343Sngie */
105272343Sngievoid		kobj_class_compile(kobj_class_t cls);
106272343Sngie
107272343Sngie/*
108272343Sngie * Free the compiled method table in a class.
109272343Sngie */
110272343Sngievoid		kobj_class_free(kobj_class_t cls);
111272343Sngie
112272343Sngie/*
113272343Sngie * Allocate memory for and initalise a new object.
114272343Sngie */
115272343Sngiekobj_t		kobj_create(kobj_class_t cls,
116272343Sngie			    struct malloc_type *mtype,
117272343Sngie			    int mflags);
118272343Sngie
119272343Sngie/*
120272343Sngie * Initialise a pre-allocated object.
121272343Sngie */
122void		kobj_init(kobj_t obj, kobj_class_t cls);
123
124/*
125 * Delete an object. If mtype is non-zero, free the memory.
126 */
127void		kobj_delete(kobj_t obj, struct malloc_type *mtype);
128
129/*
130 * Maintain stats on hits/misses in lookup caches.
131 */
132#ifdef KOBJ_STATS
133extern int kobj_lookup_hits;
134extern int kobj_lookup_misses;
135#define KOBJOPHIT	do { kobj_lookup_hits++; } while (0)
136#define KOBJOPMISS	do { kobj_lookup_misses++; } while (0)
137#else
138#define KOBJOPHIT	do { } while (0)
139#define KOBJOPMISS	do { } while (0)
140#endif
141
142/*
143 * Lookup the method in the cache and if it isn't there look it up the
144 * slow way.
145 */
146#define KOBJOPLOOKUP(OPS,OP) do {					\
147	kobjop_desc_t _desc = &OP##_##desc;				\
148	kobj_method_t *_ce =						\
149	    &OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)];		\
150	if (_ce->desc != _desc) {					\
151		KOBJOPMISS;						\
152		kobj_lookup_method(OPS->cls->methods, _ce, _desc);	\
153	} else {							\
154		KOBJOPHIT;						\
155	}								\
156	_m = _ce->func;							\
157} while(0)
158
159void kobj_lookup_method(kobj_method_t *methods,
160			kobj_method_t *ce,
161			kobjop_desc_t desc);
162
163#endif /* !_SYS_KOBJ_H_ */
164