@@ -43,6 +43,17 @@ const volatile u64 root_cgid = 1;
43
43
u32 configuration_seq ;
44
44
u32 applied_configuration_seq ;
45
45
46
+ struct update_timer {
47
+ struct bpf_timer timer ;
48
+ };
49
+
50
+ struct {
51
+ __uint (type , BPF_MAP_TYPE_ARRAY );
52
+ __uint (max_entries , 1 );
53
+ __type (key , u32 );
54
+ __type (value , struct update_timer );
55
+ } update_timer SEC (".maps" ) __weak ;
56
+
46
57
private (all_cpumask ) struct bpf_cpumask __kptr * all_cpumask ;
47
58
private (root_cgrp ) struct cgroup __kptr * root_cgrp ;
48
59
@@ -756,56 +767,51 @@ static inline int get_cgroup_cpumask(struct cgroup *cgrp,
756
767
* cgroup hierarchy.
757
768
*/
758
769
u32 level_cells [MAX_CG_DEPTH ];
759
- int running ;
760
770
761
771
/*
762
772
* On tick, we identify new cells and apply CPU assignment
763
773
*/
764
- void BPF_STRUCT_OPS ( mitosis_tick , struct task_struct * p_run )
774
+ static int update_timer_cb ( void * map , int * key , struct bpf_timer * timer )
765
775
{
766
- /*
767
- * We serialize tick() on core 0 and ensure only one tick running at a time
768
- * to ensure this can only happen once.
769
- */
770
- if (bpf_get_smp_processor_id ())
771
- return ;
776
+ int ret ;
777
+ if ((ret = bpf_timer_start (timer , TIMER_INTERVAL_NS , 0 ))) {
778
+ scx_bpf_error ("Failed to arm update timer: %d" , ret );
779
+ return 0 ;
780
+ }
772
781
773
782
u32 local_configuration_seq = READ_ONCE (configuration_seq );
774
783
if (local_configuration_seq == READ_ONCE (applied_configuration_seq ))
775
- return ;
776
-
777
- int zero = 0 ;
778
- if (!__atomic_compare_exchange_n (& running , & zero , 1 , false,
779
- __ATOMIC_SEQ_CST , __ATOMIC_SEQ_CST ))
780
- return ;
784
+ return 0 ;
781
785
782
786
DECLARE_CPUMASK_ENTRY (entry ) = allocate_cpumask_entry ();
783
787
if (!entry )
784
- return ;
788
+ return 0 ;
785
789
786
790
/* Get the root cell (cell 0) and its cpumask */
791
+ int zero = 0 ;
787
792
struct cell_cpumask_wrapper * root_cell_cpumaskw ;
788
793
if (!(root_cell_cpumaskw =
789
794
bpf_map_lookup_elem (& cell_cpumasks , & zero ))) {
790
795
scx_bpf_error ("Failed to find root cell cpumask" );
791
- return ;
796
+ return 0 ;
792
797
}
793
798
794
799
struct bpf_cpumask * root_bpf_cpumask ;
795
800
root_bpf_cpumask =
796
801
bpf_kptr_xchg (& root_cell_cpumaskw -> tmp_cpumask , NULL );
797
802
if (!root_bpf_cpumask ) {
798
803
scx_bpf_error ("tmp_cpumask should never be null" );
799
- return ;
804
+ return 0 ;
800
805
}
801
806
if (!root_cell_cpumaskw -> cpumask ) {
802
807
scx_bpf_error ("root cpumasks should never be null" );
803
808
goto out ;
804
809
}
805
810
811
+ bpf_rcu_read_lock ();
806
812
if (!all_cpumask ) {
807
813
scx_bpf_error ("NULL all_cpumask" );
808
- goto out ;
814
+ goto out_rcu_unlock ;
809
815
}
810
816
811
817
/*
@@ -819,25 +825,24 @@ void BPF_STRUCT_OPS(mitosis_tick, struct task_struct *p_run)
819
825
820
826
if (!root_cgrp ) {
821
827
scx_bpf_error ("root_cgrp should not be null" );
822
- goto out ;
828
+ goto out_rcu_unlock ;
823
829
}
824
830
825
831
struct cgrp_ctx * root_cgrp_ctx ;
826
832
if (!(root_cgrp_ctx = lookup_cgrp_ctx (root_cgrp )))
827
- goto out ;
833
+ goto out_rcu_unlock ;
828
834
829
835
if (!root_cgrp ) {
830
836
scx_bpf_error ("root_cgrp should not be null" );
831
- goto out ;
837
+ goto out_rcu_unlock ;
832
838
}
833
839
834
840
if (!(root_cgrp_ref = bpf_cgroup_acquire (root_cgrp ))) {
835
841
scx_bpf_error ("Failed to acquire reference to root_cgrp" );
836
- goto out ;
842
+ goto out_rcu_unlock ;
837
843
}
838
844
root_css = & root_cgrp_ref -> self ;
839
845
840
- bpf_rcu_read_lock ();
841
846
/*
842
847
* Iterate over all cgroups, check if any have a cpumask and populate them
843
848
* as a separate cell.
@@ -867,7 +872,7 @@ void BPF_STRUCT_OPS(mitosis_tick, struct task_struct *p_run)
867
872
scx_bpf_error (
868
873
"Cgroup hierarchy is too deep: %d" ,
869
874
level );
870
- goto out_rcu_unlock ;
875
+ goto out_root_cgrp ;
871
876
}
872
877
/*
873
878
* This is a janky way of getting the parent cell, ideally we'd
@@ -889,7 +894,7 @@ void BPF_STRUCT_OPS(mitosis_tick, struct task_struct *p_run)
889
894
}
890
895
continue ;
891
896
} else if (rc < 0 )
892
- goto out_rcu_unlock ;
897
+ goto out_root_cgrp ;
893
898
894
899
/*
895
900
* cgroup has a cpumask, allocate a new cell if needed, and assign cpus
@@ -898,7 +903,7 @@ void BPF_STRUCT_OPS(mitosis_tick, struct task_struct *p_run)
898
903
if (!cgrp_ctx -> cell_owner ) {
899
904
cell_idx = allocate_cell ();
900
905
if (cell_idx < 0 )
901
- goto out_rcu_unlock ;
906
+ goto out_root_cgrp ;
902
907
cgrp_ctx -> cell_owner = true;
903
908
}
904
909
@@ -907,14 +912,14 @@ void BPF_STRUCT_OPS(mitosis_tick, struct task_struct *p_run)
907
912
bpf_map_lookup_elem (& cell_cpumasks , & cell_idx ))) {
908
913
scx_bpf_error ("Failed to find cell cpumask: %d" ,
909
914
cell_idx );
910
- goto out_rcu_unlock ;
915
+ goto out_root_cgrp ;
911
916
}
912
917
913
918
struct bpf_cpumask * bpf_cpumask ;
914
919
bpf_cpumask = bpf_kptr_xchg (& cell_cpumaskw -> tmp_cpumask , NULL );
915
920
if (!bpf_cpumask ) {
916
921
scx_bpf_error ("tmp_cpumask should never be null" );
917
- goto out_rcu_unlock ;
922
+ goto out_root_cgrp ;
918
923
}
919
924
bpf_cpumask_copy (bpf_cpumask ,
920
925
(const struct cpumask * )& entry -> cpumask );
@@ -927,7 +932,7 @@ void BPF_STRUCT_OPS(mitosis_tick, struct task_struct *p_run)
927
932
struct cpu_ctx * cpu_ctx ;
928
933
if (!(cpu_ctx = lookup_cpu_ctx (cpu_idx ))) {
929
934
bpf_cpumask_release (bpf_cpumask );
930
- goto out_rcu_unlock ;
935
+ goto out_root_cgrp ;
931
936
}
932
937
cpu_ctx -> cell = cell_idx ;
933
938
bpf_cpumask_clear_cpu (cpu_idx ,
@@ -938,15 +943,15 @@ void BPF_STRUCT_OPS(mitosis_tick, struct task_struct *p_run)
938
943
bpf_kptr_xchg (& cell_cpumaskw -> cpumask , bpf_cpumask );
939
944
if (!bpf_cpumask ) {
940
945
scx_bpf_error ("cpumask should never be null" );
941
- goto out_rcu_unlock ;
946
+ goto out_root_cgrp ;
942
947
}
943
948
944
949
bpf_cpumask =
945
950
bpf_kptr_xchg (& cell_cpumaskw -> tmp_cpumask , bpf_cpumask );
946
951
if (bpf_cpumask ) {
947
952
scx_bpf_error ("tmp_cpumask should be null" );
948
953
bpf_cpumask_release (bpf_cpumask );
949
- goto out_rcu_unlock ;
954
+ goto out_root_cgrp ;
950
955
}
951
956
952
957
barrier ();
@@ -955,11 +960,10 @@ void BPF_STRUCT_OPS(mitosis_tick, struct task_struct *p_run)
955
960
if (level <= 0 || level >= MAX_CG_DEPTH ) {
956
961
scx_bpf_error ("Cgroup hierarchy is too deep: %d" ,
957
962
level );
958
- goto out_rcu_unlock ;
963
+ goto out_root_cgrp ;
959
964
}
960
965
level_cells [level ] = cell_idx ;
961
966
}
962
- bpf_rcu_read_unlock ();
963
967
964
968
/*
965
969
* assign root cell cpus that are left over
@@ -968,21 +972,21 @@ void BPF_STRUCT_OPS(mitosis_tick, struct task_struct *p_run)
968
972
bpf_for (cpu_idx , 0 , nr_possible_cpus )
969
973
{
970
974
if (bpf_cpumask_test_cpu (
971
- cpu_idx , (const struct cpumask * )& entry -> cpumask )) {
975
+ cpu_idx , (const struct cpumask * )root_bpf_cpumask )) {
972
976
struct cpu_ctx * cpu_ctx ;
973
977
if (!(cpu_ctx = lookup_cpu_ctx (cpu_idx )))
974
978
goto out_root_cgrp ;
975
979
cpu_ctx -> cell = 0 ;
976
- bpf_cpumask_clear_cpu (cpu_idx , root_bpf_cpumask );
977
980
}
978
981
}
979
982
980
983
root_bpf_cpumask =
981
984
bpf_kptr_xchg (& root_cell_cpumaskw -> cpumask , root_bpf_cpumask );
982
985
if (!root_bpf_cpumask ) {
983
986
scx_bpf_error ("root cpumask should never be null" );
987
+ bpf_rcu_read_unlock ();
984
988
bpf_cgroup_release (root_cgrp_ref );
985
- return ;
989
+ return 0 ;
986
990
}
987
991
988
992
root_bpf_cpumask = bpf_kptr_xchg (& root_cell_cpumaskw -> tmp_cpumask ,
@@ -994,16 +998,17 @@ void BPF_STRUCT_OPS(mitosis_tick, struct task_struct *p_run)
994
998
995
999
barrier ();
996
1000
WRITE_ONCE (applied_configuration_seq , local_configuration_seq );
997
- WRITE_ONCE (running , 0 );
998
1001
999
- bpf_cgroup_release (root_cgrp_ref );
1000
- return ;
1001
- out_rcu_unlock :
1002
1002
bpf_rcu_read_unlock ();
1003
+ bpf_cgroup_release (root_cgrp_ref );
1004
+ return 0 ;
1003
1005
out_root_cgrp :
1004
1006
bpf_cgroup_release (root_cgrp_ref );
1007
+ out_rcu_unlock :
1008
+ bpf_rcu_read_unlock ();
1005
1009
out :
1006
1010
bpf_cpumask_release (root_bpf_cpumask );
1011
+ return 0 ;
1007
1012
}
1008
1013
1009
1014
void BPF_STRUCT_OPS (mitosis_running , struct task_struct * p )
@@ -1299,6 +1304,19 @@ s32 BPF_STRUCT_OPS_SLEEPABLE(mitosis_init)
1299
1304
u32 i ;
1300
1305
s32 ret ;
1301
1306
1307
+ u32 key = 0 ;
1308
+ struct bpf_timer * timer = bpf_map_lookup_elem (& update_timer , & key );
1309
+ if (!timer ) {
1310
+ scx_bpf_error ("Failed to lookup update timer" );
1311
+ return - ESRCH ;
1312
+ }
1313
+ bpf_timer_init (timer , & update_timer , CLOCK_BOOTTIME );
1314
+ bpf_timer_set_callback (timer , update_timer_cb );
1315
+ if ((ret = bpf_timer_start (timer , TIMER_INTERVAL_NS , 0 ))) {
1316
+ scx_bpf_error ("Failed to arm update timer" );
1317
+ return ret ;
1318
+ }
1319
+
1302
1320
struct cgroup * rootcg ;
1303
1321
if (!(rootcg = bpf_cgroup_from_id (root_cgid )))
1304
1322
return - ENOENT ;
@@ -1387,7 +1405,6 @@ struct sched_ext_ops mitosis = {
1387
1405
.select_cpu = (void * )mitosis_select_cpu ,
1388
1406
.enqueue = (void * )mitosis_enqueue ,
1389
1407
.dispatch = (void * )mitosis_dispatch ,
1390
- .tick = (void * )mitosis_tick ,
1391
1408
.running = (void * )mitosis_running ,
1392
1409
.stopping = (void * )mitosis_stopping ,
1393
1410
.set_cpumask = (void * )mitosis_set_cpumask ,
0 commit comments