Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

If lock can prevent the use of volatile

How could I know a variable is read from memory not register without using volatile.

static uint64 counter;

void thread(void *arg){
  while(counter < (uint64)arg){
    acquire(&lock)
    counter++;
    release(&lock);
  }
}

I never doubt with that before, but if there’s compiler optimization, won’t it produce
bad result.
I also find the volatile is rare in xv6 kernel code, and I wonder is there some tricks to
suppress optimization through compiler’s command line to prevent use of volatile.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You don’t need volatile as long as your locking library is properly implemented – it will (by design) guarantee the correct behavior in spite of compiler optimizations, threads contending on the same resource, scheduling on other processors and cores, etc.

A properly-implemented acquire and release will guarantee that the compiler won’t produce bad reorderings, and more importantly, guarantee that a processor won’t produce bad reorderings (which can occur on some processor architectures).

One approach to doing this is with the use of barriers. I present it more as an explanation of how things work, and not as a recommendation to handwrite such synchronization code:

  • The acquire function includes a so-called memory barrier with "acquire semantics" – an acquire barrier means that any code following it (i.e. the code inside the critical section) must NOT be reordered to happen BEFORE the barrier. This means that any other threads and processors will necessarily see the acquisition of the lock before any of the writes from the critical section.

The release function provides an analogous memory barrier that prevents anything in the critical section from being reordered AFTER the barrier. This ensures that other threads will see the effects from the critical section BEFORE they see the lock being released.

Unless you are writing a low-level library and are prepared to thoroughly prove, verify, and test it, you should not be writing this kind of barrier code yourself. It’s very easy to make subtle mistakes, performance inefficiencies, etc.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading