Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

When multiple threads must access or make modifications to a common variable, they may also inadvertently access other variables adjacent in memory. This is an artifact of variables being stored compactly, with one byte possibly holding multiple variables, and is a common optimization on word-addressed machines. Bit-fields are especially prone to this behavior , since C is designed because compliers are allowed to store multiple bit-fields in one addressable byte or word. This implies that race conditions may exist not just on a variable accessed by multiple threads, but also on other variables sharing the same byte or word address.

A common tool for preventing race conditions in concurrent programming is the mutex. When properly observed by all threads, a mutex may can provide safe and secure access to a common variable, however, it guarantees nothing regarding other variables that might be accessed when a common variable is accessed.

Unfortunately there is no portable way to determine just what which adjacent variables are may be stored along with a certain variable.

...

Noncompliant Code Example (Bit Field)

In the following this noncompliant code example, two executing threads simultaneously access two separate members of a global struct.

Code Block
bgColor#FFcccc
struct multi_threaded_flags {
  unsigned int flag1 : 2;
  unsigned int flag2 : 2;
};

struct multi_threaded_flags flags;

void thread1(void) {
  flags.flag1 = 1;
}

void thread2(void) {
  flags.flag2 = 2;
}

...

Code Block
bgColor#ccccff
struct multi_threaded_flags {
  volatile unsigned int flag1 : 2;
  volatile unsigned int flag2 : 2;
};

union mtf_protect {
  struct multi_threaded_flags s;
  long padding;
};

static_assert(sizeof( long) >= sizeof( struct multi_threaded_flags));

struct mtf_mutex {
  union mtf_protect u;
  pthread_mutex_t mutex;
};

struct mtf_mutex flags;

void thread1(void) {
  pthread_mutex_lock(&flags.mutex);
  flags.u.s.flag1 = 1;
  pthread_mutex_unlock(&flags.mutex);
}

void thread2(void) {
  pthread_mutex_lock(&flags.mutex);
  flags.u.s.flag2 = 2;
  pthread_mutex_unlock(&flags.mutex);
}

Static assertions are discussed more thoroughly in detail in DCL03-C. Use a static assertion to test the value of a constant expression.

...

Although the race window is narrow, having an assignment or an expression evaluate improperly due to because of misinterpreted data can possibly result in a corrupted running state or unintended information disclosure.

...