@@ -52,6 +52,7 @@ const volatile u64 min_open_layer_disallow_preempt_after_ns;
5252const volatile u64 lo_fb_wait_ns = 5000000 ; /* !0 for veristat */
5353const volatile u32 lo_fb_share_ppk = 128 ; /* !0 for veristat */
5454const volatile bool percpu_kthread_preempt = true;
55+ int active_sticky_mod = 0 ;
5556
5657/* Flag to enable or disable antistall feature */
5758const volatile bool enable_antistall = true;
@@ -499,6 +500,11 @@ struct task_ctx {
499500 u32 qrt_llc_id ;
500501
501502 char join_layer [SCXCMD_COMLEN ];
503+
504+ #define STICKY_MOD_NR_BUCKETS 8
505+ u64 sticky_mod_buckets [STICKY_MOD_NR_BUCKETS ];
506+ u64 sticky_mod_nr_cnt ;
507+ u64 sticky_mod_start_ns ;
502508};
503509
504510struct {
@@ -871,6 +877,47 @@ s32 pick_idle_big_little(struct layer *layer, struct task_ctx *taskc,
871877 return cpu ;
872878}
873879
880+ static __always_inline
881+ s32 pick_sticky_mod_cpu (struct llc_ctx * llc , struct layer * layer , s32 prev_cpu )
882+ {
883+ u64 time = bpf_ktime_get_ns ();
884+ const struct cpumask * cpumask ;
885+ struct cpu_ctx * cpu_ctx ;
886+ s32 cpu = -1 ;
887+ int i ;
888+
889+ if (!active_sticky_mod )
890+ return cpu ;
891+
892+ cpu_ctx = lookup_cpu_ctx (prev_cpu );
893+ if (!cpu_ctx )
894+ goto llc ;
895+ if (cpu_ctx -> sticky_mod_pred_pct < layer -> sticky_mod_pred_pct )
896+ goto llc ;
897+ if (cpu_ctx -> sticky_mod_end_time_ns - time > layer -> sticky_mod_min_ns )
898+ goto llc ;
899+ return prev_cpu ;
900+ llc :
901+ if (!(cpumask = cast_mask (llc -> cpumask )))
902+ goto out ;
903+ bpf_for (i , 0 , nr_possible_cpus ) {
904+ if (i == prev_cpu )
905+ continue ;
906+ if (!bpf_cpumask_test_cpu (i , cpumask ))
907+ continue ;
908+ if (!(cpu_ctx = lookup_cpu_ctx (i )))
909+ continue ;
910+ if (cpu_ctx -> sticky_mod_pred_pct < layer -> sticky_mod_pred_pct )
911+ continue ;
912+ if (cpu_ctx -> sticky_mod_end_time_ns - time > layer -> sticky_mod_min_ns )
913+ continue ;
914+ cpu = i ;
915+ break ;
916+ }
917+ out :
918+ return cpu ;
919+ }
920+
874921static __always_inline
875922s32 pick_idle_cpu (struct task_struct * p , s32 prev_cpu ,
876923 struct cpu_ctx * cpuc , struct task_ctx * taskc , struct layer * layer ,
@@ -987,6 +1034,9 @@ s32 pick_idle_cpu(struct task_struct *p, s32 prev_cpu,
9871034 cpu = -1 ;
9881035 goto out_put ;
9891036 }
1037+
1038+ if ((cpu = pick_sticky_mod_cpu (prev_llcc , layer , prev_cpu )) >= 0 )
1039+ goto out_put ;
9901040 }
9911041
9921042 /*
@@ -1195,6 +1245,55 @@ static void layer_kick_idle_cpu(struct layer *layer)
11951245 scx_bpf_put_idle_cpumask (idle_smtmask );
11961246}
11971247
1248+ SEC ("tp_btf/sched_switch" )
1249+ int BPF_PROG (layered_sched_switch , bool ignore , struct task_struct * prev , struct task_struct * next )
1250+ {
1251+ u64 time = bpf_ktime_get_ns ();
1252+ u64 duration = time , max = 0 ;
1253+ u32 beg = 0 , end = 50000 , i ;
1254+ struct task_ctx * pc , * nc ;
1255+ struct cpu_ctx * c ;
1256+ u32 max_i = 0 ;
1257+
1258+ if (!active_sticky_mod )
1259+ return 0 ;
1260+
1261+ if (!(pc = lookup_task_ctx_may_fail (prev )))
1262+ goto next ;
1263+
1264+ duration -= pc -> sticky_mod_start_ns ;
1265+ duration /= 1000 ;
1266+
1267+ pc -> sticky_mod_nr_cnt ++ ;
1268+
1269+ for (i = 0 ; i < STICKY_MOD_NR_BUCKETS ; i ++ ) {
1270+ u64 cnt = pc -> sticky_mod_buckets [i ];
1271+
1272+ if (duration >= beg && duration <= end ) {
1273+ pc -> sticky_mod_buckets [i ]++ ;
1274+ cnt ++ ;
1275+ }
1276+ if (max < cnt ) {
1277+ max = cnt ;
1278+ max_i = i ;
1279+ }
1280+ beg += 50000 ;
1281+ end += 50000 ;
1282+ if (i == STICKY_MOD_NR_BUCKETS - 2 )
1283+ end = -1 ;
1284+ }
1285+
1286+ if (!(c = lookup_cpu_ctx (-1 )))
1287+ goto next ;
1288+ c -> sticky_mod_end_time_ns = (max_i + 1 ) * 50000 ;
1289+ c -> sticky_mod_pred_pct = ((max * 100 ) / pc -> sticky_mod_nr_cnt );
1290+ next :
1291+ if (!(nc = lookup_task_ctx_may_fail (next )))
1292+ return 0 ;
1293+ nc -> sticky_mod_start_ns = time ;
1294+ return 0 ;
1295+ }
1296+
11981297void BPF_STRUCT_OPS (layered_enqueue , struct task_struct * p , u64 enq_flags )
11991298{
12001299 struct cpu_ctx * cpuc , * task_cpuc ;
@@ -1718,6 +1817,9 @@ static __always_inline bool try_consume_layer(u32 layer_id, struct cpu_ctx *cpuc
17181817 xllc_mig_skipped = true;
17191818 continue ;
17201819 }
1820+
1821+ if (pick_sticky_mod_cpu (remote_llcc , layer , -1 ) >= 0 )
1822+ continue ;
17211823 }
17221824
17231825 if (scx_bpf_dsq_move_to_local (layer_dsq_id (layer_id , * llc_idp )))
@@ -3174,6 +3276,9 @@ static s32 init_layer(int layer_id)
31743276 return ret ;
31753277 }
31763278
3279+ if (layer -> sticky_mod_min_ns || layer -> sticky_mod_pred_pct )
3280+ active_sticky_mod ++ ;
3281+
31773282 return 0 ;
31783283}
31793284
0 commit comments