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