|
|
| version 1.6, 2004/04/01 08:41:24 | version 1.7, 2004/04/14 18:28:29 |
|---|---|
| Line 56 struct kobj_method { | Line 56 struct kobj_method { |
| const char *name; /* class name */ \ | const char *name; /* class name */ \ |
| kobj_method_t *methods; /* method table */ \ | kobj_method_t *methods; /* method table */ \ |
| size_t size; /* object size */ \ | size_t size; /* object size */ \ |
| kobj_class_t *baseclasses; /* base classes */ \ | |
| u_int refs; /* reference count */ \ | u_int refs; /* reference count */ \ |
| kobj_ops_t ops /* compiled method table */ | kobj_ops_t ops /* compiled method table */ |
| Line 80 struct kobj { | Line 81 struct kobj { |
| #define KOBJ_CACHE_SIZE 256 | #define KOBJ_CACHE_SIZE 256 |
| struct kobj_ops { | struct kobj_ops { |
| kobj_method_t cache[KOBJ_CACHE_SIZE]; | kobj_method_t *cache[KOBJ_CACHE_SIZE]; |
| kobj_class_t cls; | kobj_class_t cls; |
| }; | }; |
| struct kobjop_desc { | struct kobjop_desc { |
| unsigned int id; /* unique ID */ | unsigned int id; /* unique ID */ |
| kobjop_t deflt; /* default implementation */ | kobj_method_t *deflt; /* default implementation */ |
| }; | }; |
| /* | /* |
| Line 94 struct kobjop_desc { | Line 95 struct kobjop_desc { |
| */ | */ |
| #define KOBJMETHOD(NAME, FUNC) { &NAME##_desc, (kobjop_t) FUNC } | #define KOBJMETHOD(NAME, FUNC) { &NAME##_desc, (kobjop_t) FUNC } |
| #define DEFINE_CLASS(name, methods, size) \ | /* |
| \ | * Declare a class (which should be defined in another file. |
| struct kobj_class name ## _class = { \ | */ |
| #name, methods, size \ | #define DECLARE_CLASS(name) extern struct kobj_class name |
| /* | |
| * Define a class with no base classes (api backward-compatible. with | |
| * FreeBSD-5.1 and earlier). | |
| */ | |
| #define DEFINE_CLASS(name, methods, size) \ | |
| DEFINE_CLASS_0(name, name ## _class, methods, size) | |
| /* | |
| * Define a class with no base classes. Use like this: | |
| * | |
| * DEFINE_CLASS_0(foo, foo_class, foo_methods, sizeof(foo_softc)); | |
| */ | |
| #define DEFINE_CLASS_0(name, classvar, methods, size) \ | |
| \ | |
| struct kobj_class classvar = { \ | |
| #name, methods, size, 0 \ | |
| } | |
| /* | |
| * Define a class inheriting a single base class. Use like this: | |
| * | |
| * DEFINE_CLASS1(foo, foo_class, foo_methods, sizeof(foo_softc), | |
| * bar); | |
| */ | |
| #define DEFINE_CLASS_1(name, classvar, methods, size, \ | |
| base1) \ | |
| \ | |
| static kobj_class_t name ## _baseclasses[] = { \ | |
| &base1, 0 \ | |
| }; \ | |
| struct kobj_class classvar = { \ | |
| #name, methods, size, name ## _baseclasses \ | |
| } | |
| /* | |
| * Define a class inheriting two base classes. Use like this: | |
| * | |
| * DEFINE_CLASS2(foo, foo_class, foo_methods, sizeof(foo_softc), | |
| * bar, baz); | |
| */ | |
| #define DEFINE_CLASS_2(name, methods, size, \ | |
| base1, base2) \ | |
| \ | |
| static kobj_class_t name ## _baseclasses[] = { \ | |
| &base1, \ | |
| &base2, 0 \ | |
| }; \ | |
| struct kobj_class name ## _class = { \ | |
| #name, methods, size, name ## _baseclasses \ | |
| } | |
| /* | |
| * Define a class inheriting three base classes. Use like this: | |
| * | |
| * DEFINE_CLASS3(foo, foo_class, foo_methods, sizeof(foo_softc), | |
| * bar, baz, foobar); | |
| */ | |
| #define DEFINE_CLASS_3(name, methods, size, \ | |
| base1, base2, base3) \ | |
| \ | |
| static kobj_class_t name ## _baseclasses[] = { \ | |
| &base1, \ | |
| &base2, \ | |
| &base3, 0 \ | |
| }; \ | |
| struct kobj_class name ## _class = { \ | |
| #name, methods, size, name ## _baseclasses \ | |
| } | } |
| /* | /* |
| Line 142 extern u_int kobj_lookup_misses; | Line 211 extern u_int kobj_lookup_misses; |
| #ifdef KOBJ_STATS | #ifdef KOBJ_STATS |
| #define KOBJOPLOOKUP(OPS,OP) do { \ | #define KOBJOPLOOKUP(OPS,OP) do { \ |
| kobjop_desc_t _desc = &OP##_##desc; \ | kobjop_desc_t _desc = &OP##_##desc; \ |
| kobj_method_t *_ce = \ | kobj_method_t **_cep = \ |
| &OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)]; \ | &OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)]; \ |
| if (_ce->desc != _desc) { \ | kobj_method_t *_ce = *_cep; \ |
| kobj_lookup_misses++; \ | kobj_lookup_hits++; /* assume hit */ \ |
| kobj_lookup_method(OPS->cls->methods, _ce, _desc); \ | if (_ce->desc != _desc) \ |
| } else { \ | _ce = kobj_lookup_method(OPS->cls, \ |
| kobj_lookup_hits++; \ | _cep, _desc); \ |
| } \ | |
| _m = _ce->func; \ | _m = _ce->func; \ |
| } while(0) | } while(0) |
| #else | #else |
| #define KOBJOPLOOKUP(OPS,OP) do { \ | #define KOBJOPLOOKUP(OPS,OP) do { \ |
| kobjop_desc_t _desc = &OP##_##desc; \ | kobjop_desc_t _desc = &OP##_##desc; \ |
| kobj_method_t *_ce = &OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)]; \ | kobj_method_t **_cep = \ |
| &OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)]; \ | |
| kobj_method_t *_ce = *_cep; \ | |
| if (_ce->desc != _desc) \ | if (_ce->desc != _desc) \ |
| kobj_lookup_method(OPS->cls->methods, _ce, _desc); \ | _ce = kobj_lookup_method(OPS->cls, \ |
| _m = _ce->func; \ | _cep, _desc); \ |
| } while(0) | _m = _ce->func; \ |
| #endif /* !KOBJ_STATS */ | } while(0) |
| #endif | |
| void kobj_lookup_method(kobj_method_t *methods, | |
| kobj_method_t *ce, | kobj_method_t *kobj_lookup_method(kobj_class_t cls, |
| kobjop_desc_t desc); | kobj_method_t **cep, |
| kobjop_desc_t desc); | |
| /* | |
| * Default method implementation. Returns ENXIO. | |
| */ | |
| int kobj_error_method(void); | |
| #endif /* !_SYS_KOBJ_H_ */ | #endif /* !_SYS_KOBJ_H_ */ |