Zircon 執行緒安全性註解

Zircon 程式碼利用 clang 的執行緒安全分析功能來 並透過機器驗證部分同步處理的不變體。這些 建構 Clang 時,會檢查註解 (請參閱 入門,瞭解建構應用程式的操作說明 clang)。

使用方法

Clang 說明文件

在 Zircon 中,我們提供一組用來包裝註解的巨集, 為同步基元加上註解。編寫與下列項目相關的新程式碼時 同步處理或為現有程式碼加上註解,因此在大部分的情況下,您應使用 執行緒註解巨集 <lib/zircon-internal/thread_annotations.h. 這些巨集的開頭為 "TA_" 是為了進行執行緒分析。最常出現 常用的功能包括:

  • TA_GUARDED(x):有功能 (例如鎖定) 會保護加註的變數x
  • TA_ACQ(x...) 函式會取得 x 組合中的所有互斥鎖,並在傳回後保留這些互斥鎖
  • TA_REL(x...) 函式會釋放 x 集合中的所有互斥鎖
  • TA_REQ(x...) 函式會要求呼叫端使用 x 組合中的所有互斥鎖
  • TA_EXCL(x...) 函式會規定呼叫端不得持有 x 組合中的任何互斥鎖

舉例來說,類別包含受保護成員變數 'int foo_' 保護的類別 Mutex 的註解如下:

// example.h

class Example {
public:
    // Public function has no locking requirements and thus needs no annotation.
    int IncreaseFoo(int by);

private:
    // This is an internal helper routine that can only be called with |lock_|
    // held. Calling this without holding |lock_| is a compile-time error.
    // Annotations like TA_REQ, TA_ACQ, TA_REL, etc are part of the function's
    // interface and must be on the function declaration, usually in the header,
    // not the definition.
    int IncreaseFooLocked(int by) TA_REQ(lock_);

    // This internal routine requires that both |lock_| and |foo_lock_| be held by the
    // caller.
    int IncreaseFooAndBarLocked(int foo_by, int bar_by) TA_REQ(lock_) TA_REQ(bar_lock_);

    // The TA_GUARDED(lock_) annotation on |foo_| means that |lock_| must be
    // held to read or write from |foo_|.
    int foo_ TA_GUARDED(lock_);

    // |lock_| can be declared after annotations referencing it,
    // if desired.
    Mutex lock_;

    Mutex bar_lock_;
};

// example.cpp

int Example::IncreaseFoo(int by) {
    int new_value;
    {
        AutoLock lock(&lock_);  // fbl::AutoLock is annotated
        new_value = IncreaseFooLocked(by);
    }
    return new_value;
}

請注意,如果註解允許一組互斥物件, 多次套用註解,或為 註解。換句話說,以下兩個宣告是相等的。

    int IncreaseFooAndBarLocked(int foo_by, int bar_by) TA_REQ(lock_) TA_REQ(bar_lock_);
    int IncreaseFooAndBarLocked(int foo_by, int bar_by) TA_REQ(lock_, bar_lock_);

透過 sysroot 公開的程式庫程式碼必須使用更奇怪的名稱 巨集是由 Google 提供的 system/public/zircon/compiler.h 避免與 sysroot 的消費者發生衝突。

最佳做法

註解必須與註解和 ID 相輔相成,以利程式碼 容易理解註解不會取代註解或清除名稱。請嘗試 編寫與鎖定相關的程式碼時,請遵循下列最佳做法:

  • 受鎖定功能保護的群組成員變數。運作位置 除了用註解來記錄受保護的內容之外 註解。例如,當多個成員變數受一個鎖定保護時 多個鎖定分別受到不同的鎖定方式保護 因此,相較於其他鎖定方式 逐一介紹各個註解

  • 為需要鎖定的函式命名,並加上「Locked()」尾碼。如果有 為呼叫函式可能顯示的多個鎖定類型 確保函式名稱中的選項撥打電話時應留意的讀者 你將無法看到註解

限制

執行緒安全分析是在編譯期間執行純靜態的檢查 無法理解有條件的鎖定或跨越區域的鎖定模式 編譯單元,以無法透過靜態註解表示。在許多 這項分析還是相當實用,但有些情況下 也無法理解停用分析的主要跳脫框架 是在函式定義中加入註解 TA_NO_THREAD_SAFETY_ANALYSIS 容易造成混淆其他逸出機制包括 也可使用,詳情請參閱 Clang 說明文件。情境 人類可能難以理解 以及機器,此時應附有註解指出

執行緒安全分析可透過許多方式破解,例如 如使用指標舉例來說,當您取得受到保護資料的地址時 成員 Clang 未追蹤警衛,例如受 Lock 保護的 foo_ 在不按住鎖頭的情況下,系統不會記錄到 memset(&foo_, 0, sizeof(foo_)) 的通話 違反 YouTube 政策。