Re: vmstat's entries type

From: John Baldwin <jhb_at_freebsd.org>
Date: Fri, 28 Jul 2006 09:28:36 -0400
On Friday 28 July 2006 08:15, Brian Candler wrote:
> On Thu, Jul 27, 2006 at 10:58:12AM -0400, John Baldwin wrote:
> > That these counters are for stats. :)  You always have a race when reading the 
> > amount, so you can choose what is "good enough" to satisfy the conflicting 
> > requirements of "cheap" and "accurate".  To me, the cheapness of add+adc 
> > (compared to say, a cmpxchg8b loop with a branch, etc.) is worth it if you 
> > have this rare race.
> 
> You can work around the problem when reading - e.g. read twice and check the
> values are close.
> 
> But is add + adc safe for update? What about the following:
> 
> - processor 1 reads low32 as FFFFFFFF
> - processor 2 reads low32 as FFFFFFFF
> - processor 1 writes low32 as 00000000 and sets carry
> - processor 2 writes low32 as 00000000 and sets carry
> - processor 1 adds 1 to high32
> - processor 2 adds 1 to high32
> 
> I'm not saying this sequence can definitely occur - I'm thinking from a
> general point of view, and I don't know the i386 instruction set. It just
> seems plausible.
> 
> OTOH, if the above race can occur, it would imply that even a simple 32-bit
> counter update could lose counts.

If you do a 'lock add' (atomic add) for the first 'add' this race won't occur.
Because the adc wrapping so rare (relatively, you'd have to have 4 billion
atomic add's occur in the time it takes 2 different CPU's to do the pair of
instructions) you don't need to use 'lock' for the adc under the assumption
that simultaneous adc instructions (that aren't just effective nops) won't
happen often.  However, I've just thought of a problem with that. :(  Even
if carry is clear, 'adc foo, $0' isn't a NOP, it still wants to do a
read-modify-write, so you could use an update to high32 if you have two CPUs
do this:

CPU1 : bump low from ffffffff to 00000000
CPU2 : bump low from 00000000 to 00000001
CPU1 : adds 1 to high32
CPU2 : adds 0 to high32

and CPU2 reads an old value of high32 to add 0 to that is prior to CPU1's
update to high32.  To fix that you'd have to either use 'lock' with both
instructions, or use a branch to only do adc when it's not a nop.  So more
like this to increment a counter:

	lock incl counter
	jnc 1f
	lock incl counter+4
1:

-- 
John Baldwin
Received on Fri Jul 28 2006 - 11:33:19 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:58 UTC