本頁面將討論驅動程式調度器所做的內嵌和非內嵌呼叫的效能。
瞭解內嵌和非內嵌呼叫之間的差異,有助於最佳化驅動程式庫回應速度和 Fuchsia 的整體系統效能。本頁面會說明無法內嵌呼叫的條件,以及這些條件對效能的影響。此外,它還會建議偵錯技巧,用於調查未內嵌的呼叫。
內嵌和非內嵌呼叫
當調度器需要「呼叫至驅動程式庫」 (也就是代表驅動程式庫程式在執行緒上執行工作) 時,調度器會先判斷是否可內嵌呼叫。如果不內嵌,系統會在稍後安排呼叫。
這兩種呼叫之間的主要差異如下:
- 內嵌:調度器會立即呼叫驅動程式庫。接收端會收到傳送端的要求,但不會傳回至執行階段迴圈 (請參閱圖 1)。
- 未內嵌:調度器會安排在未來的執行階段迴圈迭代中發生呼叫 (請見圖 2)。
內嵌呼叫比非內嵌呼叫更有效率。舉例來說,內嵌單向管道呼叫大約需要 2 微秒,而未內嵌的單向管道呼叫則可能需要 10 微秒。
圖 1. 內嵌呼叫的流程。
圖 2. 非內嵌呼叫的流程。
非內嵌呼叫的條件
如果符合下列任一情況,調度器就不會將呼叫內嵌:
調度器允許封鎖呼叫,但傳送端不允許。
如果目標調度器已設定
ALLOW_SYNC_CALLS
選項,但傳送者調度器未設定,則不會以內嵌方式發出呼叫。這可避免在同一個呼叫堆疊中封鎖非阻斷式調度器。調度器已同步,且未處於閒置狀態。
這項條件僅適用於同步調度器。在呼叫驅動程式庫時,驅動程式庫執行階段會檢查調度器是否處於閒置狀態。如果不是閒置狀態,則不會內嵌呼叫,以免在驅動程式庫中進行平行呼叫。
呼叫來自未由驅動程式庫執行階段管理的執行緒。
如果驅動程式使用
std::thread
或thread_create
方法產生自己的執行緒,則該執行緒不會由驅動程式庫程式執行階段管理。與 FIDL 接收端相關聯的管道尚未就緒。
FIDL 傳輸會使用管道 (Zircon 管道或驅動程式庫傳輸管道) 傳送及接收訊息。為了接收訊息,需要由 FIDL 層在管道上註冊等待 (由 FIDL 繫結在背景處理)。如果在收到訊息時未註冊等待時間,調度器就無法讓呼叫內嵌。
呼叫會視為可重入。
在圖 3 中,當 Driver A 向 Driver B 傳送 FIDL 要求,且 Driver B 立即回覆 Driver A 時,這則訊息對 Driver A 而言,就會視為重入。在這種情況下,Driver A 的調度器會發出非內嵌呼叫,以便傳送 Driver B 的回覆。
無論調度器提供哪些驅動程式,重入檢查都會套用至調度器。舉例來說,如果驅動程式庫擁有兩個調度器,在兩個調度器之間傳送和接收訊息一律會視為可重入,因此無法內嵌。
這個呼叫是使用 Zircon 管道傳輸的 FIDL 要求。
只有搭配驅動程式傳輸時,系統才支援 FIDL 內嵌。與 Zircon 管道不同,驅動程式庫傳輸管道僅在處理程序中,且允許在驅動程式庫傳輸管道邏輯中實作特殊內嵌功能。
圖 3. 因重入而未內嵌的呼叫流程。
對未內嵌的呼叫進行偵錯
fdf_env_dispatcher_dump
函式可協助驅動程式庫作者偵錯,找出為何某些呼叫未內嵌。這個函式會記錄非內嵌呼叫的計數和原因,例如:
INFO: [my_driver.cc(212)] ---- Runtime Dispatcher Dump Begin ----
INFO: [my_driver.cc(212)] The current thread is not managed by the driver runtime.
INFO: [my_driver.cc(212)] Dispatcher to dump: TestBody (0x24a7614d4240) (driver 0x10)
INFO: [my_driver.cc(212)] Synchronized: true
INFO: [my_driver.cc(212)] Allow sync calls: false
INFO: [my_driver.cc(212)] State: running
INFO: [my_driver.cc(212)] Processed 5 requests, 3 were inlined
INFO: [my_driver.cc(212)] Reasons why requests were not inlined:
INFO: [my_driver.cc(212)] * The request would have been reentrant: 2 times
INFO: [my_driver.cc(212)] * Another thread was already dispatching a request: 1 times
INFO: [my_driver.cc(212)] No queued tasks
如要在開發期間呼叫此函式,您必須修改受限制的符號 allowlist,並使用該變更進行 OTA/閃燈處理您的 Fuchsia 裝置。