From owner-cvs-all@FreeBSD.ORG Wed Jun 9 16:45:40 2004 Return-Path: Delivered-To: cvs-all@freebsd.org Received: from green.homeunix.org (freefall.freebsd.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 7BD0C16A4CE; Wed, 9 Jun 2004 16:45:40 +0000 (GMT) Received: from green.homeunix.org (green@localhost [127.0.0.1]) by green.homeunix.org (8.12.11/8.12.11) with ESMTP id i59GjdGF015959; Wed, 9 Jun 2004 12:45:39 -0400 (EDT) (envelope-from green@green.homeunix.org) Received: (from green@localhost) by green.homeunix.org (8.12.11/8.12.11/Submit) id i59Gjc4e015958; Wed, 9 Jun 2004 12:45:38 -0400 (EDT) (envelope-from green) Date: Wed, 9 Jun 2004 12:45:38 -0400 From: Brian Feldman To: Nate Lawson Message-ID: <20040609164538.GB15285@green.homeunix.org> References: <55929.1086798000@critter.freebsd.dk> <20040609092423.N85944@root.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20040609092423.N85944@root.org> User-Agent: Mutt/1.5.6i cc: cvs-src@FreeBSD.org cc: Poul-Henning Kamp 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:45:40 -0000 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@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@FreeBSD.org \ The Power to Serve! \ Opinions expressed are my own. \,,,,,,,,,,,,,,,,,,,,,,\