Date: Mon, 24 Jun 2013 09:38:42 +1000 (EST) From: Bruce Evans <brde@optusnet.com.au> To: Bruce Evans <brde@optusnet.com.au> Cc: Konstantin Belousov <kostikbel@gmail.com>, svn-src-head@freebsd.org, svn-src-all@freebsd.org, Gleb Smirnoff <glebius@freebsd.org>, src-committers@freebsd.org Subject: Re: svn commit: r252032 - head/sys/amd64/include Message-ID: <20130624085002.G874@besplex.bde.org> In-Reply-To: <20130623181458.J2256@besplex.bde.org> References: <201306201430.r5KEU4G5049115@svn.freebsd.org> <20130621065839.J916@besplex.bde.org> <20130621081116.E1151@besplex.bde.org> <20130621090207.F1318@besplex.bde.org> <20130621064901.GS1214@FreeBSD.org> <20130621184140.G848@besplex.bde.org> <20130621135427.GA1214@FreeBSD.org> <20130622110352.J2033@besplex.bde.org> <20130622124832.S2347@besplex.bde.org> <20130622174921.I3112@besplex.bde.org> <20130623073343.GY91021@kib.kiev.ua> <20130623181458.J2256@besplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 23 Jun 2013, I wrote: > I thought of lots of variations, but couldn't find one that works perfectly. > One idea (that goes with the sign check on the low 32 bits) is to use a > misaligned add to memory to copy the 31st bit as a carry bit to the the > high word. The value of the counter is supposed to be > > [unsigned value of low 32 bits] + [unsigned value of next 24 bits] << 31 > (high 8 bits not used) > > at all times, with the 31st bit zero at most times so that the the carry > operation is rarely executed. This format is only slightly confusing for > debugging (it basically has 2 31st bits, with the one in the low 32 bits > rarely used). This format can be updated using something like: > .... > The above doesn't work if it is preempted -- then it might add do the > carry operation more than once. But it is easy to lock using cmpxchg or > disabling interrupts. Disabling interrupts requires only small code: > ... > Another idea is to use the high bits of the high word to encode state. > They can be set atomically enough using addl/andl/orl/xorl since they > are per-CPU. I couldn't quite get this to work. You could increment Here is a combined version. It uses the old shift trick instead of disabling interrupts for locking. The shift trick is not often used since it doesn't work for SMP. It works here since the counters are per-CPU: addl %1,%%fs:(%0) # only small 32-bit increments supported jns 8f sar $1,%%fs:7(%0) # hi 8 bits are for lock; init to 0xfe jc 8f # already locked addl $0x80,%%fs:3(%0) # misaligned memory access movb $0xfe,%%fs:7(%0) # unlock 8: ; Since the locked case is rarely executed and the code for it is only inline for convenience, the shortest code should be preferred and that is the simpler version that disables interrupts. Unless the lock byte can be exploited in the fetching and zeroing code. I don't see how it can be, since this type of locking only works for a single CPU. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130624085002.G874>