Chris Young
Chris Young

Reputation: 61

In c++ can memory writes be delayed by optimization or do I need volatile?

I've read dozens of questions and answers here about the use of volatile and I apologize for posting yet another but I don't think I've seen exactly what I'm looking for.

I have a library written in C++ for Arduino microcontrollers. I have an ISR that fills a buffer and when it's finished it sets a flag to let the outside world know there is data available. I have the buffer, a variable telling how many bytes in the buffer, and the flag telling the world the buffer has data. Once I set that "I'm finished filling the buffer" flag in the ISR, the ISR will never change the buffer or its length again until/unless I reenable things.

Typically I have had the flag, the buffer, and the length value all declared volatile because that's what you're supposed to do in ISR routines.

However I do a lot of processing of that buffer once it is full and that means I'm cheating myself out of some potential optimizations. Outside my ISR if I had code that reads something like

if (flag== FINISHED) {
  disable_my_ISR (); 
   /*do a bunch of stuff with the buffer*/
  reenable_my_ISR();
}

Then theoretically I think I need not have my buffer as volatile. Is that correct? As I said my concern is that my "do a bunch of stuff with the buffer" is not getting optimized because the buffer is volatile.

The only other answer I've seen anywhere on this forum was this one however I'm not sure that's really the same circumstance.

Upvotes: 2

Views: 102

Answers (2)

slugonamission
slugonamission

Reputation: 9632

It's not even that the memory writes can be delayed by an optimisation - if your buffer is not declared volatile, your compiler can potentially remove any code using it. Take this example:

int myBuffer[5] = {0};
if(flag == FINISHED) {
    printf("%d", myBuffer[0]);
}

This may very well always print 0, even though your ISR changed the value of the buffer, because the compiler does not know how the ISR can change the program flow and hence assumes that myBuffer[0] will be 0 when it is used.

Upvotes: 2

Imbue
Imbue

Reputation: 3907

When you mark something as volatile you are saying that its value might change between writes/reads in your code. And that is exactly what can happen when an ISR accesses the variable, so you need volatile.

Any variable shared between your ISR and your main code should be volatile. Your code might work without marking everything, but it will come back to bite you eventually.

Then theoretically I think I need not have my buffer as volatile.

No, your buffer needs to be marked volatile if it is used by both your main code and your ISR. I think you're probably worrying too much about missing optimizations. You could always copy the volatile array into a normal array, do your processing, and time the difference.

Upvotes: 2

Related Questions