RFC-0272:喚醒來源回報

RFC-0272:喚醒來源回報
狀態已接受
區域
  • 核心
說明

建議擴充 zx_system_suspend_enter,以便進一步說明為何暫停作業最終結束

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2025-05-23
審查日期 (年-月-日)2025-06-24

摘要

提案內容:擴充 zx_system_suspend_enter,為使用者模式提供系統呼叫傳回的所有具體原因,這些原因可能是剛退出暫停狀態,或是從未進入暫停狀態。

背景

進入低耗電狀態的最後一個步驟,是在為低耗電狀態設定平台特定的驅動程式和元件後,使用者模式目前可能會透過呼叫 zx_system_suspend_enter 要求核心進入低耗電狀態。接著,核心會採取必要步驟,將排程暫停,並將 CPU 停放在較低的電源狀態,直到發生下列任一情況為止:使用者提供的期限到期,或系統的一或多個「喚醒來源」收到信號。

喚醒來源

喚醒來源是核心物件,可在適當的訊號狀態下,喚醒系統 (或防止系統進入暫停狀態)。目前,Zircon 核心定義的喚醒來源物件,是使用 zx_interrupt_create 建立的實體中斷物件,並在選項欄位中傳遞 ZX_INTERRUPT_WAKE_VECTOR 標記。當與物件相關聯的硬體中斷發生時,系統會發出中斷喚醒來源信號,並持續發出信號,直到中斷喚醒來源遭到銷毀,或透過在物件上發布新的異步等待作業,或在物件上封鎖執行緒,明確確認中斷喚醒來源為止。

zx_system_suspend_enter 目前的行為。

zx_system_suspend_enter 目前會使用 2 個參數。資源符記和截止期限 (在啟動時間表中指定)。要求核心進入暫停狀態是透過存取資源符記 (必須是系統 CPU 資源) 所中介的特殊權限作業。如果無法傳送有效的資源符記,系統會傳回錯誤,並不會嘗試進入暫停狀態。

如果嘗試呼叫 zx_system_suspend_enter 的截止時間已過,系統會立即傳回狀態碼 ZX_ERR_TIMED_OUT。如果嘗試呼叫 zx_system_suspend_enter 的期限在未來,且任何喚醒來源物件已處於已發出信號的狀態,系統會立即傳回 ZX_ERR_BAD_STATE 狀態碼。最後,嘗試呼叫 zx_system_suspend_enter 時,如果未來的期限和沒有信號的喚醒來源,系統就會開始暫停所有 CPU 的程序。在這個程序開始或之後的任何時間點,如果指定的期限到期,或任何喚醒來源發出信號,CPU 就會從暫停狀態中移除,並傳回狀態碼 ZX_OK

術語

  • 喚醒來源:系統中的任何物件,在收到信號時,可讓系統從暫停狀態中喚醒,或防止系統進入暫停狀態。

  • 截止日期喚醒來源:這是僅存在於核心的特殊喚醒來源,當使用者為對 zx_system_suspend_enter 的呼叫提供截止日期時,系統會進入暫停狀態。

  • 喚醒來源報告項目:特定喚醒來源的資訊,詳細說明可能導致系統結束或無法進入休眠狀態的活動。

  • 喚醒來源報告:包含標頭和 Wake Source Report 項目陣列的資訊集,可能會從對 zx_system_suspend_enter 的呼叫傳回,用於向使用者說明退出或無法進入休眠狀態的原因。

  • 喚醒報表/喚醒報表項目:喚醒來源報表和喚醒來源報表項目的簡寫版本。

問題陳述

目前,雖然期限或任何喚醒來源都能將核心從暫停狀態中喚醒,但使用者模式無法判斷暫停作業完成的具體原因。

這會造成問題,尤其是在高度並行和非同步的系統中,即使只是從偵錯/診斷的角度來看也是如此。由於 Zircon 核心是所有這類邏輯的中心,且總是知道系統從暫停狀態釋放的確切原因,因此它應可發揮作用,協助使用者模式瞭解為何暫停狀態會遭到封鎖或終止。

相關人員

協助人員:

  • jamesr@google.com

審查者:

  • eieio@google.com
  • fmil@google.com
  • jmatt@google.com

