Futex是一种用户态和内核态混合机制,所以需要两个部分合作完成,linux上提供了sys_futex系统调用,对进程竞争情况下的同步处理提供支持。
其原型和系统调用号为
#include <linux/futex.h>
#include <sys/time.h>
int futex (int *uaddr, int op, int val, const struct timespec *timeout,int *uaddr2, int val3);
#define __NR_futex 240
虽然参数有点长,其实常用的就是前面三个,后面的timeout大家都能理解,其他的也常被ignore。
uaddr就是用户态下共享内存的地址,里面存放的是一个对齐的整型计数器。
op存放着操作类型。定义的有5中,这里我简单的介绍一下两种,剩下的感兴趣的自己去man futex
FUTEX_WAIT: 原子性的检查uaddr中计数器的值是否为val,如果是则让进程休眠,直到FUTEX_WAKE或者超时(time-out)。也就是把进程挂到uaddr相对应的等待队列上去。
FUTEX_WAKE: 最多唤醒val个等待在uaddr上进程。
#include <sys/atomics.h>
#include<sys/mman.h>
volatile int * lock;
extern int futex (volatile int *uaddr, int op, int val, const struct timespec *timeout,int *uaddr2, int val3);
function init_lock() {
int fd = open("/lock", O_RDWR);
if (fd > 0) {
lock = (int*)mmap(0, 4, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, g_fd, 0);
if (lock)
lock[0] = 1;
}
}
}
void mutex_lock(volatile int *lock) {
futex(lock, FUTEX_WAIT, 0, 0, 0, 0);
__atomic_dec(lock);
}
void mutex_unlock(volatile int *lock) {
__atomic_inc(lock);
futex(lock, FUTEX_WAKE, 1, 0, 0, 0);
}