From owner-cvs-all@FreeBSD.ORG Wed Jun 9 18:54:40 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 9722116A4CE; Wed, 9 Jun 2004 18:54:40 +0000 (GMT) Received: from sccrmhc11.comcast.net (sccrmhc11.comcast.net [204.127.202.55]) by mx1.FreeBSD.org (Postfix) with ESMTP id 16E5C43D4C; Wed, 9 Jun 2004 18:54:40 +0000 (GMT) (envelope-from julian@elischer.org) Received: from interjet.elischer.org ([24.7.73.28]) by comcast.net (sccrmhc11) with ESMTP id <2004060918540701100ffv68e>; Wed, 9 Jun 2004 18:54:08 +0000 Received: from localhost (localhost.elischer.org [127.0.0.1]) by InterJet.elischer.org (8.9.1a/8.9.1) with ESMTP id LAA59527; Wed, 9 Jun 2004 11:54:08 -0700 (PDT) Date: Wed, 9 Jun 2004 11:54:06 -0700 (PDT) From: Julian Elischer To: Pawel Jakub Dawidek In-Reply-To: <20040609182041.GV12007@darkness.comp.waw.pl> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII cc: src-committers@FreeBSD.org cc: cvs-src@FreeBSD.org cc: cvs-all@FreeBSD.org cc: phk@phk.freebsd.dk cc: Bosko Milekic cc: Nate Lawson 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 18:54:40 -0000 On Wed, 9 Jun 2004, Pawel Jakub Dawidek wrote: > On Wed, Jun 09, 2004 at 05:53:57PM +0000, Bosko Milekic wrote: > +> > +> Pawel Jakub Dawidek wrote: > +> >But isn't you reference counting mechanism limited to only 0 and 1 > +> >values? > +> > +> Nope. > +> > +> The cmpset does exactly this, atomically: if the refcnt is 0, set it > +> to 1 and return non-zero, otherwise leave it as it and return 0. > +> > +> Therefore, if two threads are freeing at the same time, the refcount > +> will get dropped twice [atomically, so we don't have to worry about > +> a missed decrement], and the threads will race on that atomic cmpset. > +> But since the cmpset is atomic, then only one thread will get to set > +> the refcnt to 1 and free, and the other will see that it is not zero, > +> and so its cmpset will merely return 0 and it will be done (it won't > +> have to be the one cleaning up/freeing the object). > +> > +> The reference count, after hitting zero, cannot go back up because the > +> object is being freed and no other references exist. If they do, then > +> the reference counting model is broken. > +> > +> Note that in the cmpset, if the refcnt is NOT zero, all that has happened > +> is that it was decremented by 1 and the object not freed. > +> > +> Again, the code is correct. > > Ok, I get it now. Even if there will be a race between two threads, i.e.: > > [ref_cnt is 2] > > thread1 thread2 > > atomic_substract(obj, 1) > [ref_cnt is 1] > atomic_substract(obj, 1) > [ref_cnt is 0] > atomic_cmpset(obj, 0, 1) -> true > [do clean up] > atomic_cmpset(obj, 0, 1) -> false > [skip cleanups] > > (thread2 sets ref_cnt to 0, but thread1 destroys objects) we free object > only once. Cool, I like it:) The method shown above has, however the disadvantage of being less than obvious. ALso thread 2 is likely to get a page fault, which is a less than perfect result.. the reference count must never be read or written after the [cleanup] because it may free the page on which teh counter is kept. > > BTW. Do we assume that atomic operations are atomic on MP machines? > I read atomic(9), but I still don't know if I should use it or not for > things like those. > > -- > Pawel Jakub Dawidek http://www.FreeBSD.org > pjd@FreeBSD.org http://garage.freebsd.pl > FreeBSD committer Am I Evil? Yes, I Am! >