简体   繁体   中英

C11 stdatomic and calloc

I've got a structure that contains an atomic field:

#include <stdatomic.h>

struct s {
    ...
    atomic_int a;
};

This structure is allocated with calloc :

struct s *p = calloc(1, sizeof(struct s));

Is it portable to expect p->a to be initialised to 0? There are enough barriers in the code so that weakly consistent initialisation is fine, but is the initial value guaranteed to be 0?

No, this is not portable in general. calloc only guarantees a byte-wise 0 value of the underlying object. For types that (may) have a state this is not equivalent to an initialization. You definitively have to use atomic_init to put your object into a valid state.

The reason for this are platforms that hold a "lock" in addition to the base object because they don't implement the corresponding assembler instruction. So to be portable you really need to use ATOMIC_VAR_INIT or atomic_init for all atomic objects that are not statically allocated.

That said, I don't know of any existing platform that would need such cruft for atomic_int . If your platform has ATOMIC_INT_LOCK_FREE set to 2 and sizeof(atomic_int)==sizeof(int) , you can be relatively sure that your strategy works. You could test that in a _Static_assert .

My guess is that this is not portable/safe.

It's very likely that calloc() end up doing a simple memset() on the memory area. This simple memset() would not issue the required memory barriers to ensure that other threads reading the structure would see the p->a as 0 .

struct s *p = calloc(1, sizeof(struct s));
struct s *q = p;
// some other thread
foo(*q);

The initialization to zero is accounted for before p or any of its assginees can access the memory. It is 0 .

Also see deferred zero-ing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM