Flowmotion
Flowmotion

Reputation: 163

would this be a functioning spinlock in c?

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

Answers (1)

Brendan
Brendan

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

Related Questions