cvs commit: src/sys/kern kern_proc.c
Brian Feldman
green at FreeBSD.org
Wed Jun 9 16:45:40 GMT 2004
On Wed, Jun 09, 2004 at 09:26:32AM -0700, Nate Lawson wrote:
> On Wed, 9 Jun 2004, Poul-Henning Kamp wrote:
> > In message <20040609.100413.118633043.imp at bsdimp.com>, "M. Warner Losh" writes:
> > >Can you provide a couple of lines about why BAD is BAD and why GOOD
> > >fixes that flaw? That should help others from making this mistake in
> > >the future.
> >
> > The way to fix this is to make sure that the test for zero-ness
> > is done on the result of our own decrement operation:
> >
> > LOCK(foo->lock)
> > i = --foo->refcount;
> > UNLOCK(foo->lock)
> > if (i == 0)
> > destroy(foo);
> >
> > Assume foo->refcount = 2;
> >
> > thread1 (low priority) thread2 (high priority)
> > ---------------------- -----------------------
> >
> > ... ...
> > LOCK(foo->lock) ...
> > i = --foo->refcount; LOCK(foo->lock)
> > # i == 1, refcount == 1
> > UNLOCK(foo->lock)
> > i = --foo->refcount;
> > # i == 0, refcount == 0
> > UNLOCK(foo->lock)
> > if (i == 0) # true
> > destroy(foo)
> > ...
> >
> > if (i == 0) # false
> > destroy(foo)
> >
> > I'm not very good at explaining this am I ?
>
> The only potential remaining problem is if another thread can increment
> the refcount after the unlock and i == 0 comparison but before
> "free(foo)". In this case, you'll free an object that is still in use.
> It's safe to hold locks across free(), that's how I handle this case.
That's not a way to handle that case. The way to handle that case
in general is to make it impossible to find a reference the object
when the refcount hits zero.
LOCK(foo_list)
> > LOCK(foo->lock)
> > i = --foo->refcount;
if (i == 0)
remove(foo_list, foo);
> > UNLOCK(foo->lock)
UNLOCK(foo_list)
> > if (i == 0)
> > destroy(foo);
--
Brian Fundakowski Feldman \'[ FreeBSD ]''''''''''\
<> green at FreeBSD.org \ The Power to Serve! \
Opinions expressed are my own. \,,,,,,,,,,,,,,,,,,,,,,\
More information about the cvs-src
mailing list