요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
======
futex2
======
:Author: André Almeida <andrealmeid@collabora.com>
futex, or fast user mutex, is a set of syscalls to allow userspace to create
performant synchronization mechanisms, such as mutexes, semaphores and
conditional variables in userspace. C standard libraries, like glibc, uses it
as a means to implement more high level interfaces like pthreads.
futex2 is a followup version of the initial futex syscall, designed to overcome
limitations of the original interface.
User API
========
``futex_waitv()``
-----------------
Wait on an array of futexes, wake on any::
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;
};
Userspace sets an array of struct futex_waitv (up to a max of 128 entries),
using ``uaddr`` for the address to wait for, ``val`` for the expected value
and ``flags`` to specify the type (e.g. private) and size of futex.
``__reserved`` needs to be 0, but it can be used for future extension. The
pointer for the first item of the array is passed as ``waiters``. An invalid
address for ``waiters`` or for any ``uaddr`` returns ``-EFAULT``.
If userspace has 32-bit pointers, it should do a explicit cast to make sure
the upper bits are zeroed. ``uintptr_t`` does the tricky and it works for
both 32/64-bit pointers.
``nr_futexes`` specifies the size of the array. Numbers out of [1, 128]
interval will make the syscall return ``-EINVAL``.
The ``flags`` argument of the syscall needs to be 0, but it can be used for
future extension.
For each entry in ``waiters`` array, the current value at ``uaddr`` is compared
to ``val``. If it's different, the syscall undo all the work done so far and
return ``-EAGAIN``. If all tests and verifications succeeds, syscall waits until
one of the following happens:
- The timeout expires, returning ``-ETIMEOUT``.
- A signal was sent to the sleeping task, returning ``-ERESTARTSYS``.
- Some futex at the list was woken, returning the index of some waked futex.
An example of how to use the interface can be found at ``tools/testing/selftests/futex/functional/futex_waitv.c``.
Timeout
-------
``struct timespec *timeout`` argument is an optional argument that points to an
absolute timeout. You need to specify the type of clock being used at
``clockid`` argument. ``CLOCK_MONOTONIC`` and ``CLOCK_REALTIME`` are supported.
This syscall accepts only 64bit timespec structs.
Types of futex
--------------
A futex can be either private or shared. Private is used for processes that
shares the same memory space and the virtual address of the futex will be the
same for all processes. This allows for optimizations in the kernel. To use
private futexes, it's necessary to specify ``FUTEX_PRIVATE_FLAG`` in the futex
flag. For processes that doesn't share the same memory space and therefore can
have different virtual addresses for the same futex (using, for instance, a
file-backed shared memory) requires different internal mechanisms to be get
properly enqueued. This is the default behavior, and it works with both private
and shared futexes.
Futexes can be of different sizes: 8, 16, 32 or 64 bits. Currently, the only
supported one is 32 bit sized futex, and it need to be specified using
``FUTEX_32`` flag.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
소개
1-16Futex(fast user mutex)는 userspace에서 mutex, semaphore, condition variable 같은 고성능 synchronization mechanism을 만들게 하는 syscall 집합입니다. glibc 같은 C standard library는 이를 사용해 pthreads 같은 higher-level interface를 구현합니다.
futex2는 최초 futex syscall의 한계를 극복하도록 설계한 후속 interface입니다.
Userspace synchronization과 library abstraction의 관계입니다.
.. SPDX-License-Identifier: GPL-2.0
======
futex2
======
:Author: André Almeida <andrealmeid@collabora.com>
futex, or fast user mutex, is a set of syscalls to allow userspace to create
performant synchronization mechanisms, such as mutexes, semaphores and
conditional variables in userspace. C standard libraries, like glibc, uses it
as a means to implement more high level interfaces like pthreads.
futex2 is a followup version of the initial futex syscall, designed to overcome
limitations of the original interface.
futex_waitv()와 waiter 배열
17-44`futex_waitv()`는 futex array를 기다리다가 그중 하나가 wake되면 반환합니다. Signature는 `futex_waitv(struct futex_waitv *waiters, unsigned int nr_futexes, unsigned int flags, struct timespec *timeout, clockid_t clockid)`입니다.
각 `struct futex_waitv` entry에는 expected value `val`, 기다릴 address `uaddr`, futex type과 size를 지정하는 `flags`, future extension용 `__reserved`가 있습니다. `__reserved`는 현재 0이어야 합니다.
Userspace는 최대 128개 entry의 array를 설정하고 첫 항목 pointer를 `waiters`로 전달합니다. `waiters` 또는 어느 `uaddr`라도 invalid address이면 `-EFAULT`를 반환합니다.
32-bit pointer를 쓰는 userspace는 upper bit가 0이 되도록 explicit cast해야 합니다. `uintptr_t`는 32-bit와 64-bit pointer에서 모두 올바르게 처리합니다.
Waiter 하나의 field 의미입니다.
User API
========
``futex_waitv()``
-----------------
Wait on an array of futexes, wake on any::
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;
};
Userspace sets an array of struct futex_waitv (up to a max of 128 entries),
using ``uaddr`` for the address to wait for, ``val`` for the expected value
and ``flags`` to specify the type (e.g. private) and size of futex.
``__reserved`` needs to be 0, but it can be used for future extension. The
pointer for the first item of the array is passed as ``waiters``. An invalid
address for ``waiters`` or for any ``uaddr`` returns ``-EFAULT``.
If userspace has 32-bit pointers, it should do a explicit cast to make sure
the upper bits are zeroed. ``uintptr_t`` does the tricky and it works for
both 32/64-bit pointers.
검증과 반환
45-62`nr_futexes`는 array size이며 [1, 128] 범위를 벗어나면 syscall은 `-EINVAL`을 반환합니다. Syscall 자체의 `flags` argument는 현재 0이어야 하지만 future extension에 쓸 수 있습니다.
Kernel은 `waiters`의 각 entry에서 `uaddr`의 current value를 `val`과 비교합니다. 하나라도 다르면 지금까지 한 작업을 모두 되돌리고 `-EAGAIN`을 반환합니다.
모든 검사와 검증이 성공하면 timeout expiry에는 `-ETIMEOUT`, sleeping task에 signal이 오면 `-ERESTARTSYS`, list의 futex 하나가 wake되면 wake된 futex 중 하나의 index를 반환합니다.
사용 예제는 `tools/testing/selftests/futex/functional/futex_waitv.c`에 있습니다.
모든 waiter를 원자적으로 확인한 뒤 하나의 event를 기다립니다.
조건별 return value입니다.
``nr_futexes`` specifies the size of the array. Numbers out of [1, 128]
interval will make the syscall return ``-EINVAL``.
The ``flags`` argument of the syscall needs to be 0, but it can be used for
future extension.
For each entry in ``waiters`` array, the current value at ``uaddr`` is compared
to ``val``. If it's different, the syscall undo all the work done so far and
return ``-EAGAIN``. If all tests and verifications succeeds, syscall waits until
one of the following happens:
- The timeout expires, returning ``-ETIMEOUT``.
- A signal was sent to the sleeping task, returning ``-ERESTARTSYS``.
- Some futex at the list was woken, returning the index of some waked futex.
An example of how to use the interface can be found at ``tools/testing/selftests/futex/functional/futex_waitv.c``.
Timeout
63-70`struct timespec *timeout`은 optional absolute timeout pointer입니다. `clockid`로 사용할 clock type을 지정하며 `CLOCK_MONOTONIC`과 `CLOCK_REALTIME`을 지원합니다.
이 syscall은 64-bit timespec struct만 받습니다.
시간 표현과 clock 선택입니다.
Timeout
-------
``struct timespec *timeout`` argument is an optional argument that points to an
absolute timeout. You need to specify the type of clock being used at
``clockid`` argument. ``CLOCK_MONOTONIC`` and ``CLOCK_REALTIME`` are supported.
This syscall accepts only 64bit timespec structs.
Private/shared 및 size
71-86Futex는 private 또는 shared일 수 있습니다. Private futex는 같은 memory space를 공유하여 모든 process에서 futex virtual address가 같은 경우에 사용하며 kernel optimization이 가능합니다. Futex flag에 `FUTEX_PRIVATE_FLAG`를 지정해야 합니다.
Memory space를 공유하지 않아 같은 futex가 서로 다른 virtual address를 가질 수 있는 process, 예를 들어 file-backed shared memory를 쓰는 경우에는 올바른 enqueue를 위한 다른 internal mechanism이 필요합니다. 이것이 default behavior이며 private와 shared futex 모두에서 동작합니다.
Futex size는 8, 16, 32, 64 bit일 수 있지만 현재 지원하는 것은 32-bit futex뿐이며 `FUTEX_32` flag로 지정해야 합니다.
Address relation과 flag를 비교합니다.
Types of futex
--------------
A futex can be either private or shared. Private is used for processes that
shares the same memory space and the virtual address of the futex will be the
same for all processes. This allows for optimizations in the kernel. To use
private futexes, it's necessary to specify ``FUTEX_PRIVATE_FLAG`` in the futex
flag. For processes that doesn't share the same memory space and therefore can
have different virtual addresses for the same futex (using, for instance, a
file-backed shared memory) requires different internal mechanisms to be get
properly enqueued. This is the default behavior, and it works with both private
and shared futexes.
Futexes can be of different sizes: 8, 16, 32 or 64 bits. Currently, the only
supported one is 32 bit sized futex, and it need to be specified using
``FUTEX_32`` flag.
요약·해설
futex2.rst:1-86futex_waitv waiter 배열, 검증 오류, timeout, private/shared futex와 지원 size를 설명합니다.
원문의 ABI symbol, error code, source path, 수치, code와 줄 좌표를 보존해 전문을 번역했습니다.