諮詢:

  • maniscalco@google.com
  • surajmalhotra@google.com
  • jaeheon@google.com
  • mcgrathr@google.com

社會化:

我們在 2024 年底發布了一份初步文件,說明相關規定,並收到了意見回饋。之後,我們發布了更具體的 API 提案,並經過多輪的意見回饋,與各方利益相關者討論,最後成為本 RFC 的基礎。

需求條件

需求可分為兩種類型。功能需求 (使用者模式需要的內容) 和實作需求 (核心程式碼必須遵循的規則)。雖然特定核心實作方式的詳細資訊不在本文的討論範圍,但列出核心需求相當重要,可為部分設計決策提供背景資訊。

功能

1) 每當核心從對 zx_system_suspend_enter 的呼叫中返回時,都必須提供一種機制,讓呼叫端得知每個喚醒來源 (包括期限喚醒來源) 已發出信號,並且要嘛阻止系統進入暫停狀態,要嘛最終觸發暫停狀態結束。2) zx_system_suspend_enter 的使用者模式呼叫端必須收到喚醒來源的通知,但在報表機制產生報表時,已確認該喚醒來源。換句話說,喚醒來源會發出信號,並在呼叫結束時收到確認,這項事實也必須一併回報。3) 若有未經確認的喚醒來源,系統就無法進入休眠狀態。對於已確認的喚醒來源,等待回報的喚醒來源報表項目不會阻止系統進入休眠狀態。

實作

1) 系統中每個喚醒來源的喚醒報告產生作業所需的記憶體開銷必須保持不變。換句話說,在回報前多次傳送信號並確認的喚醒來源,不得需要無限量的儲存空間。相反地,喚醒來源的回報所需的儲存空間會在建立喚醒來源時支付,且不會隨著時間無限增長。2) 喚醒報告的產生作業可使用互斥功能進行序列化,並且需要 O(N) 的時間,其中 N 是系統中喚醒來源的數量。3) 產生喚醒報告時,請勿將中斷處理或喚醒來源訊號延遲超過 O(1) 秒。4) 一般系統中的喚醒來源總數應介於 10 到 20 之間。如果遇到超過 100 個的系統,就會令人驚訝。

設計

總覽

zx_system_suspend_enter 將擴充,讓使用者可將一組緩衝區傳遞至核心,以便使用典型的外部參數模式,將喚醒事件回報至使用者模式。核心會進行修改,以追蹤仍處於信號狀態或仍在等待回報的喚醒來源 (或兩者皆是)。為避免記憶體需求無上限,喚醒來源會追蹤下列項目:

  • 首次收到信號時。
  • 上次收到信號的時間。
  • 上次收到確認訊息的時間 (如果有)。
  • 信號傳遞次數。

這可讓喚醒來源隨意發出信號和確認信號,且仍可回報,而不需要任意數量的記憶體來儲存個別信號事件。核心會另外追蹤哪些喚醒報告項目已回報,並在喚醒來源收到信號、回報,然後在未先確認的情況下再次回報時,向使用者模式指出這項資訊。

API 變更

內核 API 的變更包括幾個結構體和標記的定義,以及 zx_system_suspend_enter 系統呼叫的定義變更。

結構體和旗標

#define ZX_SYSTEM_SUSPEND_OPTION_DISCARD      ((uint64_t)(1u << 0))
#define ZX_SYSTEM_SUSPEND_OPTION_REPORT_ONLY  ((uint64_t)(1u << 1))

typedef struct zx_wake_source_report_header {
  zx_instant_boot_t report_time;
  zx_instant_boot_t suspend_start_time;
  uint32_t total_wake_sources;
  uint32_t unreported_wake_report_entries;
} zx_wake_source_report_header_t;

#define ZX_SYSTEM_WAKE_REPORT_ENTRY_FLAG_SIGNALED            ((uint32_t)(1u << 0))
#define ZX_SYSTEM_WAKE_REPORT_ENTRY_FLAG_PREVIOUSLY_REPORTED ((uint32_t)(1u << 1))

