Futex

NAME

futex - 建立使用者空間同步處理工具的基礎。

概要

futex 是快速使用者空間的 muTEX。這是低階同步基本功能,是較高層級 API (例如 pthread_mutex_tpthread_cond_t) 的建構模塊。

Futexes 的設計目的是不進入核心,或在未經競爭的情況中分配核心資源。

說明

Zircon futex 實作目前支援透過超過 6 個系統呼叫分散的三種作業:

    zx_status_t zx_futex_wait(const zx_futex_t* value_ptr,
                              zx_futex_t current_value,
                              zx_handle_t new_futex_owner,
                              zx_time_t deadline);
    zx_status_t zx_futex_wake(const zx_futex_t* value_ptr, uint32_t wake_count);
    zx_status_t zx_futex_wake_single_owner(const zx_futex_t* value_ptr);
    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);
    zx_status_t zx_futex_requeue_single_owner(const zx_futex_t* value_ptr,
                                              zx_futex_t current_value,
                                              const zx_futex_t* requeue_ptr,
                                              uint32_t requeue_count,
                                              zx_handle_t new_requeue_owner);
    zx_status_t zx_futex_get_owner(const zx_futex_t* value_ptr, uint64_t* koid);

以上所有項目都會共用 value_ptr 參數,也就是對齊的使用者空間整數的虛擬地址。這個虛擬位址是核心使用的資訊,用於追蹤特定執行緒等待中的項目。核心目前不會修改 *value_ptr 的值 (但會有日後可能執行的作業,請見下文)。至於使用者空間程式碼,必須正確地修改所有執行緒中的這個值,以建構互斥鎖等。

請注意,使用地址標記時,使用者空間指標不一定能同時與核心中的 futex 執行個體進行一對一對應。已移除架構專屬標記資訊的位址,會用於日後 ID。例如,在 ARM 中,如果已啟用 Top-Byte-Ignore (TBI),具有 0x0A000000FF123450 值的 futex 指標與值為 0x0B000000FF123450 的 futex 指標相同,因為儘管標記 (0x0A0x0B) 不同,其地址位元相同。

詳情請參閱 zx_futex_wait()zx_futex_wake()zx_futex_requeue()zx_futex_get_owner() 手冊頁面。

權利

Futex 物件沒有任何相關聯的權利。

使用者空間程式碼只能執行 2 種原始作業:等待和喚醒 (重新排入佇列是這兩者的組合)。由於未來程序僅是程序本機概念,撤銷任一項作業的存取權會導致日後功能毫無意義。

此外,從核心的角度來看,futexe 是暫時物件,狀態只會在 futex 有等候程序的情況下存在。如果核心中沒有更耐用的狀態,則更或更不可能針對未來性權利的持續概念。

與 Linux futexe 的差異

請注意,使用者空間指標虛擬位址中的所有 Zircon futex 作業金鑰。這與 Linux 實作不同,後者用於區分私人未來的作業 (對應至僅限程序中的運算),以及跨位址空間共用的。

如上所述,所有 futex 運算都會留下未透過核心修改的 Futex 值。其他可能的作業 (例如 Linux 的 FUTEX_WAKE_OP) 需要從核心中進行整體化的值,目前的實作並不需要。

擁有權和優先順序繼承

總覽

部分執行階段可能需要根據 futexe 的元件實作同步處理基本功能,這些基元表示優先繼承行為。為支援這些使用者,zircon futexes 有個「擁有權」概念,可用於實作這類原始物件。您可以選擇是否要使用這項功能。

未來任何時候,未來利潤可能是無人擁有,或由單一執行緒擁有。當執行緒擁有一或多個 futexe 時,有效優先順序會成為其基本優先順序的最大值,同時也是目前所有 futexe 目前等候者的優先順序。一旦一個執行緒不再擁有未來存在,那麼豆腐服務等候人員的壓力就會從上述關係中消失。一旦執行緒不再擁有任何舊項目,其優先順序就會放寬至基本優先順序。

模糊化擁有者信號負責使用者空間程式碼,正如建構需要優先繼承行為的特定同步物件時,要妥善套用擁有權概念。

