Compiler Intrinsics¶
Atomic Memory Access¶
Why is this code broken for multithreaded programs?
volatile int use_count;
void use_resource(void)
{
do_something_with_shared_resource();
use_count++;
}
Atomic Memory Access: Load/Modify/Store¶
Load-Modify-Store conflict
Classic form of a race condition
BTW:
volatile
is completely irrelevant!
CPU A |
CPU B |
Memory |
||
Instr |
Loc |
Instr |
Loc |
Glob |
load |
42 |
42 |
||
42 |
load |
42 |
42 |
|
inc |
43 |
42 |
||
43 |
inc |
43 |
42 |
|
43 |
store |
43 |
43 |
|
store |
43 |
43 |
43 |
Load/Modify/Store: Mutex¶
static pthread_mutex_t use_count_mutex =
PTHREAD_MUTEX_INITIALIZER;
int use_count;
void use_resource(void)
{
do_something_with_shared_resource();
pthread_mutex_lock(&use_count_mutex);
use_count++;
pthread_mutex_unlock(&use_count_mutex);
}
Drawback: mutexes are expensive (⟶ context switches)
Atomic Instructions¶
For simple integers there is a simpler way to atomicity (GCC only)
int use_count;
void use_resource(void)
{
do_something_with_shared_resource();
__sync_fetch_and_add(&use_count, 1);
}
More GCC “Builtins”¶
GCC has a sheer number of builtins …
Atomic operations
Arithmetic with overflow checking (built-in “functions” with a “success” return type)
Pointer bounds checking
Further Information