Do I need a fence or barrier or something when mutex locks/unlocks are buried deep in function calls?
Asked Answered
C

1

6

I recently learned that compilers will optimize your code by rearranging instructions, and that this can be controlled by using barriers.

IIRC, locking a mutex makes a barrier, and unlocking a mutex also makes a barrier, to keep code inside the critical section from getting out.

So pthread_mutex_lock and pthread_mutex_unlock must implicitly be these "barriers". What if I have a class like this, which wraps my mutex?

class IMutex {
public:
    virtual void lock() = 0;
    virtual void unlock() = 0;
};

it seems to me, the compiler won't know that I'm calling pthread_mutex_lock() inside lock(), and pthread_mutex_unlock() inside unlock(), because it's all virtual'd away.

Will this lead to bugs? Do I need to manually specify barriers somehow?

Collocate answered 30/3, 2013 at 19:52 Comment(2)
I think a function call would be a barrier to the compiler moving code. We use mutex's and do not add any barriers. There are memory barriers which are a different thing.Transpire
Yes, no sane compiler will reorder around a virtual function call...Gutenberg
D
6

Reordering instructions is done on various levels. The most obvious one is the compiler and a less obvious one is the CPU (which is on the fly). However synchronization functions are almost always a fence, which prevent that instructions before and after the fence are reordered.

So if your virtual lock calls pthread_mutex_*() then your virtual functions contains a fence.

So the short answer is: No, it will not lead to bugs.

There is also the volatile keyword, which depending on the platform can also generate a fence. However using the volatile keywords makes it a whole lot harder to detect those fences since every time you use a function or variable that is volatile you introduce a fence. So the advice is that you use the synchronization functions of the platform.

The only time you need to be aware of fences is when you are not using concurrency objects to perform synchronization (like using a bool instead of a mutex).

Deplume answered 8/4, 2013 at 10:53 Comment(2)
I would not recommend volatile on data members, as it may introduce a memory fence that, again, may hide a data race bug due to the "actual" mutex having some other bug... Use proper synchronization functions instead of volatile.Circumambulate
Thanks @Circumambulate I updated the answer to include your recommendation.Deplume

© 2022 - 2024 — McMap. All rights reserved.