typedef struct zx_wake_source_report_entry {
  zx_koid_t koid;
  char name[ZX_MAX_NAME_LEN];
  zx_instant_boot_t initial_signal_time;
  zx_instant_boot_t last_signal_time;
  zx_instant_boot_t last_ack_time;
  uint32_t signal_count;
  uint32_t flags;
} zx_wake_source_report_entry_t;

Syscall 變更

zx_system_suspend_enter 的定義將從以下內容變更:

zx_status_t zx_system_suspend_enter(zx_handle_t resource,
                                    zx_instant_boot_t resume_deadline);

收件者

zx_status_t zx_system_suspend_enter(zx_handle_t resource,
                                    zx_instant_boot_t resume_deadline,
                                    uint64_t options,
                                    zx_wake_source_report_header_t* out_header,
                                    zx_wake_source_report_entry_t* out_entries,
                                    uint32_t num_entries,
                                    uint32_t* actual_entries);

此外,系統也會變更狀態碼回報行為。截至目前,如果在暫停作業開始時,傳遞至呼叫的 resume_deadline 已過期,系統會傳回 ZX_ERR_TIMED_OUT,但如果在系統暫停的過程中,或在整個暫停過程中,逾期時間已過,系統會傳回 ZX_OK。此外,如果在暫停作業開始時有任何已發出訊號的喚醒來源,系統會傳回 ZX_ERR_BAD_STATE,但如果在系統暫停期間或系統已完全暫停後,有任何已發出訊號的喚醒來源,系統會傳回 ZX_OK

日後,系統會在所有情況下傳回 ZX_OK。系統會在報表標頭中傳回時間戳記 (suspend_start_time),通知使用者實際開始暫停的時間 (所有參數檢查完成後)。使用者可以根據報表中內部逾時喚醒來源是否有喚醒事件,偵測是否發生逾時情形,並比較使用者提供的逾時值與 suspend_start_time 的值,判斷是否已超過逾時時間。同樣地,使用者也可以透過檢查來源的喚醒報告項目的 last_signaled_timelast_ack_time (已定義時),並將其與傳回的 suspend_start_time 進行比較,瞭解是否在暫停作業開始前傳送喚醒來源信號。

索取報表

在要求核心進入休眠狀態時,使用者可以要求產生喚醒報告,方法是透過 out_header 參數傳遞緩衝區,以便包含喚醒報告標頭。使用者也可以傳遞緩衝區,以便在核心中填入喚醒來源報表項目陣列,但不一定要這麼做;如果只需要標頭,則只需傳遞標頭緩衝區即可。

目前必須提供三個參數才能接收報表項目:

  • out_entries:指向項目儲存空間的指標。
  • num_entries:表示項目儲存空間大小的數字。
  • actual_entries:指向緩衝區實際填入的項目數量的輸出參數指標。

雖然傳遞包含喚醒報表項目的緩衝區是選用的做法,但傳遞不一致的引數組合則是非法的。換句話說,使用者必須傳遞 out_entriesactual_entries 的有效指標,以及 num_entries 的非零值,或者必須傳遞 out_entriesactual_entries 的 nullptr,以及 num_entries 的零值。最後,雖然使用者只能要求標頭 (透過傳遞非空值 out_header,以及 (nullptr, 0, nullptr)out_entries, num_entries, actual_entries),但如果未傳遞 out_header 的有效指標,則無法傳遞有效參數來保留報表項目。如未遵守這些規則,系統會顯示狀態代碼 ZX_ERR_INVALID_ARGS,不會嘗試進入停權狀態,也不會產生報表。

使用者要求喚醒報表時,報表標頭會顯示兩個計數。首先,total_wake_sources 會回報系統中存在的喚醒來源總數 (包括內部期限喚醒來源),不論這些來源在報表產生時的狀態為何。

當使用者傳遞緩衝區來保留已回報的喚醒記錄項目時,該記錄最多只能在使用者緩衝區中回報 num_entries 個項目。實際回報的數字會儲存在 actual_entries out 參數中。使用者可以檢查標頭 unreported_wake_report_entries 中的第二個計數器,瞭解是否還有其他事件仍在等待回報 (因為使用者緩衝區中沒有足夠的空間可儲存事件)。

