4

I know about volatile variables that are defined at file scope. The compiler isn't allowed to make assumptions about these variables. They may be changed at nearly any time and the compile must not optimize out reads of the variable.

Now I found this code

BOOL InstallHandler()
{
    volatile BOOL b_bulk_erase = FALSE;
    volatile BOOL b_test_read_write = FALSE;
    volatile BOOL b_continue = TRUE;
    ...
    if (b_test_read_write)
    {
        read();
        write();
    }
}

How does the volatile corresponds to variables to the stack i.e. owned by one thread?

Edit:

With owned by one thread I wanted to express that the variable is not exposed. The address isn't given to anything else. It is not used by any other thread.

harper
  • 13,345
  • 8
  • 56
  • 105

2 Answers2

5

Ok, I realized the intention for that volatile.

The function is part of a device driver that communicates with a hardware device. The functions read and write are not used during normal operation.

But when the developer runs the program in a debugger she can set a breakpoint at the if clause and change the variable with the debugger. This will allow to manipulate the execution and to call to read and write.

The volatile inhibits the optimization that would be possible since the if clause tests a const expression. Without the volatile the whole if probably wouldn't be in the code.

harper
  • 13,345
  • 8
  • 56
  • 105
4

Simply because, while the variable itself is in a single thread, nothing stops you from giving its address to other threads. Hence unforeseeable modifications.

Quentin
  • 62,093
  • 7
  • 131
  • 191
  • 1
    Although if the variable is never the argument of the `&` operator, the compiler should be able to tell that this can't happen. – Barmar Jul 25 '14 at 11:22
  • 1
    @Barmar I'm not sure I understand your comment. Non-volatile is the all-time default. Shall the compiler treat each variable whose address is taken as volatile, the performance drawback would be awful. And unnecessary. `volatile` is here to tell the compiler "hey, please don't go crazy optimizing this variable, I intend to modify it behind your back". – Quentin Jul 25 '14 at 11:29
  • If you never take the address of the variable, how can you give its address to another thread? – Barmar Jul 25 '14 at 11:30
  • 1
    I didn't mean that all variables whose address is taken should be considered volatile. I meant that if the address is NOT taken, it can't be volatile. – Barmar Jul 25 '14 at 11:31
  • @Barmar I guess so (although I'm quite sure there's a far-fetched use case lurking somewhere), but I don't see how that's relevant to the question. Do you mean the compiler should ignore `volatile` were the variable's address not taken ? Note that the code in the question is not complete. And that I make no assumption whether `volatile` is useful therein ; I answered about the general case. – Quentin Jul 25 '14 at 11:40
  • It probably shouldn't ignore it, as the modifier implies that the programmer knows something the compiler doesn't. Although it's hard to imagine what that could be in this case. Maybe the programmer is intentionally writing outside array bounds, and knows that this will overflow into the volatile variable. – Barmar Jul 25 '14 at 11:44
  • @Barmar Implementation-flavoured foreign stack introspection, hooking on the first 3 bools of the stack frame ? Who knows. – Quentin Jul 25 '14 at 11:46
  • 1
    @Barmar You're making no sense. The question is about why a local might be declared volatile ... this answer that it matters if its address is taken. What the compiler can tell if its address isn't taken is irrelevant. And as noted in the comments above, there are other reasons for volatile locals even if their addresses aren't taken. – Jim Balter Jul 25 '14 at 11:54
  • What have threads got to do with volatile? In my opinion, volatile's sole purpose is to declare to the compiler that the value of a variable may be changed by an external agent. Another thread of the same program is not another agent, in this context. Also, volatile is *not* an acceptable tool for synchronization across threads, unless your compiler vendor specifically guarantees that volatile entails atomic access as well as acting as a memory fence (the standard doesn't). If you're sharing state across threads, proper thread sync primitives are mandatory (mutexes, semaphores, etc). – antred Dec 09 '15 at 16:49
  • @antred why wouldn't another thread be an external agent ? There can be incoherent r/w between threads. And the question is not whether `volatile`'s standard-specified behaviour is sufficient for thread synchronization (it's not), but why it is there in the first place. Which, given that standard-`volatile` is pretty useless, hints at the fact that the assumption of `volatile`s being atomic has already been made here. – Quentin Dec 09 '15 at 18:34
  • @Quentin Standard's volatile is not useless. It's just not useful as a threading tool. A particular compiler may make additional guarantees that indeed would make volatile useful for that purpose, but if your goal is to write portable code, volatile is utterly and completely useless as far as thread-shared data is concerned. – antred Jan 13 '16 at 16:53
  • @antred that is what I meant. – Quentin Jan 13 '16 at 21:21