Last active
October 31, 2016 10:00
-
-
Save thestinger/ceac2aff09578c92c844bdf5a4c70f30 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <linux/futex.h> | |
#include <syscall.h> | |
#include <time.h> | |
#include <unistd.h> | |
#include "mutex.h" | |
#define unlikely(x) __builtin_expect(!!(x), 0) | |
static int sys_futex(void *uaddr, int op, int val1, struct timespec *timeout, void *uaddr2, | |
int val3) { | |
return syscall(SYS_futex, uaddr, op, val1, timeout, uaddr2, val3); | |
} | |
bool mutex_init(mutex *m) { | |
*m = 0; | |
return false; | |
} | |
bool mutex_trylock(mutex *m) { | |
int expected = 0; | |
return !atomic_compare_exchange_strong_explicit(m, &expected, 1, memory_order_acquire, | |
memory_order_relaxed); | |
} | |
void mutex_lock(mutex *m) { | |
int expected = 0; | |
if (unlikely(!atomic_compare_exchange_strong_explicit(m, &expected, 1, memory_order_acquire, | |
memory_order_relaxed))) { | |
if (expected != 2) { | |
expected = atomic_exchange_explicit(m, 2, memory_order_acquire); | |
} | |
while (expected) { | |
sys_futex(m, FUTEX_WAIT_PRIVATE, 2, NULL, NULL, 0); | |
expected = atomic_exchange_explicit(m, 2, memory_order_acquire); | |
} | |
} | |
} | |
void mutex_unlock(mutex *m) { | |
if (unlikely(atomic_fetch_sub_explicit(m, 1, memory_order_release) != 1)) { | |
atomic_store_explicit(m, 0, memory_order_release); | |
sys_futex(m, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdatomic.h> | |
#include <stdbool.h> | |
#define MUTEX_INITIALIZER 0 | |
typedef atomic_int mutex; | |
bool mutex_init(mutex *m); | |
bool mutex_trylock(mutex *m); | |
void mutex_lock(mutex *m); | |
void mutex_unlock(mutex *m); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment