# sched_ext(3): Write a scheduler to bomb a CPU core ## Overview 利用 sched_ext 作為框架撰寫一個將所有任務全部塞給指定 CPU core 執行的排程器!參考 `scx_central` 與 `scx_simple` 。 ## Implementation 在初始化函式 `randmigrate_init` 當中只需要做兩件事,讓該排程器排程所有任務以及建立一個 FALLBACK_DSQ 。 ```c int BPF_STRUCT_OPS_SLEEPABLE(randmigrate_init) { int ret; __COMPAT_scx_bpf_switch_all(); ret = scx_bpf_create_dsq(FALLBACK_DSQ_ID, -1); return ret; } ``` 挑選 CPU 處則是任意挑選即可,此處不是最後真正任務被分配到的 CPU 。 ```c s32 BPF_STRUCT_OPS(randmigrate_select_cpu, struct task_struct *p, s32 prev_cpu, u64 wake_flags) { s32 cpu = bpf_get_prandom_u32() % nr_cpus; return cpu; } ``` select_cpu 當中沒有利用到 `scx_bpf_dispatch()` 也就意味著 `ops.enqueue()` 一定會被呼叫,我們實作自己的 `enqueue()` ,概念和 `select_cpu()` 類似,若任務是 kthread 的任務則分配到 `SCX_LOCAL` 當中,若不是則放到 `FALLBACK_DSQ_ID` 當中並喚醒挑選到的 CPU 。 ```c void BPF_STRUCT_OPS(randmigrate_enqueue, struct task_struct *p, u64 enq_flags) { __sync_fetch_and_add(&nr_total, 1); if ((p->flags & PF_KTHREAD) && p->nr_cpus_allowed == 1) { __sync_fetch_and_add(&nr_locals, 1); scx_bpf_dispatch(p, SCX_DSQ_LOCAL, SCX_SLICE_INF, enq_flags | SCX_ENQ_PREEMPT); return; } s32 cpu = bpf_get_prandom_u32() % nr_cpus; __sync_fetch_and_add(&nr_queued, 1); scx_bpf_dispatch(p, FALLBACK_DSQ_ID , SCX_SLICE_INF, enq_flags); if (!scx_bpf_task_running(p)) scx_bpf_kick_cpu(cpu, SCX_KICK_PREEMPT); } ``` `dispatch()` 則是在 CPU 發現自己的 local dsq 當中沒有任務可執行時會呼叫的函式,我們實作的原理也很簡單,若非我們指定要轟炸的 CPU ,則不做任何事讓它回到 idle state 。若是的話則從 `FALLBACK_DSQ_ID` 當中拿任務出來。 ```c void BPF_STRUCT_OPS(randmigrate_dispatch, s32 cpu, struct task_struct *prev) { if (cpu == central_cpu) { __sync_fetch_and_add(&nr_dispatches, 1); if (scx_bpf_consume(FALLBACK_DSQ_ID)) return; s32 wake_cpu = bpf_get_prandom_u32() % nr_cpus; scx_bpf_kick_cpu(wake_cpu, SCX_KICK_PREEMPT); } } ``` 到此處為止就大功告成了! ## Test 編譯後將排程器掛載至我們的系統當中,此時應該可以發現你的電腦反應變得很慢,因為只有一顆 CPU 在做事。利用 `htop` 命令可以觀察到類似以下結果 ![image](https://hackmd.io/_uploads/ByNs4e7VC.png) 只有一顆 CPU core 也就是 5 在工作而已,若是此時還利用 `stress-ng` 等工具產生大量 workload ,可以看到以下有趣的結果 ``` $ stress-ng --cpu 12 --timeout 60s --metrics-brief ``` ![image](https://hackmd.io/_uploads/HyJeBe7VC.png) 整台電腦或者 server 會陷入嚴重卡頓的狀況,若使用 ssh 連線也會中斷,想停下 `stress-ng` 命令也需要等待很長的時間,非常有趣的過程! ## Sources 原始程式碼在我的 github repo 的 scx_randmigrate 分支底下,按照原本 `scx` 的安裝方式即可在 `build/scheds/c/scx_randmigrate` 處使用此排程器! * [vax-r/scx:scx_randmigrate](https://github.com/vax-r/scx/tree/scx_randmigrate)