views:

121

answers:

6

In C I have a pointer that is declared volatile and initialized null.

void* volatile pvoid;

Thread 1 is occasionally reading the pointer value to check if it is non-null. Thread 1 will not set the value of the pointer. Thread 2 will set the value of a pointer just once.

I believe I can get away without using a mutex or condition variable.
Is there any reason thread 1 will read a corrupted value or thread 2 will write a corrupted value?

A: 

On most platforms where a pointer value can be read/written in a single instruction, it either set or it isn't set yet. It can't be interrupted in the middle and contain a corrupted value. A mutex isn't needed on that kind of platform.

progrmr
That is not true on all platforms
jdehaan
What kind of platforms would this not work on? CPUs with 16 bit ints?
progrmr
Systems with non-32-bit memory accesses, which do exist, especially in DSP-land. Also where 32-bit memory accesses must be aligned and the value being accessed is misaligned.
Andrew Aylett
A: 

Unfortunately, you cannot portably make any assumptions about what is atomic in pure C.

GCC, however, does provide some atomic built-in functions that take care of using the proper instructions for many architectures for you. See Chapter 5.47 of the GCC manual for more information.

Matt B.
+2  A: 

In the case where the value fits in a single register, such as a memory aligned pointer, this is safe. In other cases where it might take more than one instruction to read or write the value, the read thread could get corrupted data. If you are not sure wether the read and write will take a single instruction in all usage scenarios, use atomic reads and writes.

drawnonward
Okay, so there's a chance on some platforms that it won't work nicely for pointer addresses. But your answer suggests it might be okay for checking if a boolean flag goes from 0 to non-zero, since even if the read value is corrupted, it might still return non-zero, and only after the write happens. If the corrupted value happens to be zero, then the checking thread just gets it on the next read. Yeah?
fsmc
The corruption would occur because the read interrupted the write and one or the other would take more than a single instruction. If your flag is a single byte then I cannot think of a case where it could be interrupted, but there is no guarantee about the flag and pointer being written serially. If you have atomic operations, they are a better choice than a flag.
drawnonward
A: 

Well this seems fine.. The only problem will happen in this case let thread A be your checking thread and B the modifying one.. The thing is that checking for equality is not atomic technically first the values should be copied to registers then checked and then restored. Lets assume that thread A has copied to register, now B decides to change the value , now the value of your variable changes. So when control goes back to A it will say it is not null even though it SHUD be according to when the thread was called. This seems harmless in this program but MIGHT cause problems..

Use a mutex.. simple enuf.. and u can be sure you dont have sync errors!

Ram Bhat
You always have the case that it can change after you look at it, whether you load it into a register or not.
progrmr
+3  A: 

To make it thread safe, you have to make atomic reads/writes to the variable, it being volatile is not safe in all timing situations. Under Win32 there are the Interlocked functions, under Linux you can build it yourself with assembly if you do not want to use the heavy weight mutexes and conditional variables.

If you are not against GPL then http://www.threadingbuildingblocks.org and its atomic<> template seems promising. The lib is cross platform.

jdehaan
I'm a little confused. How does a variable being volatile ensure that it is thread safe in the first place?
Ram Bhat
The involved memory barrier with volatile is essential for the atomic mechanism to work, but only a part of the whole.
jdehaan
A: 

Depends on your compiler, architecture and operating system. POSIX (since this question was tagged pthreads Im assuming we're not talking about windows or some other threading model) and C don't give enough constraints to have a portable answer to this question.

The safe assumption is of course to protect the access to the pointer with a mutex. However based on your description of the problem I wonder if pthread_once wouldn't be a better way to go. Granted there's not enough information in the question to say one way or the other.

Logan Capaldo