159093Sdfr/*-
2121129Sdfr * Copyright (c) 2000,2003 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: stable/10/sys/sys/kobj.h 318275 2017-05-14 14:21:11Z marius $
2759093Sdfr */
2859093Sdfr
2959093Sdfr#ifndef _SYS_KOBJ_H_
3059093Sdfr#define _SYS_KOBJ_H_
3159093Sdfr
3259093Sdfr/*
3359093Sdfr * Forward declarations
3459093Sdfr */
3559093Sdfrtypedef struct kobj		*kobj_t;
3659093Sdfrtypedef struct kobj_class	*kobj_class_t;
37227343Sedtypedef const struct kobj_method kobj_method_t;
3859093Sdfrtypedef int			(*kobjop_t)(void);
3959093Sdfrtypedef struct kobj_ops		*kobj_ops_t;
4059093Sdfrtypedef struct kobjop_desc	*kobjop_desc_t;
4159093Sdfrstruct malloc_type;
4259093Sdfr
4359093Sdfrstruct kobj_method {
4459093Sdfr	kobjop_desc_t	desc;
4559093Sdfr	kobjop_t	func;
4659093Sdfr};
4759093Sdfr
4859093Sdfr/*
4959093Sdfr * A class is simply a method table and a sizeof value. When the first
5059093Sdfr * instance of the class is created, the method table will be compiled
5159093Sdfr * into a form more suited to efficient method dispatch. This compiled
5259093Sdfr * method table is always the first field of the object.
5359093Sdfr */
5459093Sdfr#define KOBJ_CLASS_FIELDS						\
5559093Sdfr	const char	*name;		/* class name */		\
5659093Sdfr	kobj_method_t	*methods;	/* method table */		\
5759093Sdfr	size_t		size;		/* object size */		\
58121129Sdfr	kobj_class_t	*baseclasses;	/* base classes */		\
5959820Sdfr	u_int		refs;		/* reference count */		\
6059093Sdfr	kobj_ops_t	ops		/* compiled method table */
6159093Sdfr
6259093Sdfrstruct kobj_class {
6359093Sdfr	KOBJ_CLASS_FIELDS;
6459093Sdfr};
6559093Sdfr
6659093Sdfr/*
6759093Sdfr * Implementation of kobj.
6859093Sdfr */
6959093Sdfr#define KOBJ_FIELDS				\
7060396Sbde	kobj_ops_t	ops
7159093Sdfr
7259093Sdfrstruct kobj {
7359093Sdfr	KOBJ_FIELDS;
7459093Sdfr};
7559093Sdfr
7659093Sdfr/*
7759093Sdfr * The ops table is used as a cache of results from kobj_lookup_method().
7859093Sdfr */
7959093Sdfr
8059093Sdfr#define KOBJ_CACHE_SIZE	256
8159093Sdfr
8259093Sdfrstruct kobj_ops {
83121129Sdfr	kobj_method_t	*cache[KOBJ_CACHE_SIZE];
8459093Sdfr	kobj_class_t	cls;
8559093Sdfr};
8659093Sdfr
8759093Sdfrstruct kobjop_desc {
88121129Sdfr	unsigned int	id;		/* unique ID */
89227384Sed	kobj_method_t	deflt;		/* default implementation */
9059093Sdfr};
9159093Sdfr
9259093Sdfr/*
9359093Sdfr * Shorthand for constructing method tables.
94194049Savg * The ternary operator is (ab)used to provoke a warning when FUNC
95194049Savg * has a signature that is not compatible with kobj method signature.
9659093Sdfr */
97188475Simp#define KOBJMETHOD(NAME, FUNC) \
98194028Savg	{ &NAME##_desc, (kobjop_t) (1 ? FUNC : (NAME##_t *)NULL) }
9959093Sdfr
100121129Sdfr/*
101188475Simp *
102188475Simp */
103188475Simp#define KOBJMETHOD_END	{ NULL, NULL }
104188475Simp
105188475Simp/*
106121129Sdfr * Declare a class (which should be defined in another file.
107121129Sdfr */
108121129Sdfr#define DECLARE_CLASS(name) extern struct kobj_class name
109121129Sdfr
110121129Sdfr/*
111121129Sdfr * Define a class with no base classes (api backward-compatible. with
112121129Sdfr * FreeBSD-5.1 and earlier).
113121129Sdfr */
114121129Sdfr#define DEFINE_CLASS(name, methods, size)     		\
115121129SdfrDEFINE_CLASS_0(name, name ## _class, methods, size)
116121129Sdfr
117121129Sdfr/*
118121129Sdfr * Define a class with no base classes. Use like this:
119121129Sdfr *
120121129Sdfr * DEFINE_CLASS_0(foo, foo_class, foo_methods, sizeof(foo_softc));
121121129Sdfr */
122121129Sdfr#define DEFINE_CLASS_0(name, classvar, methods, size)	\
123121129Sdfr							\
124121129Sdfrstruct kobj_class classvar = {				\
125188040Simp	#name, methods, size, NULL			\
12659093Sdfr}
12759093Sdfr
12859093Sdfr/*
129121129Sdfr * Define a class inheriting a single base class. Use like this:
130121129Sdfr *
131161587Srik * DEFINE_CLASS_1(foo, foo_class, foo_methods, sizeof(foo_softc),
132121129Sdfr *			  bar);
133121129Sdfr */
134121129Sdfr#define DEFINE_CLASS_1(name, classvar, methods, size,	\
135121129Sdfr		       base1)				\
136121129Sdfr							\
137121129Sdfrstatic kobj_class_t name ## _baseclasses[] =		\
138188475Simp	{ &base1, NULL };				\
139121129Sdfrstruct kobj_class classvar = {				\
140121129Sdfr	#name, methods, size, name ## _baseclasses	\
141121129Sdfr}
142121129Sdfr
143121129Sdfr/*
144121129Sdfr * Define a class inheriting two base classes. Use like this:
145121129Sdfr *
146161587Srik * DEFINE_CLASS_2(foo, foo_class, foo_methods, sizeof(foo_softc),
147121129Sdfr *			  bar, baz);
148121129Sdfr */
149121129Sdfr#define DEFINE_CLASS_2(name, methods, size,		\
150121129Sdfr	               base1, base2)			\
151121129Sdfr							\
152121129Sdfrstatic kobj_class_t name ## _baseclasses[] =		\
153121129Sdfr	{ &base1,					\
154188040Simp	  &base2, NULL };				\
155121129Sdfrstruct kobj_class name ## _class = {			\
156121129Sdfr	#name, methods, size, name ## _baseclasses	\
157121129Sdfr}
158121129Sdfr
159121129Sdfr/*
160121129Sdfr * Define a class inheriting three base classes. Use like this:
161121129Sdfr *
162161587Srik * DEFINE_CLASS_3(foo, foo_class, foo_methods, sizeof(foo_softc),
163121129Sdfr *			  bar, baz, foobar);
164121129Sdfr */
165121129Sdfr#define DEFINE_CLASS_3(name, methods, size,		\
166121129Sdfr		       base1, base2, base3)		\
167121129Sdfr							\
168121129Sdfrstatic kobj_class_t name ## _baseclasses[] =		\
169121129Sdfr	{ &base1,					\
170121129Sdfr	  &base2,					\
171188040Simp	  &base3, NULL };				\
172121129Sdfrstruct kobj_class name ## _class = {			\
173121129Sdfr	#name, methods, size, name ## _baseclasses	\
174121129Sdfr}
175121129Sdfr
176121129Sdfr
177121129Sdfr/*
17859093Sdfr * Compile the method table in a class.
17959093Sdfr */
18059093Sdfrvoid		kobj_class_compile(kobj_class_t cls);
18159093Sdfr
18259093Sdfr/*
18365173Sdfr * Compile the method table, with the caller providing the space for
18465173Sdfr * the ops table.(for use before malloc is initialised).
18565173Sdfr */
18665173Sdfrvoid		kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops);
18765173Sdfr
18865173Sdfr/*
18959093Sdfr * Free the compiled method table in a class.
19059093Sdfr */
19159093Sdfrvoid		kobj_class_free(kobj_class_t cls);
19259093Sdfr
19359093Sdfr/*
19472180Sasmodai * Allocate memory for and initialise a new object.
19559093Sdfr */
19659093Sdfrkobj_t		kobj_create(kobj_class_t cls,
19759093Sdfr			    struct malloc_type *mtype,
19859093Sdfr			    int mflags);
19959093Sdfr
20059093Sdfr/*
20159093Sdfr * Initialise a pre-allocated object.
20259093Sdfr */
20359093Sdfrvoid		kobj_init(kobj_t obj, kobj_class_t cls);
204227537Smariusvoid		kobj_init_static(kobj_t obj, kobj_class_t cls);
20559093Sdfr
20659093Sdfr/*
20759093Sdfr * Delete an object. If mtype is non-zero, free the memory.
20859093Sdfr */
20959093Sdfrvoid		kobj_delete(kobj_t obj, struct malloc_type *mtype);
21059093Sdfr
21159093Sdfr/*
21259093Sdfr * Maintain stats on hits/misses in lookup caches.
21359093Sdfr */
21459093Sdfr#ifdef KOBJ_STATS
21598105Skbyancextern u_int kobj_lookup_hits;
21698105Skbyancextern u_int kobj_lookup_misses;
21759093Sdfr#endif
21859093Sdfr
21959093Sdfr/*
22059093Sdfr * Lookup the method in the cache and if it isn't there look it up the
22159093Sdfr * slow way.
22259093Sdfr */
223120343Speter#ifdef KOBJ_STATS
224121129Sdfr#define KOBJOPLOOKUP(OPS,OP) do {				\
225121129Sdfr	kobjop_desc_t _desc = &OP##_##desc;			\
226121129Sdfr	kobj_method_t **_cep =					\
227121129Sdfr	    &OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)];	\
228121129Sdfr	kobj_method_t *_ce = *_cep;				\
229318275Smarius	if (_ce->desc != _desc) {				\
230121129Sdfr		_ce = kobj_lookup_method(OPS->cls,		\
231121129Sdfr					 _cep, _desc);		\
232318275Smarius		kobj_lookup_misses++;				\
233318275Smarius	} else							\
234318275Smarius		kobj_lookup_hits++;				\
235121129Sdfr	_m = _ce->func;						\
23659093Sdfr} while(0)
237121129Sdfr#else
238121129Sdfr#define KOBJOPLOOKUP(OPS,OP) do {				\
239121129Sdfr	kobjop_desc_t _desc = &OP##_##desc;			\
240121129Sdfr	kobj_method_t **_cep =					\
241121129Sdfr	    &OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)];	\
242121129Sdfr	kobj_method_t *_ce = *_cep;				\
243121129Sdfr	if (_ce->desc != _desc)					\
244121129Sdfr		_ce = kobj_lookup_method(OPS->cls,		\
245121129Sdfr					 _cep, _desc);		\
246121129Sdfr	_m = _ce->func;						\
247120343Speter} while(0)
248121129Sdfr#endif
24959093Sdfr
250121129Sdfrkobj_method_t* kobj_lookup_method(kobj_class_t cls,
251121129Sdfr				  kobj_method_t **cep,
252121129Sdfr				  kobjop_desc_t desc);
25359093Sdfr
254121129Sdfr
255121129Sdfr/*
256121129Sdfr * Default method implementation. Returns ENXIO.
257121129Sdfr */
258121129Sdfrint kobj_error_method(void);
259121129Sdfr
26059093Sdfr#endif /* !_SYS_KOBJ_H_ */
261