From owner-freebsd-current Thu Jan 18 2: 4: 2 2001 Delivered-To: freebsd-current@freebsd.org Received: from mailman.zeta.org.au (mailman.zeta.org.au [203.26.10.16]) by hub.freebsd.org (Postfix) with ESMTP id 2BA5737B69E for ; Thu, 18 Jan 2001 02:03:44 -0800 (PST) Received: from bde.zeta.org.au (bde.zeta.org.au [203.2.228.102]) by mailman.zeta.org.au (8.9.3/8.8.7) with ESMTP id VAA08276; Thu, 18 Jan 2001 21:03:33 +1100 Date: Thu, 18 Jan 2001 21:03:45 +1100 (EST) From: Bruce Evans X-Sender: bde@besplex.bde.org To: Garrett Wollman Cc: Alfred Perlstein , current@FreeBSD.ORG Subject: Re: Atomic breakage? In-Reply-To: <200101171614.LAA18224@khavrinen.lcs.mit.edu> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG On Wed, 17 Jan 2001, Garrett Wollman wrote: > < said: > > > Just wondering, can't you use 'LOCK addl' and then use 'LOCK addc'? > > add longword, add longword with carry? I know it would be pretty > > ugly, but it should work, no? > > The two bus cycles are independent, so there is a race condition. > > OTOH, it's a fairly *unlikely* race condition, and the worst thing > that can happen is statistics that are obviously off by four billion. > (The race only occurs when there is a carry out of the low-order > longword, which is to say, once in every 2**32 operations.) If they are obviously off by precisely four billion, then they can be corrected :-). I have thought of using special overflow handling methods to reduce the cost of keeping statistics. E.g.: --- uint32_t counter[2]; /* Low-level code increments only the lower 32 bits of counters. */ atomic_add_32(&counter[0]), 1); /* * Counter daemon adjusts counters before they get anywhere near * overflowing. It must run often enough to prevent overflow * (not very often). This also make the race in the adjustment * code harmless. */ KASSERT(counter[0] < 0xC0000000, "counter got near overflowing"); if (counter[0] & 0x80000000) { atomic_subtract_32(&counter[0], 0x80000000); ++counter[1]; } /* * Clients must use code like the following to convert counters * to values. More locking is required to load counter[0] and * counter[1] atomically, but this is not a new problem (e.g., * atomicity is mostly accidental for accesses via kmem). */ counter_value = ((uint64_t)counter[1] << 31) | counter[0]; --- Bruce To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message