| 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時提供期限,達到期限時可能會進入暫停狀態。喚醒來源報表項目:特定喚醒來源的相關資訊,詳細說明可能導致終止或無法進入暫停狀態的活動。
喚醒來源報告:這組資訊包括標頭和喚醒來源報告項目陣列,可能會從
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;
系統呼叫變更
「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_time 和 last_ack_time (如有定義),並與傳回的 suspend_start_time 比較,判斷喚醒來源是否在暫停作業開始前發出信號。
索取報告
要求核心進入暫停狀態時,使用者可以透過 out_header 參數傳遞緩衝區,要求系統產生喚醒報告標頭。使用者可以傳遞緩衝區,內含要由核心填入的喚醒來源報表項目陣列,但不必這麼做;如果只需要標頭,則只需要傳遞標頭緩衝區。
目前必須提供下列三個參數,才能接收報表項目:
out_entries:項目儲存空間的指標。num_entries:指出項目儲存空間大小的數字。actual_entries:輸出參數指標,指向緩衝區中實際填入的項目數。
雖然傳遞緩衝區來包含喚醒報告項目是選用做法,但傳遞不一致的引數集來執行此操作並不合法。換句話說,使用者必須為 out_entries 和 actual_entries 傳遞有效指標,並為 num_entries 傳遞非零值,否則必須為 out_entries 和 actual_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
是實際產生報告的時間 (在啟動時間軸上),也就是系統呼叫 unwinds 時,以及即將返回使用者模式前。suspend_start_time 代表系統呼叫提交暫停作業的時間。如果來源是在這個時間之後發出訊號,或是來源是在這個時間之前發出訊號,但是在這個時間之後確認,則這些來源必定在喚醒系統或防止系統進入暫停狀態方面扮演某種角色。
如果系統呼叫因任何原因產生報表,但完全沒有嘗試進入暫停狀態,suspend_start_time就會是 ZX_TIME_INFINITE。
捨棄已確認的事件。
如果使用者不希望收到來源的喚醒報告項目,但來源已發出信號,且在呼叫 zx_system_suspend_enter 前已確認,則呼叫 zx_system_suspend_enter 時,可以在選項欄位中傳遞 ZX_SYSTEM_SUSPEND_OPTION_DISCARD 位元。暫停作業開始時,系統會捨棄任何尚未回報但目前未發出信號 (例如已確認) 的喚醒來源喚醒報告項目,如同該項目已回報。
請注意,捨棄項目不會將目前已標記的來源項目 (無論先前是否已確認) 標示為「已回報」。系統會將發出信號的來源回報給使用者 (如果空間允許),並防止系統進入暫停狀態。即使來源在嘗試進入暫停狀態後,但在產生報表前獲得確認,系統仍會回報來源。
在系統嘗試暫停之前,某些喚醒來源可能會多次發出信號並獲得確認,這是正常現象。在作業開始時選擇捨棄這些事件,可能有助於減少需要回報的事件數量 (這些事件實際上並未喚醒系統),但這項操作並非必要。
回報每個喚醒事件的資訊。
向使用者回報的每個喚醒事件都會包含下列欄位:
koid- This is the KOID of the 核心物件 configured as a wake source which became signaled. KOID 是系統生命週期內特定物件的專屬 ID。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一律至少為一,如果signal_count正好為一,初始和最後的信號時間會是相同的值。flags- 包含目前定義的兩個旗標組合。ZX_SYSTEM_WAKE_REPORT_ENTRY_FLAG_SIGNALED- Indicates that the wake source for this wake report entry was still signaled (has not yet been acknowledged) at the time that the wake report containing this entry was generated.ZX_SYSTEM_WAKE_REPORT_ENTRY_FLAG_PREVIOUSLY_REPORTED- 表示這項喚醒報告項目已出現在先前的報告中。請注意,如果項目先前曾遭檢舉,但目前未標示為違規,您就無法查看該項目。如要加入等待回報的喚醒報告項目集,必須發出喚醒信號,且喚醒報告項目的喚醒來源一經確認 (清除信號位元) 及回報 (設定回報位元),就會從該集合中移除。
回報 Deadline Wake Source。
日後使用 resume_deadline 呼叫 zx_system_suspend_enter 時,如果系統進入暫停狀態,但因截止時間計時器而喚醒,系統會以特殊喚醒報告項目的形式向使用者回報。這個項目的 koid 欄位會包含 ZX_KOID_KERNEL 值。核心會自動確認這個喚醒來源,因此不需要採取任何特殊的使用者模式動作來管理期限喚醒來源。
破壞喚醒來源。
當使用者模式建立的喚醒來源遭到毀損時,系統會隱含確認,因此不會阻止系統進入暫停狀態。此外,如果待回報的喚醒報告項目是針對已毀損的喚醒來源,系統會立即從待回報的喚醒報告項目集中移除該項目。
測試
喚醒報告生成測試會在核心測試環境中,使用單元測試完成。這些單元測試只能以核心測試的形式可靠執行,否則平台特定的喚醒來源 (實體中斷的形式) 可能會導致報表產生非決定性結果。
除了在核心測試環境中執行,我們還需要新增一項內容,以利測試:非平台專屬的喚醒來源,可由測試程式碼發出信號並確認。實體中斷不符合這些規定。系統中是否存在實體中斷是平台專屬的詳細資料,我們無法依賴任何特定中斷集,適用於任意平台。此外,實體中斷物件無法由使用者模式強制觸發。只能由相關聯的硬體觸發。
由於無法使用實體中斷,且系統目前未定義其他類型的喚醒來源 (截止時間喚醒來源的特殊情況除外),我們計畫導入專為測試設計的新型喚醒來源。
虛擬中斷喚醒來源。
除了實體中斷物件,Zircon 也支援「虛擬」中斷物件。虛擬中斷物件會參與實體中斷的相同特殊情況信號,通常用於需要將中斷區塊解多工的情況,以便在一個驅動程式庫擁有中斷區塊,而其他幾個不相關的驅動程式使用該區塊中的中斷時,維持程序隔離。目前最常見的情況是將 GPIO 區塊設定為中斷,但這並非唯一情況 (例如,USB 中斷也可能使用這些物件)。
與實體中斷不同,虛擬中斷只能由使用者模式程式碼以程式輔助方式觸發 (透過呼叫 zx_interrupt_trigger)。虛擬中斷是使用與實體中斷相同的系統呼叫 (zx_interrupt_create) 建立,但目前不需要系統 IRQ 資源的有效控制代碼即可建立 (實體中斷則需要),且明確禁止建立為喚醒來源。
我們將調整這些限制。具體來說,使用者可以建立虛擬中斷物件做為喚醒來源,但前提是必須提供系統 IRQ 資源的有效控制代碼。換句話說,建立虛擬中斷喚醒來源會被視為受控的特殊權限作業,由控制實體中斷物件建立能力的相同系統資源仲介。非喚醒來源的虛擬中斷仍可建構,不需要任何特殊權限。
這樣一來,就能在核心測試環境中編寫及執行完整的確定性單元測試
效能
預期對成效的影響不大。如果中斷導致喚醒來源發出信號,則在喚醒來源發出信號的同時產生報表時,中斷會需要與鎖定爭用,但報表產生絕不會將鎖定保留 O(N) 時間,只會保留足夠時間來評估個別相關聯的喚醒報表項目狀態,並將內容複製到本機緩衝區,然後捨棄鎖定,並嘗試複製到使用者提供的緩衝區。
報表產生本身需要 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 即可,可做為唯一鍵,必要時可用於查詢使用者模式的記帳資訊。
這樣一來,我們也不必擔心設計能力模型來控管這類資訊,也不必擔心惡意行為人透過喚醒來源報告存取私人記帳資訊,可能造成的安全風險。
回報已銷毀喚醒來源的喚醒事件。
如前所述,當喚醒來源遭到破壞時,任何待回報的相關聯喚醒報告項目資訊都會立即遭到破壞,且永遠不會回報。我們是否應堅持回報已毀損的喚醒來源的喚醒報告項目?
雖然提議的行為表示技術上可能無法向使用者模式回報喚醒報告項目,但預期在一般用途情境中不會造成任何嚴重問題。目前喚醒來源一律為中斷,這類來源通常會在系統啟動期間提早分配,並在整個系統的生命週期內保持運作,因此不會在正常運作期間遭到破壞。選擇立即移除任何等待回報的喚醒報告項目,可確保系統中發生下列情況時,喚醒報告的記憶體需求不會無限增長:
建立喚醒來源 + 發出信號。+ 毀損。 + 永久重複。
日後如果推出新的喚醒來源類型,且這些來源在一般作業期間會定期建立及刪除,而刪除來源可能導致喚醒報告項目資訊遺失,進而造成問題,我們可能會重新考慮這項決定。