unreported_wake_report_entries 會回報喚醒報表項目的數量,這些項目需要在報表產生時回報,但不符合使用者緩衝區的限制,因此未回報。您可以透過後續對 zx_system_suspend_enter 的呼叫來擷取這些項目 (請參閱下方的「在不暫停的情況下要求報表」)。

請注意,喚醒來源可能會在報表產生後建立或銷毀,因為系統會暫停回溯呼叫,這表示 total_wake_sources 可能在呼叫傳回時不再反映系統層級喚醒來源的確切計數。同樣地,喚醒來源可以在解開期間發出信號 (或重新發出信號),增加待回報的喚醒報告項目數量,超出 unreported_wake_report_entries 在程序中指出的數量。

在不暫停帳戶的情況下索取報表。

使用者也可以在選項中傳遞 ZX_SYSTEM_SUSPEND_OPTION_REPORT_ONLY 標記,要求系統只產生報表。傳遞此標記後,系統不會嘗試暫停,且標頭中傳回的 suspend_start_time 會是 ZX_TIME_INFINITE。此外,在傳遞此旗標時,使用者至少必須傳遞緩衝區,以便保留報表標頭。否則系統會傳回 ZX_ERR_INVALID_ARGS 錯誤。另外請注意,即使只要求報表,仍需要仲介系統 CPU 資源。

這個標記的主要用途之一,是用於支援以下情況:呼叫端的事件緩衝區可能有有限或固定的記憶體量,而需要回報的事件數量超過緩衝區空間。請考慮以下情況:系統的緩衝區中只有 2 個事件的空間。它會呼叫暫停,並在暫停呼叫解開時,向 10 個來源發出信號並確認。系統會產生報表,並將 10 個事件中的 2 個傳回給使用者。為了排空剩餘事件,使用者需要多次回呼至暫停作業。沒有任何主動發出信號的喚醒來源可防止系統進入休眠狀態,因此使用者必須在過去的期限內強制通過,以免系統不小心再次進入休眠狀態。每次發生這種情況時,系統都會傳送及確認期限喚醒來源,並可能或不一定會重新回報 (取決於事件的列舉順序,未指定)。

在極端情況下,如果使用者緩衝區只允許一個事件,他們可能連進度都無法前進,因為截止時間來源的事件可能會一再回報。

報表標頭時間戳記

報表標頭會包含啟動時間表上的兩個時間戳記。report_time 是系統實際產生報表的時間 (在啟動時間軸上),發生時間是在系統調用函式解開,並在返回使用者模式之前。suspend_start_time 代表系統呼叫在暫停作業中提交的時間。喚醒事件表示來源在指定時間之後最後一次收到信號,或是表示來源在指定時間之前最後一次收到信號,但在指定時間之後才收到確認信號,這些來源必須在喚醒系統或防止系統進入休眠狀態方面發揮某種作用。

如果系統調用產生報表,但未嘗試進入暫停狀態,suspend_start_time 就會是 ZX_TIME_INFINITE

捨棄已確認的事件。

如果使用者不想收到喚醒報表項目,針對已發出信號但在呼叫 zx_system_suspend_enter 之前已確認的來源,使用者可能在呼叫 zx_system_suspend_enter 時傳遞選項欄位中的 ZX_SYSTEM_SUSPEND_OPTION_DISCARD 位元。在暫停作業開始時,如果喚醒來源的喚醒報告項目尚未回報,但目前未傳送信號 (例如已確認),則會視為已回報而遭到捨棄。

請注意,捨棄項目「不會」將目前已傳送信號的來源 (無論是否已收到確認) 標示為「已回報」。已發出信號的來源會防止系統進入暫停狀態,並且會向使用者回報 (如果有足夠空間),即使來源是在嘗試進入暫停狀態後,但在產生報表之前確認,也是如此。

在正常運作期間,系統可能會嘗試暫停,但在那之前,某些喚醒來源可能會收到信號並確認多次。選擇在作業開始時捨棄這些事件,或許有助於減少系統喚醒時實際上並未用到的事件數量,但這並非必要。

每個喚醒事件的回報資訊。

