Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tools/sched_ext: scx_userland: fix data races on shared counters

The stats thread reads nr_vruntime_enqueues, nr_vruntime_dispatches,
nr_vruntime_failed, and nr_curr_enqueued concurrently with the main
thread writing them, with no synchronization.

Use __atomic builtins with relaxed ordering for all accesses to these
counters to eliminate the data races.

Only display accuracy is affected, not scheduling correctness.

Signed-off-by: David Carlier <devnexen@gmail.com>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

David Carlier and committed by
Tejun Heo
f892f9f9 625be345

+13 -13
+13 -13
tools/sched_ext/scx_userland.c
··· 157 157 158 158 err = bpf_map_update_elem(dispatched_fd, NULL, &pid, 0); 159 159 if (err) { 160 - nr_vruntime_failed++; 160 + __atomic_add_fetch(&nr_vruntime_failed, 1, __ATOMIC_RELAXED); 161 161 } else { 162 - nr_vruntime_dispatches++; 162 + __atomic_add_fetch(&nr_vruntime_dispatches, 1, __ATOMIC_RELAXED); 163 163 } 164 164 165 165 return err; ··· 202 202 return ENOENT; 203 203 204 204 update_enqueued(curr, bpf_task); 205 - nr_vruntime_enqueues++; 206 - nr_curr_enqueued++; 205 + __atomic_add_fetch(&nr_vruntime_enqueues, 1, __ATOMIC_RELAXED); 206 + __atomic_add_fetch(&nr_curr_enqueued, 1, __ATOMIC_RELAXED); 207 207 208 208 /* 209 209 * Enqueue the task in a vruntime-sorted list. A more optimal data ··· 279 279 LIST_INSERT_HEAD(&vruntime_head, task, entries); 280 280 break; 281 281 } 282 - nr_curr_enqueued--; 282 + __atomic_sub_fetch(&nr_curr_enqueued, 1, __ATOMIC_RELAXED); 283 283 } 284 - skel->bss->nr_scheduled = nr_curr_enqueued; 284 + skel->bss->nr_scheduled = __atomic_load_n(&nr_curr_enqueued, __ATOMIC_RELAXED); 285 285 } 286 286 287 287 static void *run_stats_printer(void *arg) ··· 306 306 printf("|-----------------------|\n"); 307 307 printf("| VRUNTIME / USER |\n"); 308 308 printf("|-----------------------|\n"); 309 - printf("| enq: %10llu |\n", nr_vruntime_enqueues); 310 - printf("| disp: %10llu |\n", nr_vruntime_dispatches); 311 - printf("| failed: %10llu |\n", nr_vruntime_failed); 309 + printf("| enq: %10llu |\n", __atomic_load_n(&nr_vruntime_enqueues, __ATOMIC_RELAXED)); 310 + printf("| disp: %10llu |\n", __atomic_load_n(&nr_vruntime_dispatches, __ATOMIC_RELAXED)); 311 + printf("| failed: %10llu |\n", __atomic_load_n(&nr_vruntime_failed, __ATOMIC_RELAXED)); 312 312 printf("o-----------------------o\n"); 313 313 printf("\n\n"); 314 314 fflush(stdout); ··· 376 376 { 377 377 exit_req = 0; 378 378 min_vruntime = 0.0; 379 - nr_vruntime_enqueues = 0; 380 - nr_vruntime_dispatches = 0; 381 - nr_vruntime_failed = 0; 382 - nr_curr_enqueued = 0; 379 + __atomic_store_n(&nr_vruntime_enqueues, 0, __ATOMIC_RELAXED); 380 + __atomic_store_n(&nr_vruntime_dispatches, 0, __ATOMIC_RELAXED); 381 + __atomic_store_n(&nr_vruntime_failed, 0, __ATOMIC_RELAXED); 382 + __atomic_store_n(&nr_curr_enqueued, 0, __ATOMIC_RELAXED); 383 383 memset(tasks, 0, pid_max * sizeof(*tasks)); 384 384 LIST_INIT(&vruntime_head); 385 385