select_cpu_vtime.bpf.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * A scheduler that validates that enqueue flags are properly stored and
  4. * applied at dispatch time when a task is directly dispatched from
  5. * ops.select_cpu(). We validate this by using scx_bpf_dsq_insert_vtime(),
  6. * and making the test a very basic vtime scheduler.
  7. *
  8. * Copyright (c) 2024 Meta Platforms, Inc. and affiliates.
  9. * Copyright (c) 2024 David Vernet <dvernet@meta.com>
  10. * Copyright (c) 2024 Tejun Heo <tj@kernel.org>
  11. */
  12. #include <scx/common.bpf.h>
  13. char _license[] SEC("license") = "GPL";
  14. volatile bool consumed;
  15. static u64 vtime_now;
  16. #define VTIME_DSQ 0
  17. static inline bool vtime_before(u64 a, u64 b)
  18. {
  19. return (s64)(a - b) < 0;
  20. }
  21. static inline u64 task_vtime(const struct task_struct *p)
  22. {
  23. u64 vtime = p->scx.dsq_vtime;
  24. if (vtime_before(vtime, vtime_now - SCX_SLICE_DFL))
  25. return vtime_now - SCX_SLICE_DFL;
  26. else
  27. return vtime;
  28. }
  29. s32 BPF_STRUCT_OPS(select_cpu_vtime_select_cpu, struct task_struct *p,
  30. s32 prev_cpu, u64 wake_flags)
  31. {
  32. s32 cpu;
  33. cpu = scx_bpf_pick_idle_cpu(p->cpus_ptr, 0);
  34. if (cpu >= 0)
  35. goto ddsp;
  36. cpu = prev_cpu;
  37. scx_bpf_test_and_clear_cpu_idle(cpu);
  38. ddsp:
  39. scx_bpf_dsq_insert_vtime(p, VTIME_DSQ, SCX_SLICE_DFL, task_vtime(p), 0);
  40. return cpu;
  41. }
  42. void BPF_STRUCT_OPS(select_cpu_vtime_dispatch, s32 cpu, struct task_struct *p)
  43. {
  44. if (scx_bpf_dsq_move_to_local(VTIME_DSQ))
  45. consumed = true;
  46. }
  47. void BPF_STRUCT_OPS(select_cpu_vtime_running, struct task_struct *p)
  48. {
  49. if (vtime_before(vtime_now, p->scx.dsq_vtime))
  50. vtime_now = p->scx.dsq_vtime;
  51. }
  52. void BPF_STRUCT_OPS(select_cpu_vtime_stopping, struct task_struct *p,
  53. bool runnable)
  54. {
  55. p->scx.dsq_vtime += (SCX_SLICE_DFL - p->scx.slice) * 100 / p->scx.weight;
  56. }
  57. void BPF_STRUCT_OPS(select_cpu_vtime_enable, struct task_struct *p)
  58. {
  59. p->scx.dsq_vtime = vtime_now;
  60. }
  61. s32 BPF_STRUCT_OPS_SLEEPABLE(select_cpu_vtime_init)
  62. {
  63. return scx_bpf_create_dsq(VTIME_DSQ, -1);
  64. }
  65. SEC(".struct_ops.link")
  66. struct sched_ext_ops select_cpu_vtime_ops = {
  67. .select_cpu = (void *) select_cpu_vtime_select_cpu,
  68. .dispatch = (void *) select_cpu_vtime_dispatch,
  69. .running = (void *) select_cpu_vtime_running,
  70. .stopping = (void *) select_cpu_vtime_stopping,
  71. .enable = (void *) select_cpu_vtime_enable,
  72. .init = (void *) select_cpu_vtime_init,
  73. .name = "select_cpu_vtime",
  74. .timeout_ms = 1000U,
  75. };