每個向使用者回報的喚醒事件都會包含下列欄位:

  • koid:這是已設為喚醒來源的核心物件 KOID,該來源已收到信號。做為 KOID,它會在系統生命週期內唯一識別特定物件。
  • name:一個 ZX_MAX_NAME_LEN 字元陣列,其中包含可供人類閱讀的字串,用於協助偵錯。名稱的具體格式未指定,因此實際工作邏輯不應使用。這項功能僅供內部開發和偵錯使用。由於 Zircon 中斷物件目前無法重新命名,因此系統會自動產生中斷物件的名稱。
  • initial_signal_time:在啟動時間表中,系統首次發出這個喚醒來源信號的時間。如果來源在回報前已確認並重新發出信號多次,initial_signal_time 就會保持不變,並記錄第一次發出信號的時間。
  • last_signal_time:在啟動時間軸上,此喚醒來源在回報前收到信號的最近時間。如果來源在回報前已確認並重新發出多次訊號,last_signal_time 會每次更新,並一律記錄喚醒來源最近一次發出訊號的時間。
  • last_ack_time:在啟動時間軸上,系統最近一次確認這個喚醒來源的時間。如果來源在回報前從未獲得確認,則此值為 ZX_TIME_INFINITE。如果喚醒來源多次傳送信號並確認,然後在回報前再傳送一次信號,last_ack_time 可能會小於 last_signal_time,但一律會大於或等於 initial_signal_time
  • signal_count:包含在初始和最後一次發出訊號之間,喚醒來源被發出訊號的次數。signal_count 一律會至少為 1,如果 signal_count 恰為 1,初始和最後信號時間的值會相同。
  • flags:包含兩個目前定義的旗標組合。

    • ZX_SYSTEM_WAKE_REPORT_ENTRY_FLAG_SIGNALED:表示在產生含有此項目的喚醒報表時,此喚醒報表項目的喚醒來源仍會發出信號 (尚未收到確認)。
    • ZX_SYSTEM_WAKE_REPORT_ENTRY_FLAG_PREVIOUSLY_REPORTED:表示這個喚醒報表項目已出現在先前的報表中。請注意,您無法查看先前回報但目前未發出信號的項目。如要加入等待回報的喚醒報告項目集合,喚醒信號必須發出,且喚醒報告項目的喚醒來源一經確認 (清除已發出信號位元) 並回報 (設定已回報位元),就會從集合中移除。

回報截止日期喚醒來源。

如果未來使用 resume_deadline 呼叫 zx_system_suspend_enter,且系統進入暫停狀態,只會在截止時間計時器喚醒時才會喚醒,系統會以特殊喚醒報告項目的形式向使用者回報這項資訊。這個項目的 koid 欄位會包含 ZX_KOID_KERNEL 值。此喚醒來源會自動獲得核心的確認;不需要採取任何特殊使用者模式動作來管理截止日期喚醒來源。

喚醒來源遭到破壞。

當使用者模式建立的喚醒來源遭到銷毀時,系統會隱含地確認,因此無法防止系統進入休眠狀態。此外,如果有待回報的喚醒來源已遭到摧毀,系統會立即從待回報的喚醒報表項目集合中移除該項目。

測試

喚醒報表產生功能的測試將在核心測試環境中使用單元測試進行。這些單元測試只能以核心測試的形式執行,因為如果有以實體中斷形式存在的平台專屬喚醒來源,則可能會導致報表產生的結果不具決定性。

除了在核心測試環境中執行之外,我們還需要新增一項內容來協助測試:非平台專屬的喚醒來源,可由測試程式碼發出信號並確認。物理中斷不符合這些要求。系統中是否有物理中斷是平台專屬的細節,我們無法依賴任意平台的任何特定組合。此外,物理中斷物件並非可由使用者模式強制觸發的物件。只能由相關聯的硬體觸發。

由於無法使用實體中斷,且目前系統中沒有其他類型的喚醒來源 (除了截止時間喚醒來源的特殊情況),因此我們打算推出專門用於測試的新類型喚醒來源。

虛擬中斷喚醒來源。

除了實體中斷物件外,Zircon 也支援「虛擬」中斷物件。虛擬中斷物件會參與與實體中斷相同的特殊情況信號,通常用於在單一驅動程式庫擁有中斷區塊,而其他幾個不相關的驅動程式使用區塊中斷時,需要解調中斷區塊的情況。目前最常見的情況是,GPIO 區塊會設為中斷,但不一定是唯一的情況 (例如,USB 中斷也可能會使用這些物件)。

