0

I'm creating a buffer to be accessed by some threads.

struct buffer {
   struct items[32];
   int numItems = 0;   /*will keep track of number of items in the buffer
};                       and will be updated by threads when accessed.
                         We'll include mutex locking*/

Should I declate buffer to be volatile or make numItems volatile?

What I'm thinking: My understanding is that volatile should be used to prevent compiler optimizations of operations between atomic access of the data by threads. Please correct me if I'm misunderstanding this

Thanks!

8protons
  • 3,591
  • 5
  • 32
  • 67
  • 2
    Do not attempt to use `volatile` for thread-safety. – Jonathan Leffler Nov 21 '16 at 00:33
  • 1
    Don't bother with volatile; it's useless if your goal is a correct multithreaded program. You'll need stronger juju (e.g. locks/mutexes/atomics) instead. http://stackoverflow.com/questions/2484980/why-is-volatile-not-considered-useful-in-multithreaded-c-or-c-programming – Jeremy Friesner Nov 21 '16 at 02:54
  • 1
    @JonathanLeffler The OPs concern isn't thread safety, but incorrect optimizations of variables that are used from inside threads (callback functions). – Lundin Nov 21 '16 at 09:33

2 Answers2

2

If you want to prevent the compiler from reordering, merging, or refetching reads or writes, use a volatile access (the uint8_t type is an example):

*(volatile uint8_t *) p = *(uint8_t  *) res;

If your type is aggregate and a single access isn't feasible, use memcpy with memory barriers before and after the call. You can organise these the same way Linux does with READ_ONCE/WRITE_ONCE, see here, and here.

The above is applicable even within critical sections, which your program should have anyway, since multiple threads are modifying shared state concurrently.

Michael Foukarakis
  • 39,737
  • 6
  • 87
  • 123
-3

Qualifier volatile is not used for multithreading.

If a variable is correctly protected by a mutex then it doesn't need to be defined with qualifiers volatile or atomic.

Variables protected by a mutex, or defined with the atomic qualifier, are recognized by the compiler and won't be optimized in a way that would change the output of the program.

As long as you use atomic primitives correctly, you don't need to worry about compiler optimizations that would remove writes or reads to shared variables. The compiler can still perform optimizations, but it may not change the intent (read:output) of the program.

2501
  • 25,460
  • 4
  • 47
  • 87
  • 2
    Source? What exactly is guaranteeing that variables protected by a mutex won't be optimized away? – Lundin Nov 21 '16 at 09:31
  • 1
    @2501, _multiple_ reads/writes can still be optimised inside critical sections, just not across critical section boundaries. – Michael Foukarakis Nov 21 '16 at 10:55
  • @Lundin Which claim is that? – 2501 Nov 21 '16 at 10:59
  • 1
    @2501, yes, very carefully. Variables aren't protected by mutexes, _operations_ are. – Michael Foukarakis Nov 21 '16 at 11:00
  • @Lundin What are you talking about? I'm still waiting for you to explain what is the 'claim', I'm supposedly making in my answer, which you're arguing against. – 2501 Nov 21 '16 at 11:05
  • "If a variable is correctly protected by a mutex then it doesn't need to be defined with qualifiers volatile or atomic." I find nothing in the C11 standard supporting this. – Lundin Nov 21 '16 at 11:54
  • @Lundin *I find nothing in the C11 standard supporting this.* Are mutexes even part of standard C? – Andrew Henle Nov 21 '16 at 13:11
  • @Lundin Do you think that variables in the critical section must also be defined as atomic variables? – 2501 Nov 21 '16 at 13:56
  • @AndrewHenle Yes they are since C11. Which is irrelevant in this case since the question was about pthreads. – Lundin Nov 21 '16 at 13:57
  • @2501 All I'm asking for is the source for the things stated in your answer. Since historically, there's been lots of compilers that have produced various optimizer hiccup bugs when faced with callback functions. For which the solution has been to declare variables shared with a callback as volatile. Now modern compilers are far better at detecting callbacks, so this might not be a problem in practice. But I haven't heard that compilers can detect mutex locks surrounding variable accesses at compile-time and adjust optimizations accordingly, let alone that some standard requires this. – Lundin Nov 21 '16 at 14:05
  • @Lundin What does that have to do with: *What exactly is guaranteeing that variables protected by a mutex won't be optimized away?* ? I feel like I'm talking to two different persons here. – 2501 Nov 21 '16 at 14:08
  • @Lundin Anyhow. I think your questions are addressed in the first 10 minutes of this great talk: http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 And yes optimizations are performed on all levels: compiler, processor, cache. – 2501 Nov 21 '16 at 14:30