cmemoryx8664-bitvolatile

x64: Concurrent writes to bool array


Assuming I have an array like this in C:

static volatile bool my_array[128] = {0};

And on top of that I have 128 threads and each thread writes to a different index true whenever it is finished.

Can this produce some issues? Writing a single byte has no impact to the surrounding bytes on x64, right?

I'm just asking, because I'm not sure if the CPU / memory controller / etc. always reads 8 (or 4) bytes and then writes them. Which would create some weird race condition.

Thanks a lot


Solution

  • No two elements of the array are stored in the same memory location as defined by the C standard, so concurrent access or modification of separate elements of the array do not interfere with each other, as confirmed by C17 3.14 paragraph 2:

    3.14

    1. memory location

      either an object of scalar type, or a maximal sequence of adjacent bit-fields all having nonzero width

    2. Note 1 to entry: Two threads of execution can update and access separate memory locations without interfering with each other.

    The only thing to be careful of is the concurrent update of different bit-field members in a sequence of adjacent bit-fields all having nonzero width, as confirmed by the next paragraph of C17 3.14:

    1. Note 2 to entry: A bit-field and an adjacent non-bit-field member are in separate memory locations. The same applies to two bit-fields, if one is declared inside a nested structure declaration and the other is not, or if the two are separated by a zero-length bit-field declaration, or if they are separated by a non-bit-field member declaration. It is not safe to concurrently update two non-atomic bit-fields in the same structure if all members declared between them are also (nonzero-length) bit-fields, no matter what the sizes of those intervening bit-fields happen to be.

    (emphasis mine).

    The next paragraph of C17 3.14 provides an example:

    1. EXAMPLE A structure declared as

      struct {
            char a;
            int b:5, c:11,:0, d:8;
            struct { int ee:8; } e;
      }
      

      contains four separate memory locations: The member a, and bit-fields d and e.ee are each separate memory locations, and can be modified concurrently without interfering with each other. The bit-fields b and c together constitute the fourth memory location. The bit-fields b and c cannot be concurrently modified, but b and a, for example, can be.


    NOTE

    I speculate that concurrent access to different elements of a "packed" array, or to different members of a packed structure is potentially unsafe on some architectures, but that is outside the scope of the C specification.