與實體中斷不同,虛擬中斷只能由使用者模式程式碼 (透過呼叫 zx_interrupt_trigger) 以程式設計方式觸發。這些中斷是使用與實體中斷 (zx_interrupt_create) 相同的系統呼叫建立,但目前不需要有效的系統 IRQ 資源句柄即可建立 (實體中斷需要),且明確禁止建立為喚醒來源。

我們會在日後調整這些限制。具體來說,使用者可以建立虛擬中斷物件做為喚醒來源,但前提是他們必須提供系統 IRQ 資源的有效句柄。換句話說,建立虛擬中斷喚醒來源會被視為特權作業,由控制建立實體中斷物件的相同系統資源進行調解。即使沒有任何特殊權限,您仍可繼續建構非喚醒來源虛擬中斷。

這麼做可讓您編寫並在核心測試環境中執行一整套確定性的單元測試

成效

預期對成效的影響不大。在少數情況下,系統會在產生報表的同時發出喚醒來源信號,導致導致喚醒來源產生信號的中斷會需要與鎖定機制競爭,但報表產生作業不會永久保留鎖定機制,只會在足夠的時間內評估個別相關聯的喚醒報表項目狀態,並將內容複製到本機緩衝區,然後放棄鎖定機制並嘗試複製到使用者提供的緩衝區。

報表產生作業本身 (出於必要) 會耗費 O(N) 時間,在此期間,系統無法建立或刪除新的喚醒來源。這不會造成任何重大效能問題,因為絕大多數喚醒來源會在系統初始化期間建立,並在系統的整個生命週期中存在。

回溯相容性

這種做法會直接修改現有的系統呼叫,因此從 ABI 觀點來看,並未具備回溯相容性。不過,目前要修改的系統呼叫是 @next 的成員,仍在開發中,也就是說,不應有需要使用明確淘汰週期處理的外部依附元件。

程式碼庫中的現有呼叫網址可修改為將 0, nullptr, nullptr, 0, nullptr 傳遞為呼叫的預設值,這會保留系統目前的行為 (除了對傳回狀態碼行為的變更)。喚醒報表項目會在內部累積,但不會產生重大費用。

安全性考量

預期不會有重大安全性疑慮。虛擬喚醒來源中斷的引入方式,與物理喚醒來源中斷建立方式相同,都是透過資源符記進行調解。此外,所有對 zx_system_suspend_enter 的呼叫都已透過存取系統 CPU 權杖進行調解,因此系統會自動產生喚醒來源報告。

隱私權注意事項

無論是暫停系統或回報系統解除暫停的原因,都不會涉及任何 PII,因此沒有任何已知的隱私權疑慮。如果喚醒來源的觸發和確認時間資訊屬於「私密」資訊,使用者可以放心,因為產生報表的權限操作是由資源權杖調解。

說明文件

目前,zx_system_suspend_enter 是處於開發階段的 API,位於 @next 下方。因此,目前沒有正式的公開文件。短期內,喚醒來源回報的內部使用者將可使用內部設計文件、這份 RFC 和單元測試,做為特定行為和用法範例的參考資料。

在 Zircon 支援進入/退出暫停狀態,以及回報特定喚醒原因的穩定性後,我們會撰寫子系統最終表單的正式公開說明文件。假設在該時間點,這個喚醒來源回報機制仍存在,則預期會撰寫說明文件,反映這份 RFC 中所述的規則,以及在這段期間所做的任何變更。

考慮的替代方案

計時器喚醒來源

除了中斷之外,建立 Zircon Timer 物件並將其設為喚醒來源,也可能有助於實現某些實用功能。使用者可以在啟動時間表上安排截止時間,當計時器物件收到信號時,系統會將喚醒來源視為已收到信號,並一直維持這個狀態,直到計時器收到已取消或日後重新排定的信號為止。

