Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler reordering around mutex boundaries?

Suppose I have my own non-inline functions LockMutex and UnlockMutex, which are using some proper mutex - such as boost - inside. How will the compiler know not to reorder other operations with regard to calls to the LockMutex and UnlockMutex? It can not possibly know how will I implement these functions in some other compilation unit.

void SomeClass::store(int i)
{
  LockMutex(_m);
  _field = i;  // could the compiler move this around?
  UnlockMutex(_m);
}

ps: One is supposed to use instances of classes for holding locks to guarantee unlocking. I have left this out to simplify the example.

like image 761
shojtsy Avatar asked Apr 22 '10 22:04

shojtsy


People also ask

How do I stop compiler reordering?

To prevent compiler reorderings at other times, you must use a compiler-specific barrier. GCC uses __asm__ __volatile__("":::"memory"); for this purpose. This is different from CPU reordering, a.k.a. the memory-ordering model.

Why do compilers reorder instructions?

Compiler and hardware try to reorder programs in order to improve their efficiency, while respecting dependencies.


4 Answers

It can not possibly know how will I implement these functions in some other compilation unit.

This is the key - since the compiler cannot know (in general) about the implementation of the function calls, it can't move the store to _field outside those function calls.

Generally, since _field is accessible outside of SomeClass::store() (it's not a local), the compiler can't know whether or not it's modified by the external function, therefore it must perform the store to _field between the function call sequence points.

The underlying hardware platform might need some attention in the form of memory barriers or cache flushes to deal with caching or out of order operations that occur in the hardware. The platform's implementation of the mutex APIs will deal with those issues if necessary.

like image 160
Michael Burr Avatar answered Sep 20 '22 06:09

Michael Burr


In general, a compiler will not move code around unless it knows with certainty that doing so will not affect run-time behavior.

like image 29
500 - Internal Server Error Avatar answered Sep 21 '22 06:09

500 - Internal Server Error


As it is written, if the functions are not inline, the compiler won't move the variable assignation, as the call may be unrelated to the _field variable, but it has to preserve the strict order of calls. If, however, the compiler decides to inline the calls, I think it will treat them as blocks of independent code, that is, it will only reorder instructions within the same code unit (the inlined function itself) but not with the following or preceding code (the assignation to the _field variable).

like image 26
Diego Sevilla Avatar answered Sep 20 '22 06:09

Diego Sevilla


You're right, that code is correct and safe. I did think of a "code joke," though.

pthread_mutex_lock( &mx ) + foo() + pthread_mutex_unlock( &mx );
like image 43
Potatoswatter Avatar answered Sep 21 '22 06:09

Potatoswatter