RFC-0077:改善 zx_clock_update 準確率

RFC-0077:提升 zx_clock_update 準確度
狀態已接受
區域
  • 核心
說明

對 zx_clock_update 的變更,可讓時鐘維護人員選擇提供更多資訊,並提高準確率。

問題
變更
作者
審查人員
提交日期 (年/月)2021-03-04
審查日期 (年/月)2021-03-18

摘要

zx_clock_update Syscall 是用來設定核心時鐘物件的時間,但目前的 API 設計會限制可能達到的準確率。這個 RFC 說明瞭 zx_clock_update 的變更,可讓時鐘維護人員選擇提供更多資訊並達到更高的準確率。

提振精神

核心時鐘物件會使用 zx_clock_update 系統呼叫來更新。時鐘維護人員可以設定 ZX_CLOCK_UPDATE_OPTION_VALUE_VALID,並在 zx_clock_update_args_v1_t.value 中放置新時間,以要求時鐘時間變更。

此 API 設計易於使用,但會限制設定新時鐘值時可能達到的準確度:在計算 zx_clock_update_args_v1_t.value 到呼叫 zx_clock_update 之間,使用者空間程序可能會被先佔,而在這兩個事件之間每 1 毫秒的延遲時間,則會導致時鐘收發 1 毫秒的錯誤。 這個錯誤與 UTC 整合的原因是系統整合發生問題,導致多次測試花絮,尤其是在錯誤可能幾百毫秒的模擬器上。請注意,zx_clock_update 也支援變更時鐘速率,但不必設定新值,而僅針對頻率更新可大幅降低出錯率。

這個 RFC 定義了 zx_clock_update 的新選項,可為世界標準時間 (UTC) 和其他未來核心時鐘的使用者提供更準確的時鐘。

設計

總覽

時鐘時鐘單調參考時間軸的單一維度仿造轉換,定義瞭如何根據時鐘轉譯「參照」時間 (即裝置的單調時鐘) 如何轉換成「合成」時間輸出內容。當時鐘維護人員要求變更時鐘時,他們可在這個轉換中有效地提供新的線段,如圖 1 所示。

圖 1:做為從參照到合成時間的轉換時鐘
此圖顯示 Y 軸的參照時間與合成時間之間的關係,顯示為多個線段,有些相鄰和有些不相交。

在現有設計中,時鐘維護器使用 zx_clock_update_args_v1_t.rate_adjust 提供這個線段的漸層,並使用 zx_clock_update_args_v1_t.value 提供片段開頭的 y 座標。核心會將片段開始的 x 座標設為處理 sys 呼叫時的單調時間。

這個區段開始的定義是由不同實體設定的兩個座標,是時鐘錯誤的根本原因,如圖 2 所示。

圖 2 - 計算與處理之間的延遲會導致時鐘錯誤
此圖說明 X 軸參照時間與 Y 軸的合成時間之間的預期關聯和實際相關性,但差異在於時鐘錯誤。

我們提議變更 zx_clock_update 引數,讓時鐘維護器完整指定其預期行,而核心會決定套用變更的參考時間,即這行的起始位置。

API 變更

我們推出了新的 zx_clock_update_args_v2_t 結構,其中包含目前 zx_clock_update_args_v1_t 中的所有欄位,加上額外的 reference_value 欄位。我們也會新增 ZX_CLOCK_UPDATE_OPTION_REFERENCE_VALUE_VALID 選項。

為了命名一致性,我們會將 zx_clock_update_args_v1_t 中的 value 欄位重新命名為 zx_clock_update_args_v2_t 中的 synthetic_value,並將 ZX_CLOCK_UPDATE_OPTION_VALUE_VALID 重新命名為 ZX_CLOCK_UPDATE_OPTION_SYNTHETIC_VALUE_VALID

為了方便起見,我們還定義了 ZX_CLOCK_UPDATE_OPTION_BOTH_VALUES_VALID,可用於設定 ZX_CLOCK_UPDATE_OPTION_REFERENCE_VALUE_VALIDZX_CLOCK_UPDATE_OPTION_SYNTHETIC_VALUE_VALID

行為變更

為了方便閱讀本節和後續章節,我們將使用 ZX_CLOCK_UPDATE_OPTION_X_VALID 縮寫為 X_VALID

REFERENCE_VALUE_VALIDSYNTHETIC_VALUE_VALIDRATE_ADJUST_VALID 全都已設定時,zx_clock_update 會在目前的參照時間開始新的線片段,將一個點 (reference=zx_clock_update_args_v2_t.reference_valuesynthetic=zx_clock_update_args_v2_t.synthetic_value) 與由 zx_clock_update_args_v2_t.rate_adjust 決定的漸層相交,如圖 3 所示。

圖 3 - 更新時鐘的值和速率
這張圖片說明如何指定參照時間、合成時間和漸層,藉此更新時鐘。

如果已設定 REFERENCE_VALUE_VALIDSYNTHETIC_VALUE_VALID,但未設定 RATE_ADJUST_VALIDzx_clock_update 會在目前的參考時間啟動新的線段,與一個點 (reference=zx_clock_update_args_v2_t.reference_valuesynthetic=zx_clock_update_args_v2_t.synthetic_value) 交集,並以先前時鐘速率決定的梯度,如圖 4 所示。

圖 4 - 僅更新時鐘值
這張圖片說明如何指定參照時間和合成時間來更新時鐘。

如果已設定 REFERENCE_VALUE_VALIDRATE_ADJUST_VALID,但並未設定 SYNTHETIC_VALUE_VALIDzx_clock_update 會在目前的參考時間啟動新的線段,將位於 reference=zx_clock_update_args_v2_t.reference_value 的點與 zx_clock_update_args_v2_t.rate_adjust 決定的漸層相交,如圖 5 所示。

