Skip to content

Instantly share code, notes, and snippets.

@thestinger
Last active October 31, 2016 10:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thestinger/ceac2aff09578c92c844bdf5a4c70f30 to your computer and use it in GitHub Desktop.
Save thestinger/ceac2aff09578c92c844bdf5a4c70f30 to your computer and use it in GitHub Desktop.
#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);
}
}
#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