NE6101050林峻毅
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    --- tags: linux, kernel --- # [Concurrency Managed Workqueue](https://www.kernel.org/doc/html/latest/core-api/workqueue.html) ## 為什麼我們需要 cmwq - 在 cmwq 推出之前只有兩種 workqueue ,Multithread workqueue 和 Singlethread workqueue,前者一個 workqueue 只有一個 execution context ,後者則是整個 system 共同持有一個 execution context,這樣的作法容易造成 deadlock。因為兩者的方便性與功能沒辦法滿足 concurrency 和 resource usage 的考量,所以為了解決這些問題他們甚至實作了自己的 thread pool 。 ### 名詞補充解釋 - **Execution context** includes the state of the processor, which is the value of its program counter and all of its registers ## cmwq 想要達成的目的 - 兼容以前的 workqueue API - 每個 CPU 有一個統一的 worker pool 被所有的 workqueue 共用,藉此滿足一定程度的 concurrency 需求,同時避免過多的資源浪費。 - 規範好 worker pool 的行為以及 concurrency 的程度,減輕使用者的負擔 ## 內部設計 - work item - 用一個 function pointer 指向要非同步執行的 function ,並包裝成一個 work item 放入 workqueue 之中 ```c= /* a work item*/ struct work_struct { atomic_long_t data; struct list_head entry; work_func_t func; #ifdef CONFIG_LOCKDEP struct lockdep_map lockdep_map; #endif }; ``` `work_func_t` 是一個 funciton pointer 的別名,指向 “一個擁有一個 work_struct * 當作參數並回傳 int 的函式” ```c typedef void (*work_func_t)(struct work_struct *work); ``` - worker threads - 負責執行 workqueue 中的 work ,如果沒有 work 則會 idle ```c= ``` - 將 workqueue 的後端運作機制抽離,只提供指令給 user 或是 driver 將 work item 放入 workqueue 。 - 每一個可供系統調用的 CPU 都有兩種 bounded worker-pool ,一個給一般的 work item 的 worker-pool 和一個給高優先度的 work item 的 worker-pool。除了 bounded worker-pool 還會有額外的 unbounded worker-pool,但不屬於單一個 CPU。 - 當一個 work item 放入 workqueue 之後,會由 workqueue 的屬性選擇應該被放入的 worker-pool,同時被登記在 worker-pool 之間共用的 worklist。 - concurrency 的程度都是對於任何一種 worker-pool 都很重要,最佳的情況是可以維持足夠程度的並行程度,但又不會太超過以至於佔用過多的硬體資源。 - worker-pool 通過 scheduler 來實現並行管理,而 worker-pool 只有在所有的 worker 全部都 idle 的情況才會喚醒一個 worker 去取得新的 work item 來執行,確保 CPU 不會 idle。 - **bounded worker-pool** => 限制綁定在哪個 CPU 上 - **unbounded worker-pool** => 不限制綁定在哪個 CPU 上 - 因為 idle 的 worker 是一個 kthread 所以佔用的資源極少,所以不會在他剛變成 idle 就刪除他。 - 控制 unbounded workqueues 的 concurrency 程度是 user 的責任,`cmwq` 提供了 [`apply_workqueue_attrs()`](https://hackmd.io/Q66IYnGKSwy8ckseib-IpA?view#alloc_workqueue-的-flags-與-argument) 來讓 user 自己進行調整。 - 除了前面提到的 worker,worker-pool 還有 rescue-worker 來幫忙釋放原本 worker 所佔用的記憶體,避免 worker 全部被使用光而沒辦法收回被這些 worker 所佔用的記憶體,行程整個 worker-pool 的 deadlock ## alloc_workqueue() 的 flags 與 argument ### WQ_UNBOUND - 讓這個 workqueue 的 work item 不被限制在一個特定的 CPU 上面。這樣的設計雖然犧牲了 locality 但在下列兩種環境有具有優勢 - 執行的過程之中並行的程度差異大,如果全部放在一個 bounded workqueue 會建立大量多餘的 worker,造成不必要的資源浪費。 - 需要佔用一個 cpu 大量的時間,所以交給 system scheduler 排班可以換來更好的效益。 ### WQ_FREEZABLE - 決定這個 workqueue 能不能被暫停。被凍結的 workqueue 之中的 work item 將暫時不會被執行,直到整個 workqueue 被解凍。 ### WQ_MEM_RECLAIM - 保證至少有一個 work item 可以無視 memory pressure。( 所有在回收 memory 的路徑上的 workqueue 都必須加上這個 flag ) ### WQ_HIGHPRI - 如果這是一個 high priority workqueue,其中的 work item 在被 worker thread 服務時的優先度會是 nice level ### WQ_CPU_INTENSIVE - 這個 workqueue 中的 work item 不會阻止同一個 workqueue 的其他 work item 開始執行,而且可以由 system scheduler 進行排班,但對於 unbounded workqueue 沒有意義。( unbounded workqueue 的 work 本來就是由 system scheduler 排班的) ### max_active (argument) - 同一個 cpu 最多可以拿走這個 workqueue 多少的 work item,一般建議設定為 0 ( default value ) - 對於 bounded workqueue ,官方設定的 default 值為 256 ,而可以設定的上限為 512 。 - 對於 unbounded workqueue ,官方設定的 default 值為 256 ,而可以設定的上限為 max(512, 4 * num_possible_cpus()) 。 ### 執行範例 在不同 workqueue attributes 的情況下,work item w0, w1, w2 的執行方式 ``` w0 佔用 cpu 5 秒, sleep 10 秒, 再佔用 cpu 5 秒 w1, w2 佔用 cpu 5 秒, 再 sleep 10 秒 ``` #### normal case w0, w1, w2 在同一個 workqueue ``` TIME IN MSECS EVENT 0 w0 starts and burns CPU 5 w0 sleeps 15 w0 wakes up and burns CPU 20 w0 finishes 20 w1 starts and burns CPU 25 w1 sleeps 35 w1 wakes up and finishes 35 w2 starts and burns CPU 40 w2 sleeps 50 w2 wakes up and finishes ``` #### max_active >= 3 ``` TIME IN MSECS EVENT 0 w0 starts and burns CPU 5 w0 sleeps 5 w1 starts and burns CPU 10 w1 sleeps 10 w2 starts and burns CPU 15 w2 sleeps 15 w0 wakes up and burns CPU 20 w0 finishes 20 w1 wakes up and finishes 25 w2 wakes up and finishes ``` #### max_active == 2 ``` TIME IN MSECS EVENT 0 w0 starts and burns CPU 5 w0 sleeps 5 w1 starts and burns CPU 10 w1 sleeps 15 w0 wakes up and burns CPU 20 w0 finishes 20 w1 wakes up and finishes 20 w2 starts and burns CPU 25 w2 sleeps 35 w2 wakes up and finishes ``` #### w1, w2 與 w0 在不同的 workqueue 且這個 workqueue 為 WQ_CPU_INTENSIVE ``` TIME IN MSECS EVENT 0 w0 starts and burns CPU 5 w0 sleeps 5 w1 and w2 start and burn CPU 10 w1 sleeps 15 w2 sleeps 15 w0 wakes up and burns CPU 20 w0 finishes 20 w1 wakes up and finishes 25 w2 wakes up and finishes ``` ## Non-reentrance Conditions 有三個條件會讓 work item 不能在被放入其他 workqueue 之中 1. The work function hasn’t been changed. 2. No one queues the work item to another workqueue. 3. The work item hasn’t been reinitiated. 如果可以確保上面這三個條件成立,則可以保證一個 work 在任意時刻只會被一個 worker 執行 ## 特殊名詞簡寫 `irq` : interrupt request `iret` : interrupt return `pwq` : pool workqueue `PIC` : programmable interrupt controller ## Reference :::warning 補充 : 用處比較小 : <s> [work queue 參考資料](https://iter01.com/427752.html) [work queue 參考資料](https://zhuanlan.zhihu.com/p/91106844) </s> YouTube 教學 : [workqueue 教學](https://www.youtube.com/watch?v=zno3WFng61w) CMWQ 與 workqueue 詳細講解 : [Concurrency Managed Workqueue之(一):workqueue的基本概念](http://www.wowotech.net/irq_subsystem/workqueue.html) [Concurrency Managed Workqueue之(二):CMWQ概述](http://www.wowotech.net/irq_subsystem/cmwq-intro.html) [Concurrency Managed Workqueue之(三):创建workqueue代码分析](http://www.wowotech.net/irq_subsystem/alloc_workqueue.html) [Concurrency Managed Workqueue之(四):workqueue如何处理work](http://www.wowotech.net/irq_subsystem/queue_and_handle_work.html) CMWQ 使用範例 : [workqueue kernel 程式碼](https://embetronicx.com/tutorials/linux/device-drivers/workqueue-in-linux-kernel/) :::

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully