Reputation: 163
I am currently learning about operating systems and was wondering, using these definitions, would this be working as expected or am I missing some atomic operations?
int locked = 0;
void lsLock(){
while(1) {
if (locked){
continue;
} else {
locked = 1;
break;
}
}
}
void lsUnlock(){
locked = 0;
}
Thanks in advance!
Upvotes: 0
Views: 384
Reputation: 37232
The first problem is that the compiler assumes that nothing will be altered by anything "external" (unless it's marked volatile
); which means that the compiler is able to optimize this:
int locked = 0;
void lsLock(){
while(1) {
if (locked){
continue;
} else {
locked = 1;
break;
}
}
}
..into this:
int locked = 0;
void lsLock(){
if (locked){
while(1) { }
}
locked = 1;
}
Obviously that won't work if something else modifies locked
- once the while(1) {}
starts it won't stop. To fix that, you could use volatile int locked = 0;
.
This only prevents the compiler from assuming locked
didn't change. Nothing prevents a theoretical CPU from playing similar tricks (e.g. even if volatile
is used, a non-cache coherent CPU could not realize a different CPU altered locked
). For a guarantee you need to use atomics or something else (e.g. memory barriers).
However; with volatile int locked
it may work, especially for common 80x86 CPUs. Please note that "works" can be considered the worst possibility - it leads to assuming that the code is fine and then having a spectacular (and nearly impossible to debug due to timing issues) disaster when you compile the same code for a different CPU.
Upvotes: 2