[parisc-linux] missing barrier in _raw_spin_lock?

Grant Grundler grundler at parisc-linux.org
Sat Jan 24 18:37:49 MST 2004


On Sat, Jan 24, 2004 at 04:15:44PM -0500, John David Anglin wrote:
> > >> static int x;
> > >> static spinlock_t lock;
...
> The test is wrong.  Static variables are initialized to 0.  So, the first
> `if' is never true and the code will optimize to a return instruction.

In any case, that should be
	static spinlock_t lock = SPIN_LOCK_UNLOCKED;

(On parisc UNLOCKED == 1, not 0 like the rest of the world)

Is gcc really that smart that it knows static variables are 0?
The would be amazing to me because I thought linker magic could
twiddle stuff like this. Anyway, gcc doesn't seem to be that smart:

# diff t1.c t2.c
3c3
< static int x=1;
---
> static int x;

# diff t1.S t2.S
3,7d2
<       .align 4
<       .type   x, @object
<       .size   x, 4
< x:
<       .word   1
54a50,51
>       .local  x
>       .comm   x,4,4


BTW, the .S diff is the same for both -O2 and -O3 output.
Maybe other compile options would further optimize.


Arndt,
In any case, thanks for raising the issue.
I hadn't looked at the asm code in a long time.

The key bit is __ldcw() in asm/system.h:

/* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.  */
#define __ldcw(a) ({ \
        unsigned __ret; \
        __asm__ __volatile__("ldcw 0(%1),%0" : "=r" (__ret) : "r" (a)); \
        __ret; \
})

I suspect (but am not certain) Arnd is right.
We indicate __ret is getting clobbered (=r) and that 'a' is an input ("r").
I don't see anything indicating we changed the memory location.

But I don't see the problem.  The t2.S output looks correct.
The "if (!x) {...}" code is generated:

...
.L18:
        ldw RR'x-$global$(%r21),%r20
        comib,<> 0,%r20,.L13
        ldi 4660,%r25
        stw %r25,RR'x-$global$(%r21)
...

BTW, PARISC still doesn't support CONFIG_SMP (cpu init sequence)
on 2.6 kernels. SMP works (mostly) on 2.4 kernels.

Here's how I generated t1.S output and it's not completely trivial.
One has to:
	o cp /usr/src/linux-2.6/include/linux/autoconf.h ./linux/
	o vi linux/autoconf.hl
		- change "#undef CONFIG_SMP" to #define
		- add "#define CONFIG_NR_CPUS 4"
	o gcc -O3 -I. -I/usr/src/linux-2.6/include/ -S t1.c -o t1.S

I've put the whole mess on
	http://iou.parisc-linux.org/~grundler/asm-memory/


BTW, I notice several other asm() in linux/asm-parisc/system.h which
specify ': "memory"' but the instructions used are register only.
Notably the ssm/rsm/mtsm insn's.
Any comment if those asm() *do NOT* need ': "memory"'?

thanks,
grant


More information about the parisc-linux mailing list