'C: How to guard static variables in multithreaded environment?

Suppose having the following code elements working on a fifo buffer:

static uint_fast32_t buffer_start;
static uint_fast32_t buffer_end;
static mutex_t buffer_guard;

(...)

void buffer_write(uint8_t* data, uint_fast32_t len)
{
  uint_fast32_t pos;

  mutex_lock(buffer_guard);

  pos = buffer_end;
  buffer_end = buffer_end + len;

  (...) /* Wrap around buffer_end, fill in data */

  mutex_unlock(buffer_guard);
}

bool buffer_isempty(void)
{
  bool ret;
  mutex_lock(buffer_guard);
  ret = (buffer_start == buffer_end);
  mutex_unlock(buffer_guard);
  return ret;
}

This code might be running on an embedded system, with a RTOS, with the buffer_write() and buffer_isempty() functions called from different threads. The compiler has no means to know that the mutex_lock() and mutex_unlock() functions provided by the RTOS are working with a critical sections.

As the code is above, due to buffer_end being a static variable (local to the compilation unit), the compiler might choose to reorder accesses to it around function calls (at least as far as I understand the C standard, this seems possible to happen). So potentially the code performing buffer_end = buffer_end + len line have a chance to end up before the call to mutex_lock().

Using volatile on these variables (like static volatile uint_fast32_t buffer_end;) seems to resolve this as then they would be constrained by sequence points (which a mutex_lock() call is, due to being a function call).

  • Is my understanding right on these?
  • Is there a more appropriate means (than using volatile) of dealing with this type of problem?


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source