Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 9 Jun 2004 11:54:06 -0700 (PDT)
From:      Julian Elischer <julian@elischer.org>
To:        Pawel Jakub Dawidek <pjd@FreeBSD.org>
Cc:        "M. Warner Losh" <imp@bsdimp.com>
Subject:   Re: cvs commit: src/sys/kern kern_proc.c
Message-ID:  <Pine.BSF.4.21.0406091151050.57882-100000@InterJet.elischer.org>
In-Reply-To: <20040609182041.GV12007@darkness.comp.waw.pl>

next in thread | previous in thread | raw e-mail | index | archive | help


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!
> 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0406091151050.57882-100000>