...
Code Block |
---|
|
struct multi_threaded_flags {
unsigned char flag1;
unsigned char flag2;
};
struct multi_threaded_flags flags;
void* thread1(void* arg) {
flags.flag1 = 1;
return 0;
}
void* thread2(void* arg) {
flags.flag2 = 2;
return 0;
}
|
...
Code Block |
---|
|
struct multi_threaded_flags {
unsigned int flag1 : 2;
unsigned int flag2 : 2;
};
struct multi_threaded_flags flags;
void* thread1(void* arg) {
flags.flag1 = 1;
return 0;
}
void* thread2(void* arg) {
flags.flag2 = 2;
return 0;
}
|
...
Code Block |
---|
Thread 1: register 0 = flags
Thread 1: register 0 &= ~mask(flag1)
Thread 2: register 0 = flags
Thread 2: register 0 &= ~mask(flag2)
Thread 1: register 0 |= 1 << shift(flag1)
Thread 1: flags = register 0
Thread 2: register 0 |= 2 << shift(flag2)
Thread 2: flags = register 0 |
Compliant Solution (Bit-field, C11, mutex)
This compliant solution protects all accesses of the flags with a mutex, thereby preventing any data races. Finally, the flags are embedded in a union alongside a long
, and a static assertion guarantees that the flags do not occupy more space than the long
. This technique prevents any data not checked by the mutex from being accessed or modified with the bit-fields on platforms that do not comply with C11.
Code Block |
---|
|
#include <threads.h>
struct multi_threaded_flags {
unsigned int flag1 : 2;
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;
mtx_t mutex;
};
struct mtf_mutex flags;
void* thread1(void* arg) {
int result;
if ((resultthrd_success != mtx_lock(&flags.mutex)) == thrd_error) {
/* Handle error */
}
flags.u.s.flag1 = 1;
if ((resultthrd_success != mtx_unlock(&flags.mutex)) == thrd_error) {
/* Handle error */
}
return 0;
}
void* thread2(void* arg) {
int result;
if ((resultthrd_success != mtx_lock(&flags.mutex)) == thrd_error) {
/* Handle error */
}
flags.u.s.flag2 = 2;
if ((resultthrd_success != mtx_unlock(&flags.mutex)) == thrd_error) {
/* Handle error */
}
return 0;
}
|
...