Skip site navigation (1)Skip section navigation (2)
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>