分析環(huán)境為centos惧辈,還有其他的futex_wait_private實(shí)現(xiàn)刨晴,這里暫時(shí)忽略。
brpc中bthread主線程的等待操作wait_task使用futex_wait_private實(shí)現(xiàn)。
futex_wait_private的具體實(shí)現(xiàn)使用了系統(tǒng)調(diào)用SYS_futex染厅。
SYS_futex的優(yōu)勢(shì)從名字“futex - fast user-space locking”就可以看的出來,詳細(xì)實(shí)現(xiàn)相關(guān)后續(xù)自己閱讀了解泉哈,暫時(shí)先明白用法蛉幸。
futex_wait_private等在brpc中實(shí)現(xiàn)
inline int futex_wait_private(
void* addr1, int expected, const timespec* timeout) {
return syscall(SYS_futex, addr1, (FUTEX_WAIT | FUTEX_PRIVATE_FLAG),
expected, timeout, NULL, 0);
}
inline int futex_wake_private(void* addr1, int nwake) {
return syscall(SYS_futex, addr1, (FUTEX_WAKE | FUTEX_PRIVATE_FLAG),
nwake, NULL, NULL, 0);
}
inline int futex_requeue_private(void* addr1, int nwake, void* addr2) {
return syscall(SYS_futex, addr1, (FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG),
nwake, NULL, addr2, 0);
}
futex說明:
NAME futex - fast user-space locking
long futex(uint32_t *uaddr, int futex_op, uint32_t val,
const struct timespec *timeout, /* or: uint32_t val2 */
uint32_t *uaddr2, uint32_t val3);
FUTEX_PRIVATE_FLAG (since Linux 2.6.22)
This option bit can be employed with all futex operations.
It tells the kernel that the futex is process-private and
not shared with another process (i.e., it is being used
for synchronization only between threads of the same
process). This allows the kernel to make some additional
performance optimizations.
As a convenience, <linux/futex.h> defines a set of
constants with the suffix _PRIVATE that are equivalents of
all of the operations listed below, but with the
FUTEX_PRIVATE_FLAG ORed into the constant value. Thus,
there are FUTEX_WAIT_PRIVATE, FUTEX_WAKE_PRIVATE, and so
on.
FUTEX_WAIT (since Linux 2.6.0)
This operation tests that the value at the futex word
pointed to by the address uaddr still contains the
expected value val, and if so, then sleeps waiting for a
FUTEX_WAKE operation on the futex word. The load of the
value of the futex word is an atomic memory access (i.e.,
using atomic machine instructions of the respective
architecture). This load, the comparison with the
expected value, and starting to sleep are performed
atomically and totally ordered with respect to other futex
operations on the same futex word. If the thread starts
to sleep, it is considered a waiter on this futex word.
If the futex value does not match val, then the call fails
immediately with the error EAGAIN.
The purpose of the comparison with the expected value is
to prevent lost wake-ups. If another thread changed the
value of the futex word after the calling thread decided
to block based on the prior value, and if the other thread
executed a FUTEX_WAKE operation (or similar wake-up) after
the value change and before this FUTEX_WAIT operation,
then the calling thread will observe the value change and
will not start to sleep.
FUTEX_WAKE (since Linux 2.6.0)
This operation wakes at most val of the waiters that are
waiting (e.g., inside FUTEX_WAIT) on the futex word at the
address uaddr. Most commonly, val is specified as either
1 (wake up a single waiter) or INT_MAX (wake up all
waiters). No guarantee is provided about which waiters
are awoken (e.g., a waiter with a higher scheduling
priority is not guaranteed to be awoken in preference to a
waiter with a lower priority).
The arguments timeout, uaddr2, and val3 are ignored.
FUTEX_REQUEUE (since Linux 2.6.0)
This operation performs the same task as FUTEX_CMP_REQUEUE
(see below), except that no check is made using the value
in val3. (The argument val3 is ignored.)
FUTEX_CMP_REQUEUE (since Linux 2.6.7)
This operation first checks whether the location uaddr
still contains the value val3. If not, the operation
fails with the error EAGAIN. Otherwise, the operation
wakes up a maximum of val waiters that are waiting on the
futex at uaddr. If there are more than val waiters, then
the remaining waiters are removed from the wait queue of
the source futex at uaddr and added to the wait queue of
the target futex at uaddr2. The val2 argument specifies
an upper limit on the number of waiters that are requeued
to the futex at uaddr2.
內(nèi)容參考:https://man7.org/linux/man-pages/man2/futex.2.html