futex2¶
- 作者:
André Almeida <andrealmeid@collabora.com>
futex,或快速用户互斥锁,是一组系统调用,允许用户空间创建高性能的同步机制,例如用户空间中的互斥锁、信号量和条件变量。C 标准库(如 glibc)使用它作为实现更高层次接口(如 pthreads)的手段。
futex2 是初始 futex 系统调用的后续版本,旨在克服原始接口的限制。
用户 API¶
futex_waitv()
¶
等待一个 futex 数组,唤醒任何一个
futex_waitv(struct futex_waitv *waiters, unsigned int nr_futexes,
unsigned int flags, struct timespec *timeout, clockid_t clockid)
struct futex_waitv {
__u64 val;
__u64 uaddr;
__u32 flags;
__u32 __reserved;
};
用户空间设置一个 struct futex_waitv 数组(最多 128 个条目),使用 uaddr
表示要等待的地址,val
表示期望的值,flags
表示类型(例如私有)和 futex 的大小。__reserved
需要为 0,但可以用于将来的扩展。数组中第一项的指针作为 waiters
传递。waiters
或任何 uaddr
的无效地址都会返回 -EFAULT
。
如果用户空间有 32 位指针,则应进行显式转换以确保高位为零。uintptr_t
可以处理技巧,并且适用于 32/64 位指针。
nr_futexes
指定数组的大小。超出 [1, 128] 区间的数字将使系统调用返回 -EINVAL
。
系统调用的 flags
参数需要为 0,但可以用于将来的扩展。
对于 waiters
数组中的每个条目,将 uaddr
的当前值与 val
进行比较。如果不同,系统调用将撤消到目前为止完成的所有工作并返回 -EAGAIN
。如果所有测试和验证都成功,系统调用将等待,直到发生以下情况之一
超时时间到期,返回
-ETIMEOUT
。信号发送到睡眠任务,返回
-ERESTARTSYS
。列表中某个 futex 被唤醒,返回某个被唤醒的 futex 的索引。
有关如何使用该接口的示例,请参见 tools/testing/selftests/futex/functional/futex_waitv.c
。
超时¶
struct timespec *timeout
参数是一个可选参数,指向绝对超时。您需要在 clockid
参数中指定使用的时钟类型。支持 CLOCK_MONOTONIC
和 CLOCK_REALTIME
。此系统调用仅接受 64 位 timespec 结构。
futex 的类型¶
futex 可以是私有的或共享的。私有用于共享同一内存空间的进程,所有进程的 futex 的虚拟地址将相同。这允许内核进行优化。要使用私有 futex,需要在 futex 标志中指定 FUTEX_PRIVATE_FLAG
。对于不共享同一内存空间,因此同一 futex 可能具有不同虚拟地址的进程(例如,使用文件支持的共享内存),需要不同的内部机制才能正确排队。这是默认行为,它适用于私有和共享 futex。
Futex 可以有不同的大小:8、16、32 或 64 位。目前,唯一支持的是 32 位大小的 futex,并且需要使用 FUTEX_32
标志指定。