圖 5 - 僅更新時鐘速率
這張圖片說明如何指定參考時間和更新率,藉此更新時鐘。

如果已設定 REFERENCE_VALUE_VALID,但未設定 RATE_ADJUST_VALIDSYNTHETIC_VALUE_VALIDzx_clock_update 會傳回 ZX_ERR_INVALID_ARGS 錯誤。

如未設定 REFERENCE_VALUE_VALIDzx_clock_update 會遵循現有行為,在目前的參照時間開始新的線區段;如果已設定 SYNTHETIC_VALUE_VALID,則綜合時間將合成時間變更為 zx_clock_update_args_v2_t.synthetic_value;如果已設定 RATE_ADJUST_VALID,則根據 zx_clock_update_args_v2_t.rate_adjust 變更漸層。

連續時鐘和單指時鐘

時鐘可能會在建立時設定 ZX_CLOCK_OPT_MONOTONIC 和/或 ZX_CLOCK_OPT_CONTINUOUS 選項,因此會限制可套用的更新。

ZX_CLOCK_OPT_CONTINUOUS 時鐘不接受任何步數變更。從圖 4、5 和圖 6 可以看出,REFERENCE_VALUE_VALID 一律會在合成值中導入不連續,因此為 ZX_CLOCK_OPT_CONTINUOUS 時鐘設定 REFERENCE_VALUE_VALID 一律會導致 ZX_ERR_INVALID_ARGS 錯誤。

如果時鐘採用 ZX_CLOCK_OPT_MONOTONIC 但不是 ZX_CLOCK_OPT_CONTINUOUS,則只有在導致綜合值增加時,系統才會接受步數變更。有些時鐘更新可能會導致競爭狀況,視要求到達核心的時間而定,可能會接受或拒絕要求。例如,在此 RFC 之前,假設在計算 zx_clock_update_args 及呼叫 zx_clock_update 之間,如果呼叫程序先佔超過 5 毫秒,系統就會將要求設定為未來時鐘 5 毫秒的要求遭到拒絕。

這項非確定性並不理想,因此在發生 ZX_CLOCK_OPT_MONOTONIC 時鐘時,下列zx_clock_update要求就會失敗並發生 ZX_ERR_INVALID_ARGS 錯誤:

  1. SYNTHETIC_VALUE_VALID 已設定,但未設定 REFERENCE_VALUE_VALID
  2. 已設定 RATE_ADJUST_VALID,且已設定 REFERENCE_VALUE_VALID

請注意,這代表無法在相同的 zx_clock_update 呼叫中同時變更 ZX_CLOCK_OPT_MONOTONIC 時鐘的速率和偏移量。

實作

這項變更將分為四個階段:

  1. 定義 zx_clock_update_args_v2_tZX_CLOCK_UPDATE_OPTION_REFERENCE_VALUE_VALIDZX_CLOCK_UPDATE_OPTION_BOTH_VALUES_VALID
  2. 更新 clock.cc 和相關單元測試以接受 zx_clock_update_args_v2_t
  3. 更新語言專屬的包裝函式 (例如 Rust 的 fuchsia-zircon),以使用 zx_clock_update_args_v2_t 並公開新功能。
  4. 更新時間 keeper,以便在設定世界標準時間時提供參照值,並減少允許的測試錯誤期間。

效能

這項變更對效能的影響較小,因為 zx_clock_update 系統呼叫並未大量使用,且變更內容相當簡單。

zx_clock_update_args 會增加 8 個位元組,如果已設定 ZX_CLOCK_UPDATE_OPTION_REFERENCE_VALUE_VALID,核心就會在處理 zx_clock_update 時執行更多整數算術指令。

安全性考量

這項變更不會變更時鐘維護人員與時鐘使用者之間的關係,因此不會影響安全性。

隱私權注意事項

這項變更不會改變時鐘維護器與時鐘使用者之間的關係,因此不會影響隱私權。

測試

我們將擴充 kernel-clocks.cc 中的單元測試,以涵蓋這個新行為。時間維護工具會以明確的單調時間更新為世界標準時間,因此現有的世界標準時間單元和整合測試都會提供額外的測試涵蓋範圍。

說明文件

zx_clock_update 參考說明文件將更新以說明這個新行為。

缺點、替代方案和未知

較簡單的替代做法,是保留現有的 zx_clock_update_args_v1_t 結構,但導入額外的 ZX_CLOCK_UPDATE_OPTION_ZERO_VALUE_VALID 選項來變更其解釋。如果設定了 ZX_CLOCK_UPDATE_OPTION_ZERO_VALUE_VALID,核心會將 zx_clock_update_args_v1_t.value 解讀為與 monotonic=0 對應的合成時間,並確保新的線段經過點 (monotonic=0synthetic=zx_clock_update_args_v1_t.value),如圖 6 所示。

圖 6:以合成偏移值為基礎的替代解決方案
此圖顯示 X 軸的參考時間和合成時間,並示範在 x=0 上使用位置和漸層設定。

這樣就能在 API 中以較小的變更完整指定新行。但是,對時鐘維護人員來說並不直觀,且需要更複雜的計算才能正確使用。在整個 Fuchsia 的生命週期內,我們相信這個替代方法會產生更多錯誤。

先前的圖片和參考資料

kernel_objects/clock 提供使用者空間時鐘的作業總覽。

世界標準時間同步處理演算法可摘要說明目前的 UTC 同步處理設計。

「Zircon Syscalls Struct Evolution」(Zircon Syscalls Struct Evolution) 是 Google 於 2019 年 5 月提供的內部文件,旨在探討系統呼叫結構的演進過程,對於有存取權的讀者可能有所幫助。