简体   繁体   中英

Guaranteeing the order of execution without using volatile or memory barrier and locks

I have Question regarding on compiler changing the order of execution. I am trying to improve performance of a multi-thread program (C language) by replacing the critical section with a signaling mechanism (thorugh semaphore).

I need to guarantee the order of execution here, and have been doing some research on this. I saw many questions on the order of execution within a function, but not much discussion on a function within a function.

Based on https://en.wikipedia.org/wiki/Sequence_point rules #4 , would the below code chunk guarantees that *p->a has to be evaluated first before func2 is entered since func2 takes p as an input (assuming the compiler adheres to the rules of schedule point defined here)?

func1 (struct *p) {
  p->a = x;  
  func2 (p);
}

func2 (struct *p) {
  p->b = y;
  releaseSemaphore(s);
}

It is critical that p->b is set only after p->a is set as another thread is in a loop processing various request and identifies a valid request by whether p->b is set. Releasing semaphore only triggers the task if it is idle (and waiting for the semaphore), but if it is busy processing other requests, it will check p->b later, and we cannot guarantee that func1 is called only when that thread is idle.

No. Sequence point ordering does not transition over thread boundaries. That is the whole point of why we need memory ordering guarantees in the first place.

The sequence point ordering is always guaranteed (modulo as-if-rule) for the thread which executes the code. Any other thread might observe the writes of that thread in an arbitrary order. This means that even if Thread #1 can verify that it performs writes in a certain order, Thread #2 might still observe them in a different order. That is why volatile is also not enough here.

Technically this can be explained eg. by caches. The writes by Thread #1 might go to a write buffer first, where they will still be invisible to Thread #2. Only once the write buffer is flushed back to main memory they become visible and the hardware is allowed to reorder the writes before flushing.

Note that just because the platform is allowed to reorder writes does not mean that it will. This is the dangerous part. Code that will run perfectly fine on one platform might break out of the blue when being ported to another. Using proper memory orderings guarantees that the code will work everywhere .

Implementation can 1 change the ordering as long as this isn't not done over function calls from other translation units.

Such reordering is orthogonal to multithreading, ie it is done in both singlethreaded and multithreaded programs.

If function func2 is in the same translation unit as func1, the execution could be done as if:

func1 (struct *p) 
{
    func2 (p);
    p->a = x;  
}

Use volatile iff you want to prevent 2 such reorderings. (Note that this is done to prevent reordering mentioned above, not for other synchronization purposes. You will have to use atomic primitives for those.)


1 (Quoted from: ISO/IEC 9899:201x 5.1.2.3 Program execution 10)
Alternatively, an implementation might perform various optimizations within each translation unit, such that the actual semantics would agree with the abstract semantics only when making function calls across translation unit boundaries.

2 (Quoted from: ISO/IEC 9899:201x 6.7.3 Type qualifiers 7)
An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Therefore any expression referring to such an object shall be evaluated strictly according to the rules of the abstract machine, as described in 5.1.2.3. Furthermore, at every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine, except as modified by the unknown factors mentioned previously.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM