diff --git a/scheds/kernel-examples/scx_central.bpf.c b/scheds/kernel-examples/scx_central.bpf.c index 5faf0d22d3..4f398249fb 100644 --- a/scheds/kernel-examples/scx_central.bpf.c +++ b/scheds/kernel-examples/scx_central.bpf.c @@ -60,6 +60,7 @@ const volatile s32 central_cpu; const volatile u32 nr_cpu_ids = 1; /* !0 for veristat, set during init */ const volatile u64 slice_ns = SCX_SLICE_DFL; +bool timer_pinned = true; u64 nr_total, nr_locals, nr_queued, nr_lost_pids; u64 nr_timers, nr_dispatches, nr_mismatches, nr_retries; u64 nr_overflows; @@ -255,7 +256,7 @@ static int central_timerfn(void *map, int *key, struct bpf_timer *timer) s32 i, curr_cpu; curr_cpu = bpf_get_smp_processor_id(); - if (curr_cpu != central_cpu) { + if (timer_pinned && (curr_cpu != central_cpu)) { scx_bpf_error("Central timer ran on CPU %d, not central CPU %d", curr_cpu, central_cpu); return 0; @@ -308,12 +309,28 @@ int BPF_STRUCT_OPS_SLEEPABLE(central_init) if (!timer) return -ESRCH; - if (bpf_get_smp_processor_id() != central_cpu) + if (bpf_get_smp_processor_id() != central_cpu) { + scx_bpf_error("init from non-central CPU"); return -EINVAL; + } bpf_timer_init(timer, ¢ral_timer, CLOCK_MONOTONIC); bpf_timer_set_callback(timer, central_timerfn); + ret = bpf_timer_start(timer, TIMER_INTERVAL_NS, BPF_F_TIMER_CPU_PIN); + /* + * BPF_F_TIMER_CPU_PIN is pretty new (>=6.7). If we're running in a + * kernel which doesn't have it, bpf_timer_start() will return -EINVAL. + * Retry without the PIN. This would be the perfect use case for + * bpf_core_enum_value_exists() but the enum type doesn't have a name + * and can't be used with bpf_core_enum_value_exists(). Oh well... + */ + if (ret == -EINVAL) { + timer_pinned = false; + ret = bpf_timer_start(timer, TIMER_INTERVAL_NS, 0); + } + if (ret) + scx_bpf_error("bpf_timer_start failed (%d)", ret); return ret; } diff --git a/scheds/kernel-examples/scx_central.c b/scheds/kernel-examples/scx_central.c index 1092443230..a3d22409e9 100644 --- a/scheds/kernel-examples/scx_central.c +++ b/scheds/kernel-examples/scx_central.c @@ -98,6 +98,9 @@ int main(int argc, char **argv) link = bpf_map__attach_struct_ops(skel->maps.central_ops); SCX_BUG_ON(!link, "Failed to attach struct_ops"); + if (!skel->data->timer_pinned) + printf("WARNING : BPF_F_TIMER_CPU_PIN not available, timer not pinned to central\n"); + while (!exit_req && !uei_exited(&skel->bss->uei)) { printf("[SEQ %llu]\n", seq++); printf("total :%10lu local:%10lu queued:%10lu lost:%10lu\n",