spinlocks
Alan Modra
amodra at bigpond.net.au
Wed Dec 31 09:18:32 EST 2003
On Sun, Dec 28, 2003 at 04:29:55PM +1100, Anton Blanchard wrote:
> static inline void _raw_spin_lock(spinlock_t *lock)
> {
> unsigned long tmp;
>
> asm volatile(
> "1: ldarx %0,0,%1 # spin_lock\n\
> cmpdi 0,%0,0\n\
> bne- 2f\n\
> stdcx. 13,0,%1\n\
> bne- 1b\n\
> isync\n\
> .subsection 1\n\
> 2:"
> HMT_LOW
> BEGIN_FTR_SECTION
> " mflr %0\n\
> bl .splpar_spinlock\n"
> END_FTR_SECTION_IFSET(CPU_FTR_SPLPAR)
> " ldx %0,0,%1\n\
> cmpdi 0,%0,0\n\
> bne- 2b\n"
> HMT_MEDIUM
> " b 1b\n\
> .previous"
> : "=&r"(tmp)
> : "r"(&lock->lock)
> : "cr0", "memory");
> }
You might want to restore lr somewhere in there, unless there's
something magic about those FTR_SECTION macros. :)
Do you really want to tell gcc that all memory is potentially changed
by _raw_spin_lock? Hmm, I guess if you're accessing something
protected by a lock then you want to say that old values of the
"something" are stale. However, I think it would be better to
explicitly say that &lock->lock is an output of the asm, rather than
relying on the "memory" clobber to do that.
Also, you might find it a little tricky to write splpar_spinlock. The
problem is that you can't use any registers (since you haven't told
gcc about any), and you'll need to be careful about using the stack.
If _raw_spin_lock is called from a leaf function foo, then gcc may not
set up a stack frame for foo. As per the ABI, gcc may use 288 bytes
below r1 as scratch that isn't saved over calls. Since you haven't
told gcc that you're making a call, you need to skip this area if
using the stack in splpar_spinlock.
I wonder if you wouldn't do better by making _raw_spin_lock a function
written in asm. OK, that would mean the overhead of a function call,
but I reckon many people forget that inline code blows icache, which
probably hurts more..
--
Alan Modra
IBM OzLabs - Linux Technology Centre
** Sent via the linuxppc64-dev mail list. See http://lists.linuxppc.org/
More information about the Linuxppc64-dev
mailing list