Skip site navigation (1)Skip section navigation (2)
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>