Zircon futexe 最多只能有一位擁有者。不支援為了優先順序繼承的目的而針對 futexe 的多個擁有權。而且,同一名之前牛仔褲的主人永遠不能同時是同一人。

指派擁有權

系統會透過每項「等待」或「重新排入佇列」作業,指派 futex 擁有權。如果是重新佇列作業,目標 futex 是重新佇列 futex,而非 wake_futex。使用者會將控制代碼傳遞至執行緒,指出該執行緒目前的擁有者應由誰負責,如果不應的擁有者,則為 ZX_HANDLE_INVALID

  • 將有效的控制代碼傳遞至執行緒,表示該未來擁有者是使用者空間程式碼的責任。如果傳遞無效的控制代碼,或傳送至非執行緒物件的控制代碼,會導致等候/重新佇列作業失敗。
  • 尚未啟動的執行緒可能無法擁有未來性。只要嘗試將 futex 的擁有權指派給尚未啟動的執行緒,就會導致等待/重新排入佇列作業失敗。
  • 退出的討論串可能不是未來生活的擁有者。如果執行緒在擁有 futex 時結束,則系統會重設為無人擁有該執行緒。如果使用者嘗試將 futex 的擁有權指派給已經結束的執行緒,等待/重新佇列作業的行為會像是傳遞 ZX_HANDLE_INVALID 做為新 futex 擁有者的情況。
  • 如果等候/重新佇列作業成功,目標 futex 的擁有者「一律」會設為指定的執行緒;如果傳遞 ZX_HANDLE_INVALID,則不予設定。
  • 具體而言,如果因為預期的 futex 值與實際 futex 值不符,導致等候/重新佇列作業失敗,futex 的擁有者將維持不變,而作業的狀態碼將是 ZX_ERR_BAD_STATE。無論傳遞的值是否為代表擁有權的控制代碼,系統都會傳回此錯誤代碼,即使傳遞的值導致傳回 ZX_ERR_BAD_HANDLE 的狀態也是如此。

轉移擁有權

在 Wake 作業或重新佇列作業期間,核心可代表使用者轉移 Cutex 的擁有權。如果是重新佇列作業,移轉作業的目標為 Wake_futex,而非 requeue_futex。只有在使用 Wake/重新佇列作業的 zx_futex_wake_single_owner()zx_futex_requeue_single_owner() 變化版本時,系統才會執行擁有權轉移作業。這些作業的 single_owner 變體只會釋出一個等候程序,並將該錯誤的擁有權指派給已發布的執行緒。

  • 如果喚醒作業期間「沒有」等候程序,則目前沒有擁有者。這項異動將保持不變。
  • 如果重新佇列作業因為預期的 futex 值與實際未來值不相符而失敗,該函式的擁有者將維持不變。
  • 如果喚醒/重新佇列作業的非單獨擁有者變化版本呼叫,會導致目標 futex 的擁有者設定為無任何項目。

有關牛仔的紙

  • Fuss、Futexes 和 Furwocks:在 Linux 中快速鎖定使用者、Hubertus Franke 和 Rusty Russell

    這是說明 Linux futex 的原始白皮書。這項工具記錄了原始實作的記錄和設計,先前 (失敗) 嘗試建立快速的使用者空間同步處理原始物件,以及效能測量。

  • Futexes Are Tricky、Ulrich Drepper

    本文件說明 Linux 中可能存在的一些問題和實作詳細資料。本文會討論核心實作,並進一步說明互斥鎖、條件變數等正確且有效率的使用者空間實作方式。

  • 使用 Futexes 的互斥鎖和條件變數

    針對「Futexes 很有棘手」的論述,簡要說明一個簡單的實作方式,可避免使用 FUTEX_CMP_REQUEUE

  • 鎖定 WebKit、Filip Pizlo

    深入瞭解在 WebKit 中鎖定原始物件,並取得基準和分析的說明。包含「停車空間」概念的詳細說明,可讓您以非常精簡的方式呈現使用者空間互斥鎖。

音效