Date: Mon, 9 Jun 2003 10:30:08 +0100 From: Doug Rabson <dfr@nlsystems.com> To: Paul Richards <paul@freebsd-services.com> Cc: "M. Warner Losh" <imp@bsdimp.com> Subject: Re: VFS: C99 sparse format for struct vfsops Message-ID: <200306091030.08293.dfr@nlsystems.com> In-Reply-To: <20030604122602.GC68108@survey.codeburst.net> References: <20030603134717.GD35187@survey.codeburst.net> <1054724940.32568.6.camel@builder02.qubesoft.com> <20030604122602.GC68108@survey.codeburst.net>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wednesday 04 June 2003 1:26 pm, Paul Richards wrote:
> On Wed, Jun 04, 2003 at 12:09:00PM +0100, Doug Rabson wrote:
> > On Mon, 2003-06-02 at 21:04, Paul Richards wrote:
> > > On Tue, 2003-06-03 at 18:19, M. Warner Losh wrote:
> > > > Notice how thread 1's _m gets set based on the results of the
> > > > kobj lookup, and we have a race, even if thread1 and thread2
> > > > took out their driver instance locks.
> > >
> > > That means we have to lock the dispatch table before every method
> > > is looked up and hold it until the method returns (the
> > > alternative would be to free it inside the method once it had
> > > been called but that'd be a right mess).
> >
> > Don't even think about trying to put a mutex into the kobj dispatch
>
> I wasn't, I was just pointing out what would be necessary if the
> cacheing problem wasn't resolved :-)
I think this patch should fix the SMP-unsafe problems with kobj, at the
expense of changing the ABI slightly.
Index: tools/makeobjops.awk
===================================================================
RCS file: /home/ncvs/src/sys/tools/makeobjops.awk,v
retrieving revision 1.2
diff -u -r1.2 makeobjops.awk
--- tools/makeobjops.awk 20 Aug 2002 03:06:30 -0000 1.2
+++ tools/makeobjops.awk 9 Jun 2003 09:25:30 -0000
@@ -283,7 +283,7 @@
firstvar = varnames[1];
if (default == "")
- default = "0";
+ default = "kobj_error_method";
# the method description
printh("extern struct kobjop_desc " mname "_desc;");
@@ -293,8 +293,12 @@
line_width, length(prototype)));
# Print out the method desc
+ printc("struct kobj_method " mname "_method_default = {");
+ printc("\t&" mname "_desc, (kobjop_t) " default);
+ printc("};\n");
+
printc("struct kobjop_desc " mname "_desc = {");
- printc("\t0, (kobjop_t) " default);
+ printc("\t0, &" mname "_method_default");
printc("};\n");
# Print out the method itself
Index: sys/kobj.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/kobj.h,v
retrieving revision 1.7
diff -u -r1.7 kobj.h
--- sys/kobj.h 10 Jun 2002 22:40:26 -0000 1.7
+++ sys/kobj.h 9 Jun 2003 09:26:14 -0000
@@ -79,13 +79,13 @@
#define KOBJ_CACHE_SIZE 256
struct kobj_ops {
- kobj_method_t cache[KOBJ_CACHE_SIZE];
+ kobj_method_t *cache[KOBJ_CACHE_SIZE];
kobj_class_t cls;
};
struct kobjop_desc {
unsigned int id; /* unique ID */
- kobjop_t deflt; /* default implementation */
+ kobj_method_t *deflt; /* default implementation */
};
/*
@@ -151,19 +151,27 @@
*/
#define KOBJOPLOOKUP(OPS,OP) do { \
kobjop_desc_t _desc = &OP##_##desc; \
- kobj_method_t *_ce = \
+ kobj_method_t **_cep = \
&OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)]; \
+ kobj_method_t *_ce = *_cep; \
if (_ce->desc != _desc) { \
KOBJOPMISS; \
- kobj_lookup_method(OPS->cls->methods, _ce, _desc); \
+ _ce = kobj_lookup_method(OPS->cls->methods, \
+ _cep, _desc); \
} else { \
KOBJOPHIT; \
} \
_m = _ce->func; \
} while(0)
-void kobj_lookup_method(kobj_method_t *methods,
- kobj_method_t *ce,
- kobjop_desc_t desc);
+kobj_method_t* kobj_lookup_method(kobj_method_t *methods,
+ kobj_method_t **cep,
+ kobjop_desc_t desc);
+
+
+/*
+ * Default method implementation. Returns ENXIO.
+ */
+int kobj_error_method(void);
#endif /* !_SYS_KOBJ_H_ */
Index: kern/subr_kobj.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/subr_kobj.c,v
retrieving revision 1.5
diff -u -r1.5 subr_kobj.c
--- kern/subr_kobj.c 10 Jun 2002 22:40:26 -0000 1.5
+++ kern/subr_kobj.c 9 Jun 2003 09:27:14 -0000
@@ -59,7 +59,7 @@
static int kobj_next_id = 1;
-static int
+int
kobj_error_method(void)
{
return ENXIO;
@@ -127,23 +127,21 @@
kobj_class_compile_common(cls, ops);
}
-void
+kobj_method_t*
kobj_lookup_method(kobj_method_t *methods,
- kobj_method_t *ce,
+ kobj_method_t **cep,
kobjop_desc_t desc)
{
- ce->desc = desc;
- for (; methods && methods->desc; methods++) {
- if (methods->desc == desc) {
- ce->func = methods->func;
- return;
+ kobj_method_t *ce;
+ for (ce = methods; ce && ce->desc; ce++) {
+ if (ce->desc == desc) {
+ *cep = ce;
+ return ce;
}
}
- if (desc->deflt)
- ce->func = desc->deflt;
- else
- ce->func = kobj_error_method;
- return;
+ ce = desc->deflt;
+ *cep = ce;
+ return ce;
}
void
--
Doug Rabson Mail: dfr@nlsystems.com
Phone: +44 20 8348 6160
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200306091030.08293.dfr>
