总结
唤醒一些等待 futex 的线程,并将更多 Waiter 移至另一个等待队列。
声明
#include <zircon/syscalls.h>
zx_status_t zx_futex_requeue(const zx_futex_t* value_ptr,
uint32_t wake_count,
zx_futex_t current_value,
const zx_futex_t* requeue_ptr,
uint32_t requeue_count,
zx_handle_t new_requeue_owner);
说明
重新加入队列是对唤醒的泛化。首先,内核会验证 current_value 中的值是否与 value_ptr 处的 futex 值匹配,如果不是,则报告 ZX_ERR_BAD_STATE
。唤醒 wake_count 线程后,requeue_count 线程会从原始 futex 的等待队列移至与另一个 futex requeue_ptr 对应的等待队列。
这种重新排队行为可用于避免醒来时有雷象群。
所有权
重新排队操作针对两个 futex,即唤醒 futex 和 requeue futex。下文将分别讨论每个功能对所有权的影响。通常,如果调用因任何原因失败,系统不会针对任一 futex 更改所有权。
如需了解详情,请参阅 futex 中的所有权和优先级继承。
对 wake futex 目标的影响
成功调用 zx_futex_requeue()
会导致 futex 的所有者被设为无任何值,无论唤醒计数是多少。如需转移 futex 的所有权,请改用 zx_futex_requeue_single_owner()
变体。zx_futex_requeue_single_owner()
会尝试从 futex 等待队列中仅唤醒一个线程。如果至少有一个线程要唤醒,futex 的所有者将被设置为已唤醒的线程。否则,Futex 将没有所有者。
对 requeue futex 目标的影响
如果成功调用 zx_futex_requeue()
或 zx_futex_requeue_single_owner()
,会导致 futex 的所有者被设置为 new_requeue_owner 句柄引用的线程;如果 new_requeue_owner 为 ZX_HANDLE_INVALID
,则不设置为任何值。
权限
无。
返回值
zx_futex_requeue()
会在成功时返回 ZX_OK
。
错误
ZX_ERR_INVALID_ARGS
以下情况之一为 true:
- value_ptr 或 requeue_ptr 不是有效的用户空间指针
- value_ptr 或 requeue_ptr 未与
sizeof(zx_futex_t)
边界对齐。 - value_ptr 与 requeue_ptr 是相同的 futex
- new_requeue_owner 当前是 value_ptr 或 requeue_ptr 的 Waiter 成员
- new_requeue_owner 尚未启动。
ZX_ERR_BAD_HANDLE
new_requeue_owner 不是 ZX_HANDLE_INVALID
,不是有效的句柄,并且 current_value 与 value_ptr 中的值匹配
ZX_ERR_WRONG_TYPE
new_requeue_owner 是有效的句柄,但不是线程的句柄。
ZX_ERR_BAD_STATE
current_value 与 value_ptr 中的值不匹配。