Basically, test_and_set_bit() is broken.
A reduced test case is this:
static __inline__ unsigned long
value_bit2(void *addr)
{
unsigned long *m = (unsigned long *) addr;
unsigned long temp;
__asm__ __volatile__(
".set\tnoreorder\n"
"ld\t%0, %2\n\t"
".set\treorder\n"
:"=&r" (temp), "=m" (*m)
:"m" (*m));
return temp;
}
void test4(void)
{
printk("test4 : 0x%x\n", value_bit2(&test_lock));
}
void test5(void)
{
printk("test5 : 0x%x\n", test_lock);
}
test5() prints the right value, test4() does not.
Here's some disas'ed code:
(dbx) test4/10i
[test4, 0x800e0974] daddiu sp,sp,-16
[test4, 0x800e0978] lui a0,0x8015
[test4, 0x800e097c] daddiu a0,a0,8920
[test4, 0x800e0980] sd ra,0(sp)
[test4, 0x800e0984] lui a1,0x801c
[test4, 0x800e0988] ld a1,-19064(a1)
[test4, 0x800e098c] jal printk (0x8003530c)
[test4, 0x800e0990] nop
[test4, 0x800e0994] ld ra,0(sp)
[test4, 0x800e0998] jr ra
[test4, 0x800e099c] daddiu sp,sp,16
(dbx) test5/10i
[test5, 0x800e09a0] daddiu sp,sp,-16
[test5, 0x800e09a4] lui v0,0x801c
[test5, 0x800e09a8] daddiu v0,v0,-19064
[test5, 0x800e09ac] sd ra,0(sp)
[test5, 0x800e09b0] lw a1,0(v0)
[test5, 0x800e09b4] lui a0,0x8015
[test5, 0x800e09b8] jal printk (0x8003530c)
[test5, 0x800e09bc] daddiu a0,a0,8936
[test5, 0x800e09c0] ld ra,0(sp)
[test5, 0x800e09c4] jr ra
[test5, 0x800e09c8] daddiu sp,sp,16
Right away, you can see that the way test5() loads the value is
lui v0,0x801c
daddiu v0,v0,-19064
lw a1,0(v0)
whereas test4() loads it using
lui a1,0x801c
ld a1,-19064(a1)
Now, I don't see any problems with the test4() code, but I would like
to change the code to something like
lui X,0x801c
ld a1,-19064(X)
where X != a1 and see whether that makes a difference. In any case,
from the asm inline constraints in value_bit2(), the test4() generated
code is _unexpected_, a1 should not have been used both for %0 and %2.
(The fact that I have =m in the output like is irrelevant, since in
this case, memory is not really being written to.)
Comments?
Kanoj
|