Lockless Access to Structure

To reiterate, we have the following data definitions:

struct foo {
    int a;
    int b;
};
struct foo static_foo = { 42, 17 };
struct foo *foo_p = &static_foo;

At some random point during runtime, the following code executes:

foo_p = NULL;

The question is whether readers can do the following:

p = foo_p;
if (p != NULL)
    do_something_with(p->a, p->b);

And the answer is that this does not work. The reason is that the compiler is within its rights to transform this code as follows:

if (foo_p != NULL)
    do_something_with(foo_p->a, foo_p->b);

This might in fact be an entirely reasonable transformation in cases of excessive register pressure. Entirely reasonable, that is, if the code was single-threaded. Unfortunately, this transformation can break multithreaded code. For example, if foo_p was set to NULL just after the if condition was evaluated, but before the arguments to do_something_with() were evaluated, the argument evaluation would segfault.

How to fix this? In the Linux kernel, you would use the ACCESS_ONCE() primitive as follows:

p = ACCESS_ONCE(foo_p);
if (p != NULL)
    do_something_with(p->a, p->b);

ACCESS_ONCE() is a volatile cast that prevents the compiler from refetching foo_p. Similar features are provided by the upcoming C and C++ standards. These standards must also deal with more challenging situations, such as making this sort of code work on an 8-bit CPU with 16-bit addressing, so that the machine is incapable of fetching or storing a pointer in a single access. But that is a topic for another time.