samedi 30 janvier 2016

In C11/C++11, possible to mix atomic/non-atomic ops on the same memory?

Is it possible to perform atomic and non-atomic ops on the same memory location?

I ask not because I actually want to do this, but because I'm trying to understand the C11/C++11 memory model. They define a "data race" like so:

The execution of a program contains a data race if it contains two conflicting actions in different threads, at least one of which is not atomic, and neither happens before the other. Any such data race results in undefined behavior. -- C11 §5.1.2.4 p25, C++11 § 1.10 p21

Its the "at least one of which is not atomic" part that is troubling me. If it weren't possible to mix them, it would just say "on an object which is not atomic."

I can't see any straightforward way of performing non-atomic operations on atomic variables. std::atomic<T> in C++ doesn't define any operations with non-atomic semantics. In C, all direct reads/writes of an atomic variable appear to be translated into atomic operations.

I suppose memcpy() and other direct memory operations might be a way of doing this?

For performing atomic operations on non-atomic variables, atomic_load() and atomic_store() in C11 seem like they might possibly work for this. The C11 standard doesn't appear to require that the argument you pass points to an atomic variable:

7.17.7.2 The atomic_load generic functions

Synopsis

#include <stdatomic.h>
C atomic_load(volatile A *object);
C atomic_load_explicit(volatile A *object, memory_order order);

Description

The order argument shall not be memory_order_release nor memory_order_acq_rel. Memory is affected according to the value of order. Returns Atomically returns the value pointed to by object.

I was able to compile a C11 program with GCC 5.2.1 that accepted an atomic_store() of a non-atomic variable.

However the same doesn't appear to be possible in C++11. std::atomic_store appears to only be defined for a std::atomic<T> parameter. I couldn't get a program to compile that called std::atomic_store() on a non-atomic variable.

So what is the story here? Is it really about memcpy()?

EDIT: I just thought of one other possible explanation. I remember reading in Stroustrup that initialization of an atomic variable is not atomic. I don't know where in the standard it says that, but perhaps that could be another example of a non-atomic operation on an atomic variable.

Aucun commentaire:

Enregistrer un commentaire