From owner-cvs-all@FreeBSD.ORG Wed Jun 9 16:26:36 2004 Return-Path: Delivered-To: cvs-all@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5EBA516A4CE for ; Wed, 9 Jun 2004 16:26:36 +0000 (GMT) Received: from root.org (root.org [67.118.192.226]) by mx1.FreeBSD.org (Postfix) with SMTP id 27C8F43D31 for ; Wed, 9 Jun 2004 16:26:36 +0000 (GMT) (envelope-from nate@root.org) Received: (qmail 86069 invoked by uid 1000); 9 Jun 2004 16:26:32 -0000 Date: Wed, 9 Jun 2004 09:26:32 -0700 (PDT) From: Nate Lawson To: Poul-Henning Kamp In-Reply-To: <55929.1086798000@critter.freebsd.dk> Message-ID: <20040609092423.N85944@root.org> References: <55929.1086798000@critter.freebsd.dk> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII cc: cvs-src@FreeBSD.org cc: src-committers@FreeBSD.org cc: cvs-all@FreeBSD.org cc: "M. Warner Losh" Subject: Re: cvs commit: src/sys/kern kern_proc.c X-BeenThere: cvs-all@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: CVS commit messages for the entire tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 09 Jun 2004 16:26:36 -0000 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