想利用cmpxchg指令来实现双核对临界资源的互斥访问。如下代码:
static volatile __com u32 spinlock;
void spin_lock(void)
{
u32 lock = 1;
u32 ret0 = 0;
u32 ret1 = 1;
u32 unlock;
s32 ret;
while(1){
unlock = 0;
asm("cmpxchg %0,%1,%2":"+r"(unlock):"r"(lock),"r"(&spinlock));
asm("cmov %0,%1,%2":"=r"(ret):"r"(ret0),"r"(ret1));
if(ret)
break;
}
}
void spin_unlock()
{
#if 1
spinlock = 0;
#else
u32 unlock = 0;
u32 lock;
u32 ret0 = 0;
u32 ret1 = 1;
s32 ret;
while(1){
lock = 1;
asm("cmpxchg %0,%1,%2":"+r"(lock):"r"(unlock),"r"(&spinlock));
asm("cmov %0,%1,%2":"=r"(ret):"r"(ret0),"r"(ret1));
if(ret)
break;
}
#endif
}
在RISC0调用spin_lock() 和 spin_unlock()发现正常,能锁住,也能解锁。
但RISC0和RISC1都使用它们对临界资源进行保护时,发现不能正常上锁。
例如,在spin_lock()函数中,即使spinlock=0,经过cmpxchg指令后,unlock变成了1,但spinlock仍然等于0.
怀疑cmpxchg指令有问题。。
cmpxchg is an atomic compare-exchange instruction. Its operation is as follows:
cmpxchg rD,rA,rB
T = MEM32[rB]
if(T == rD) {
T = rA;
flag = 0;
} else
flag = 1;
MEM32[rB] = T;
rD = T;
cmov rD,rA,rB
Description:
According to the condition flag, either rA or rB is selected to be copied to the general-purpose register
rD. If flag is set, rA is selected. If flag is cleared, rB is selected.
rD[31:0] <- flag ? rA[31:0] : rB[31:0]