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 的类型(例如 private)和大小。 __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 可以是 private 或 shared。 Private 用于共享相同内存空间的进程,并且 futex 的虚拟地址对于所有进程都是相同的。 这允许内核中的优化。 要使用 private futex,需要在 futex 标志中指定 FUTEX_PRIVATE_FLAG
。 对于不共享相同内存空间,因此对于同一个 futex 可以有不同的虚拟地址的进程(例如,使用文件支持的共享内存),需要不同的内部机制才能正确排队。 这是默认行为,它适用于 private 和 shared futex。
Futex 可以是不同的大小:8、16、32 或 64 位。 目前,唯一支持的是 32 位大小的 futex,它需要使用 FUTEX_32
标志指定。