@@ -151,6 +151,15 @@ const volatile struct {
151151 .pelt_enabled = true,
152152};
153153
154+ /* Latency priority and preemption configuration */
155+ const volatile struct {
156+ bool latency_priority_enabled ;
157+ bool wakeup_preemption_enabled ;
158+ } latency_config = {
159+ .latency_priority_enabled = false,
160+ .wakeup_preemption_enabled = false,
161+ };
162+
154163const volatile u32 debug = 2 ;
155164const u32 zero_u32 = 0 ;
156165extern const volatile u32 nr_cpu_ids ;
@@ -1177,6 +1186,39 @@ static s32 p2dq_select_cpu_impl(struct task_struct *p, s32 prev_cpu, u64 wake_fl
11771186 else
11781187 cpu = pick_idle_cpu (p , taskc , prev_cpu , wake_flags , & is_idle );
11791188
1189+ // Wakeup preemption for extremely latency-critical tasks
1190+ // Only attempt if: no idle CPU found AND task has very high priority
1191+ if (!is_idle && latency_config .wakeup_preemption_enabled ) {
1192+ struct cpu_ctx * prev_cpuc ;
1193+
1194+ // Only preempt for truly latency-critical tasks (scx.weight >= 2847, equivalent to nice <= -15)
1195+ // and only if we can check the prev_cpu state
1196+ if (p -> scx .weight >= 2847 &&
1197+ bpf_cpumask_test_cpu (prev_cpu , p -> cpus_ptr ) &&
1198+ (prev_cpuc = lookup_cpu_ctx (prev_cpu ))) {
1199+
1200+ // Don't preempt interactive tasks - they need low latency too
1201+ if (cpu_ctx_test_flag (prev_cpuc , CPU_CTX_F_INTERACTIVE )) {
1202+ goto skip_preempt ;
1203+ }
1204+
1205+ // Only preempt if incoming task has higher priority than running task
1206+ // This ensures we only preempt lower priority work
1207+ if (p -> scx .weight <= prev_cpuc -> running_weight ) {
1208+ goto skip_preempt ;
1209+ }
1210+
1211+ // Queue to prev_cpu's LLC DSQ with high priority
1212+ // Don't bypass normal queueing - let vtime ordering work
1213+ // Just ensure we target prev_cpu for better cache affinity
1214+ cpu = prev_cpu ;
1215+ trace ("PREEMPT_TARGET [%d][%s] weight=%u > running_weight=%u on cpu=%d" ,
1216+ p -> pid , p -> comm , p -> scx .weight , prev_cpuc -> running_weight , prev_cpu );
1217+ }
1218+ }
1219+
1220+ skip_preempt :
1221+
11801222 if (likely (is_idle )) {
11811223 stat_inc (P2DQ_STAT_IDLE );
11821224 // Only direct dispatch non-affinitized tasks
@@ -1665,6 +1707,7 @@ static int p2dq_running_impl(struct task_struct *p)
16651707 cpu_ctx_clear_flag (cpuc , CPU_CTX_F_INTERACTIVE );
16661708
16671709 cpuc -> dsq_index = taskc -> dsq_index ;
1710+ cpuc -> running_weight = p -> scx .weight ;
16681711
16691712 if (p -> scx .weight < 100 )
16701713 cpu_ctx_set_flag (cpuc , CPU_CTX_F_NICE_TASK );
@@ -2466,6 +2509,7 @@ static s32 p2dq_init_task_impl(struct task_struct *p, struct scx_init_task_args
24662509
24672510 taskc -> llc_id = cpuc -> llc_id ;
24682511 taskc -> node_id = cpuc -> node_id ;
2512+ taskc -> pid = p -> pid ;
24692513
24702514 // Adjust starting index based on niceness
24712515 if (p -> scx .weight == 100 ) {
@@ -2500,8 +2544,6 @@ static s32 p2dq_init_task_impl(struct task_struct *p, struct scx_init_task_args
25002544 else
25012545 taskc -> dsq_id = cpuc -> llc_dsq ;
25022546
2503- taskc -> pid = p -> pid ;
2504-
25052547 return 0 ;
25062548}
25072549
@@ -3025,6 +3067,7 @@ void BPF_STRUCT_OPS(p2dq_running, struct task_struct *p)
30253067void BPF_STRUCT_OPS (p2dq_enqueue , struct task_struct * p __arg_trusted , u64 enq_flags )
30263068{
30273069 struct enqueue_promise pro ;
3070+
30283071 async_p2dq_enqueue (& pro , p , enq_flags );
30293072 complete_p2dq_enqueue (& pro , p );
30303073}
0 commit comments