...
| Code Block | ||||
|---|---|---|---|---|
| ||||
struct multi_threaded_flags {
unsigned char flag1;
unsigned char flag2;
};
struct multi_threaded_flags flags;
voidint *thread1(void *arg) {
flags.flag1 = 1;
return 0;
}
voidint *thread2(void *arg) {
flags.flag2 = 2;
return 0;
}
|
...
The same code is compliant when run on a C11-compliant platform. Unlike C99, C11 explicitly defines a memory location and provides the following note, in clause subclause 3.14.2 [ISO/IEC 9899:2011]:
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
struct multi_threaded_flags {
unsigned int flag1 : 2;
unsigned int flag2 : 2;
};
struct multi_threaded_flags flags;
voidint *thread1(void *arg) {
flags.flag1 = 1;
return 0;
}
void*int thread2(void *arg) {
flags.flag2 = 2;
return 0;
}
|
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <threads.h>
#include <assert.h>
struct multi_threaded_flags {
unsigned int flag1 : 2;
unsigned int flag2 : 2;
};
union mtf_protect {
struct multi_threaded_flags s;
long padding;
};
struct mtf_mutex {
union mtf_protect u;
mtx_t mutex;
};
struct mtf_mutex flags;
void chk_flags(void) {
static_assert(sizeof(long) >=
sizeof(struct multi_threaded_flags));
}
voidint *thread1(void *arg) {
if (thrd_success != mtx_lock(&flags.mutex)) {
/* Handle error */
}
flags.u.s.flag1 = 1;
if (thrd_success != mtx_unlock(&flags.mutex)) {
/* Handle error */
}
return 0;
}
voidint *thread2(void *arg) {
if (thrd_success != mtx_lock(&flags.mutex)) {
/* Handle error */
}
flags.u.s.flag2 = 2;
if (thrd_success != mtx_unlock(&flags.mutex)) {
/* Handle error */
}
return 0;
}
|
...
Bibliography
| [ISO/IEC 9899:2011] | Clause Subclause 3.14, "Memory Location" |
...