英語

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_MONOTONICCLOCK_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 標誌指定。