From owner-freebsd-net Tue Dec 12 18:50:34 2000 From owner-freebsd-net@FreeBSD.ORG Tue Dec 12 18:50:31 2000 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from khavrinen.lcs.mit.edu (khavrinen.lcs.mit.edu [18.24.4.193]) by hub.freebsd.org (Postfix) with ESMTP id 1838B37B400 for ; Tue, 12 Dec 2000 18:50:31 -0800 (PST) Received: (from wollman@localhost) by khavrinen.lcs.mit.edu (8.9.3/8.9.3) id VAA55319; Tue, 12 Dec 2000 21:50:19 -0500 (EST) (envelope-from wollman) Date: Tue, 12 Dec 2000 21:50:19 -0500 (EST) From: Garrett Wollman Message-Id: <200012130250.VAA55319@khavrinen.lcs.mit.edu> To: Alfred Perlstein Cc: net@FreeBSD.ORG Subject: Re: MEXT_IS_REF broken. In-Reply-To: <20001212175937.M16205@fw.wintelcom.net> References: <20001211014837.W16205@fw.wintelcom.net> <20001212014429.Y16205@fw.wintelcom.net> <20001212015059.Z16205@fw.wintelcom.net> <20001212143214.H2312@canonware.com> <20001212175937.M16205@fw.wintelcom.net> Sender: owner-freebsd-net@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org < said: > Actually, in truth I think you can get the code right like so: > long x = _mmm->m_ext.ref_cnt->refcnt; > while (!atomic_cmpset_long(&_mmm->m_ext.ref_cnt->refcnt, x - 1, x)) > ; Cool! You've just (almost) reinvented non-blocking parallel reference-counts. Of course, what you really need is: long atomic_decrement_long(long *where) { long oldval; do { oldval = *where; } while (compare_exchange(where, &oldval, oldval - 1) != FAILURE); return (oldval); /* * Five instructions in-line on i486. * 1: movl (%ebx), %eax * movl %eax, %edx * subl $1, %edx * cmpxchg (%ebx), %eax, %edx ; IIRC -- might be backwards * jc 1 */ } ...except that on some architectures, the right way to write it would be: long atomic_decrement_long(long *where) { long oldval; do { oldval = load_linked_long(where); } while (store_conditional(where, oldval - 1) != FAILURE); return (oldval); /* * Compiles to four or five instructions on an Alpha. */ } In this particular instance, you know that you just deleted the last reference if atomic_decrement_long returns an `old value' of > But that's just gross, expensive and shouldn't be needed. Nothing gross about it -- just ask any parallel algorithms geek. (Of which I am emphatically not one, I should point out.) -GAWollman To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-net" in the body of the message