基於以下幾個原因,我們目前決定不這麼做。1) 喚醒來源是功能強大的物件,可能會阻止系統進入休眠狀態,因此可能會遭到濫用。目前,與中斷不同,建立計時器時不需要提供明確的能力,這表示沒有任何可立即使用的做法,可將計時器喚醒來源的建構作業視為以句柄形式的能力所調解的特權作業。2) zx_system_suspend_enter 呼叫已支援截止期限。如果使用者模式需要支援任意數量的計時器,以便讓系統停止暫停,則可在具有呼叫 zx_system_suspend_enter 能力的元件層級實作簡單的計時器佇列。這也讓任何必要的能力模型,完全由使用者模式中的電源管理子系統控管。3) 最後,我們隨時可以回來完成這項操作。我們需要撰寫新的 RFC,以解決如何介入建立喚醒來源計時器的問題,但這裡提供的喚醒報告項目回報結構應足以回報計時器觸發的喚醒來源,就像處理中斷一樣。

以聯合或 TLV 為基礎的喚醒報告項目。

目前已修正喚醒報表項目的建議結構。在系統中,喚醒來源的類型有很多種,每種都有不同的重要細節,因此您可以想像,系統中會有不同類型的喚醒來源,而需要回報的資訊集合不會重疊。

在這樣的世界中,喚醒報表項目物件會是什麼樣子?一種可能的做法是將結構定義為具有型別列舉,以及各種不重疊資料集合的聯集。基本上,這是 std::variant 的 C ABI 版本。雖然這麼做是可行的,但會相當不便。目前系統中只有一種可由使用者建構的喚醒來源,因此不需要使用聯合。

如果我們想為未來 (未知) 的喚醒來源類型做好準備,就需要將聯集填充至盡可能大的大小 (也未知),以便在最終新增新的喚醒報表項目類型時,希望能維持聯集的固定大小。但在那一天到來時,我們可能無法預留足夠的空間,因此還是得強制改版介面,而預留的空間會在那一天到來前浪費掉。

同樣地,我們可以採用類型-長度-值 (TLV) 方法來編碼喚醒報告項目。這種做法不需要猜測「編碼喚醒事件的可能最大大小」,但會引入使用變數長度物件來源的核心 ABI,進而使用於序列化報表的核心程式碼和處理報表的使用者模式程式碼變得複雜。

歸根究柢,目前的固定喚醒報表項目定義既可用於現有用途 (中斷喚醒報表項目),也適用於唯一已知的未來潛在用途 (計時器喚醒來源),因此目前沒有理由採用更複雜的方法來複雜化事情。

其他使用者模式資訊。

視使用者模式如何使用回報的喚醒報表項目而定,允許使用者模式將二進位 blob (固定最大大小) 與喚醒來源建立關聯可能會帶來好處,這樣一來,系統在產生報表時,就會在喚醒報表項目中回報這項資訊。這可讓使用者模式透過喚醒來源物件「中繼」任意記帳,並將這些記帳轉入回報的喚醒報表項目。

雖然這項功能可能很實用,但使用喚醒報表功能的現有客戶表示他們不需要這項功能。回報的 KOID 就足夠了;它可做為不重複的索引鍵,可用於視需要查詢使用者模式記帳資訊。

不這樣做也表示我們不必擔心設計用於控管這類資訊的能力模型,也不必擔心惡意人士會透過喚醒來源回報取得私人記帳資訊,進而產生潛在的安全風險。

回報已毀壞的喚醒來源喚醒事件。

如前文所述,當喚醒來源遭到銷毀時,任何待回報的喚醒報表項目資訊都會立即銷毀,且永遠不會回報。我們是否應該改為堅持回報已銷毀的喚醒來源的喚醒報表項目?

雖然建議的行為表示在技術上可能無法將喚醒報告項目回報至使用者模式,但在一般用途情境中,這不會造成任何嚴重問題。目前喚醒來源一律為中斷,通常會在系統啟動初期分配,並在整個系統的生命週期內生效,也就是說,在正常運作期間不會遭到刪除。選擇立即移除所有待回報的喚醒事件記錄,是確保喚醒回報記憶體需求不會無限擴增的簡單方法,除非系統中發生下列情況:

建立喚醒來源 + 傳送信號。+ 摧毀它。+ 無限重複。

日後,如果推出的新喚醒來源會在例行作業期間定期建立及刪除,且可能會因刪除來源而導致喚醒報告輸入資訊遺失,導致問題發生,我們就會重新考慮這項決定。