Basically, I'm trying to run void spinlock_counter(int) in two threads and count ought to be 2000(parameter doesn't do anything I'm just too lazy). However I made a breakpoint in the critical zone i.e. "count " and printed "flag", the flag is "GO" (the flag should be "BLOCK" if everything worked). didn't get why this hadn't worked.
Thank you for your answers!
code:
int xchg(volatile int *addr, int newval){
int result;
asm volatile("lock xchg %0, %1"
:" m"(addr),
"=a"(result)
:"1"(newval)
:"cc");
return result;
}
#define GO 0
#define BLOCK 1
int flag = GO;
void lock(int *addr){
int note = BLOCK;
while(!xchg(addr, note));
}
void unlock_spin(int *addr){
int note = GO;
xchg(addr, note);
}
void spinlock_counter(int a){
while(1) {
lock(&flag);
count ;
unlock_spin(&flag);
}
printf("%d\n", count);
}
CodePudding user response:
The condition in your while loop (in lock()
) is backwards.
The consequence is that lock()
effectively does nothing. If another thread already acquired the lock it won't spin at all, and if the lock was GO
it'll spin once (setting the lock to BLOCK
on the first iteration so that the spinning stops on the 2nd iteration).
I'd recommend writing code that describes your intent in a clearer/less confusing/less error prone way (and never relying on the value of true/false in C) so that these kinds of bugs are prevented. E.g.:
void lock(int *addr){
int note = BLOCK;
while(xchg(addr, note) != GO);
}
However I made a breakpoint in the critical zone i.e. "count " and printed "flag", the flag is "GO"
This is probably a separate bug (although the first bug can cause a different thread to unlock after your thread locks it wouldn't be easily reproducible). Specifically; nothing prevents the compiler from re-ordering your code and you'll want some kind of barrier to prevent the compiler transforming your code into the equivalent of lock(&flag); unlock_spin(&flag);
then count ;
. Changing the clobber list for your inline assembly to "cc, memory"
should prevent the compiler from reordering functions.