Using of "volatile sig_atomic_t "

Hi Community

If I have two threads which to compete together and one of these
threads are counting some event, and the other one are looking at this
counting variable and computing some result from this.

Is it useful to apply[color=green] “volatile sig_atomic_t counter ++” like using it
by signals? catchword atomic ?

Thank you !!!

Yes it is.

Thank You mario

and what is the justification for your answer?

if only one thread is modifing your global variable and others are only reading, you can do that as usual:

volatile uint32_t counter;

thread1(){

counter++;

}

thread2(){

if(counter>1000) {
/* do something */
}

}

If more than one threads have “modify” access to the variable, use atomic_* functions to modify the variable, i.e.
thread1(){

atomic_add(&counter, 1);

}

and if thread2() only reads counter (as in your example) leave it as is.

Eduard.

Thank you Eduard !!!

interesting fact, thanks !!!
what is the advantage of this?
why is it better?

Although in practice that’s true it may not be in theory. When a variable is not volatile, the compiler may decide to optimize the code. For example
int count;

thread1 () {
while ( foo > 5 ) {
count++;
}
printf(“count %d\n”, count );
}

thread2 ()
{
if ( count > 1000 ) {
printf(“timeout\n”);
}
}

In theory the compiler could look at thread1() and say oh, let’s optimize it (compiler doesn’t really know it’s a thread). Instead of accessing the value from memory every time. I will do this:

int count;

thread1 () {
//Load value from memory and put it in ebx register

while ( value == 1 ) {
count++; // increment ebx, this is faster then reading/writing to memory
}

printf(“count %d\n”, count ); // use ebx again

//Now as the fonction prepares to return it put the ebx value back in memory we are out the compiler will store eax into the count global variable.
}

That optimisation would make thread1() work perfectly and much faster (Saves a memory read and a memory read per loop).

Thread2() will only see count being greater then 1000 when the while loop of thread 1 is terminates. So it may appear like it’s working but in fact it’s not ;-)

In real life though this kind of optimisation rarely happens. Typicaly there would be a fonction call in the while loop and if the fonction call is in a different file or a library, the compiler can’t detect if count is access or not and thus will play it safe and assume it could be change by the fonction.

This can get even trickier if you put in pointer and pointer aliases ;-) So it comes down to: don’t really on specific compiler behavior, really on what the C or C++ code language says.

The rules says if a variable can be access by two or more routines from different context (threads/interrupt/variable in share mem etc) (imagine this can get worse if you run on multi-cpu/core) you must use volatile.

play by the rules and you will be safe (well almost), volatile doesn’t solve all problemes. They only apply to atomic type, for example volatile on long long (int64) on 32 bit OS are useless.

Thank you mario !!!

interesting fact too, thanks !!!