Date: Wed, 9 Jun 2004 09:26:32 -0700 (PDT) From: Nate Lawson <nate@root.org> To: Poul-Henning Kamp <phk@phk.freebsd.dk> Cc: "M. Warner Losh" <imp@bsdimp.com> Subject: Re: cvs commit: src/sys/kern kern_proc.c Message-ID: <20040609092423.N85944@root.org> In-Reply-To: <55929.1086798000@critter.freebsd.dk> References: <55929.1086798000@critter.freebsd.dk>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 9 Jun 2004, Poul-Henning Kamp wrote: > In message <20040609.100413.118633043.imp@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. -Nate
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040609092423.N85944>