Apparent compiler bug involving volatile

Discussion to talk about software related topics only.
Post Reply
ScottM
Posts: 32
Joined: Mon Feb 01, 2010 10:00 am

Apparent compiler bug involving volatile

Post by ScottM »

It looks like volatile works fine if it's applied to an unsigned char, but if it's applied to a pointer to a pointer (at both levels of pointer), it gets ignored. I can reproduce the code if anyone is interested, but the take away is, if you want an interrupt handler to indicate to application code that the handler has completed, you're probably best off having the handler set a volatile unsigned char, and not count on anything more complex (especially involving pointers).

I have NNDK 2.4 RC2, which might be old.

Details: interrupt handler increments a pointer to pointer, A, stopping when *A == NULL. Application code loops until *A==NULL, with while (*A) ;. The end result is that the interrupts successfully advance A until *A == NULL, but the application code loops forever, apparently because the compiler doesn't believe that anything else can possibly change A, even when it's marked volatile. But if the code is changed to while (*A) complicated-iprintf(..); then it works, presumably because the printf clobbers enough registers that the compiler is forced to re-fetch A each time.
rnixon
Posts: 833
Joined: Thu Apr 24, 2008 3:59 pm

Re: Apparent compiler bug involving volatile

Post by rnixon »

How are you declaring the pointer as volatile? If I remember correctly:

volatile int *pI; is a non-volatile pointer to a volatile variable, the point is no volatile

int * volatile pI; is a volatile pointer to a non-volatile variable

volatile int * volatile pI; is a volatile pointer to a volatile variable

Not sure how to properly declare a volatile pointer to a volatile pointer to a volatile variable
roland.ames

Re: Apparent compiler bug involving volatile

Post by roland.ames »

rnixon wrote:
Not sure how to properly declare a volatile pointer to a volatile pointer to a volatile variable
You should just need a volatile pointer to a pointer to ...


eg.

int * * volatile A;

should do it (replace int with whatever you want)
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: Apparent compiler bug involving volatile

Post by tod »

Not sure how to properly declare a volatile pointer to a volatile pointer to a volatile variable
I don't think you can go wrong with

Code: Select all

volatile int * volatile * volatile X;
Which according to cdecl.org is "declare X as volatile pointer to volatile pointer to volatile int"

That said, a while back (years) there used to be a volatile optimization bug, dropping the optimization from -O2 to O1 fixed it. I doubt that bug is still around but it's easy to test.
ScottM
Posts: 32
Joined: Mon Feb 01, 2010 10:00 am

Re: Apparent compiler bug involving volatile

Post by ScottM »

I was using
int * volatile * volatile ppi;
where each interrupt would do a ++ppi if *ppi != NULL, and the app would check *ppi == NULL to know if the interrupt handler had finished all the work.

Once I realized I had a compiler bug, I made up a separate volatile unsigned char finished; for the interrupt hander to set nonzero when it got through the list of tasks, and life got much better.

I'm guessing I need to update my compiler. Thanks.
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: Apparent compiler bug involving volatile

Post by tod »

It's hard to know exactly what you are trying to achieve here without more of your code but this appears to me to be highly unlikely to work and it has nothing to do with volatile. ++ppi is not incrementing the value of the integer, it's incrementing the value of the pointer to the pointer. So now ppi has the value of a memory location (I believe 4 bytes past the old location). *ppi, then asks for the pointer stored at that location, and you're checking that that pointer isn't null. Is that what you intended?
ScottM
Posts: 32
Joined: Mon Feb 01, 2010 10:00 am

Re: Apparent compiler bug involving volatile

Post by ScottM »

tod wrote:It's hard to know exactly what you are trying to achieve here without more of your code but this appears to me to be highly unlikely to work and it has nothing to do with volatile. ++ppi is not incrementing the value of the integer, it's incrementing the value of the pointer to the pointer. So now ppi has the value of a memory location (I believe 4 bytes past the old location). *ppi, then asks for the pointer stored at that location, and you're checking that that pointer isn't null. Is that what you intended?
PinOperationWithDelay is a class that describes some operation I want done, in member function op(). It's subclassed for different operations.

PinOperationWithDelay* worklist[3] = {&op1, &op2, NULL};
is a list of two PinOperationWithDelay operations I want done, with NULL to mark the end of the list. I want one operation to occur at each interrupt.

PinOperationWithDelay** workToDo is set to worklist, when I want interrupts to start doing that work; then I turn on that interrupt.

In the interrupt handler:

if (*workToDo == NULL)
disable the interrupt and return; //we finished the work and don't need the interrupts any more
(*workToDo)->op(); // do whatever this unit of work is
++workToDo; //next time, do the next unit of work (ie, walk the array)
return;


It works fine. It causes the list of work to get done, one operation per interrupt. The code leaves out some details, like volatile, and the fact that PinOperationWithDelay objects also specify the time interval I want the next operation to occur at, so in the interrupt handler I'm also changing the time for the next interrupt. It all works as intended, and means I can pre-create lists of work, that have each operation executed at precise points in time. (I'm using this to bit bang one-wire, which requires timings in the microseconds range.)

The more usual approach, just turning off interrupts and doing a busy loop to get timing right, won't work in my case; I have other interrupts happening that can't be put off for that long.
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: Apparent compiler bug involving volatile

Post by tod »

OK I understand better now. I don't see why it wouldn't work although I must admit when I want to communicate this way between an interrupt and a task I use an OS facility like OSSemPend/OSSemPost. Using a shared resource without some sort of mutual exclusion technique can be fraught with peril, although I must admit I don't see anything wrong in the snippets provided. Maybe a dump with

m68k-elf-objdump -dS yourFile.od (from the debug src folder) might let you see the assembly. I thought the -S was supposed to intersperse source with assembley but it doesn't appear to be working for me.
ScottM
Posts: 32
Joined: Mon Feb 01, 2010 10:00 am

Re: Apparent compiler bug involving volatile

Post by ScottM »

tod wrote:OK I understand better now. I don't see why it wouldn't work although I must admit when I want to communicate this way between an interrupt and a task I use an OS facility like OSSemPend/OSSemPost. Using a shared resource without some sort of mutual exclusion technique can be fraught with peril, although I must admit I don't see anything wrong in the snippets provided. Maybe a dump with

m68k-elf-objdump -dS yourFile.od (from the debug src folder) might let you see the assembly. I thought the -S was supposed to intersperse source with assembley but it doesn't appear to be working for me.
Yup. I use OSSemPost in other situations; I just really, really wanted this to happen exactly when the interrupt went off, without dragging thread switches into it. The interrupt code always worked just fine; the only problem was having the app-level code monitoring *workToDo == NULL to know when the work was complete. Marking worktToDo and *workToDo as volatile should have made it work, but I hit an optimizer bug. Using a separate volatile unsigned char as "work is done" flag got around it.
Post Reply