@@ -40,7 +40,8 @@ namespace {
4040int prerun_count;
4141int prerun_stored_count;
4242int count;
43- std::map<std::string, int > count_map = std::map<std::string, int >();
43+ std::unordered_map<CgroupPath, int > prerun_count_map{};
44+ std::unordered_map<CgroupPath, int > count_map{};
4445int stored_count;
4546bool controlled_detector_on;
4647std::unordered_map<std::string, unsigned int > prekill_hook_count;
@@ -52,6 +53,8 @@ void reset_counters() {
5253 stored_count = 0 ;
5354 controlled_detector_on = false ;
5455 prekill_hook_count.clear ();
56+ prerun_count_map.clear ();
57+ count_map.clear ();
5558}
5659
5760} // namespace
@@ -69,8 +72,11 @@ class ContinuePlugin : public BasePlugin {
6972 return 0 ;
7073 }
7174
72- void prerun (OomdContext& /* unused */ ) override {
75+ void prerun (OomdContext& ctx ) override {
7376 ++prerun_count;
77+ if (auto rulesetCgroup = ctx.getRulesetCgroup ()) {
78+ prerun_count_map[*rulesetCgroup]++;
79+ }
7480 }
7581
7682 PluginRet run (OomdContext& /* unused */ ) override {
@@ -92,8 +98,11 @@ class StopPlugin : public BasePlugin {
9298 return 0 ;
9399 }
94100
95- void prerun (OomdContext& /* unused */ ) override {
101+ void prerun (OomdContext& ctx ) override {
96102 ++prerun_count;
103+ if (auto rulesetCgroup = ctx.getRulesetCgroup ()) {
104+ prerun_count_map[*rulesetCgroup]++;
105+ }
97106 }
98107
99108 PluginRet run (OomdContext& /* unused */ ) override {
@@ -115,12 +124,18 @@ class IncrementCountPlugin : public BasePlugin {
115124 return 0 ;
116125 }
117126
118- void prerun (OomdContext& /* unused */ ) override {
127+ void prerun (OomdContext& ctx ) override {
119128 ++prerun_count;
129+ if (auto rulesetCgroup = ctx.getRulesetCgroup ()) {
130+ prerun_count_map[*rulesetCgroup]++;
131+ }
120132 }
121133
122- PluginRet run (OomdContext& /* unused */ ) override {
134+ PluginRet run (OomdContext& ctx ) override {
123135 ++count;
136+ if (auto rulesetCgroup = ctx.getRulesetCgroup ()) {
137+ count_map[*rulesetCgroup]++;
138+ }
124139 return PluginRet::CONTINUE ;
125140 }
126141
@@ -139,8 +154,11 @@ class StoreCountPlugin : public BasePlugin {
139154 return 0 ;
140155 }
141156
142- void prerun (OomdContext& /* unused */ ) override {
157+ void prerun (OomdContext& ctx ) override {
143158 ++prerun_count;
159+ if (auto rulesetCgroup = ctx.getRulesetCgroup ()) {
160+ prerun_count_map[*rulesetCgroup]++;
161+ }
144162 }
145163
146164 PluginRet run (OomdContext& /* unused */ ) override {
@@ -164,8 +182,11 @@ class ControlledDetectorPlugin : public BasePlugin {
164182 return 0 ;
165183 }
166184
167- void prerun (OomdContext& /* unused */ ) override {
185+ void prerun (OomdContext& ctx ) override {
168186 ++prerun_count;
187+ if (auto rulesetCgroup = ctx.getRulesetCgroup ()) {
188+ prerun_count_map[*rulesetCgroup]++;
189+ }
169190 }
170191
171192 PluginRet run (OomdContext& /* unused */ ) override {
@@ -191,8 +212,11 @@ class AsyncPausePlugin : public BasePlugin {
191212 return 0 ;
192213 }
193214
194- void prerun (OomdContext& /* unused */ ) override {
215+ void prerun (OomdContext& ctx ) override {
195216 ++prerun_count;
217+ if (auto rulesetCgroup = ctx.getRulesetCgroup ()) {
218+ prerun_count_map[*rulesetCgroup]++;
219+ }
196220 }
197221
198222 PluginRet run (OomdContext& /* unused */ ) override {
@@ -221,8 +245,11 @@ class NoInitPlugin : public BasePlugin {
221245 return 1 ;
222246 }
223247
224- void prerun (OomdContext& /* unused */ ) override {
248+ void prerun (OomdContext& ctx ) override {
225249 ++prerun_count;
250+ if (auto rulesetCgroup = ctx.getRulesetCgroup ()) {
251+ prerun_count_map[*rulesetCgroup]++;
252+ }
226253 }
227254
228255 PluginRet run (OomdContext& /* unused */ ) override {
@@ -282,8 +309,11 @@ class KillPlugin : public BasePlugin {
282309 return 0 ;
283310 }
284311
285- void prerun (OomdContext& /* unused */ ) override {
312+ void prerun (OomdContext& ctx ) override {
286313 ++prerun_count;
314+ if (auto rulesetCgroup = ctx.getRulesetCgroup ()) {
315+ prerun_count_map[*rulesetCgroup]++;
316+ }
287317 }
288318
289319 PluginRet run (OomdContext& ctx) override {
@@ -805,6 +835,68 @@ TEST_F(DropInCompilerTest, PrerunCount) {
805835 EXPECT_EQ (prerun_count, 0 + 3 + 2 + 3 + 5 );
806836}
807837
838+ TEST_F (CompilerTest, RulesetCGroupCount) {
839+ IR ::DetectorGroup always_yes{
840+ .name = " dg" ,
841+ .detectors = {IR ::Detector{IR ::Plugin{.name = " Continue" }}}};
842+ IR ::Action cnt{IR ::Plugin{.name = " IncrementCount" }};
843+ CgroupPath system_slice (kRandomCgroupFs , " system.slice" );
844+ CgroupPath workload_slice (kRandomCgroupFs , " workload.slice" );
845+
846+ root.rulesets = {IR ::Ruleset{
847+ .name = " A" ,
848+ .dgs = {always_yes},
849+ .acts = {cnt},
850+ .post_action_delay = " 0" ,
851+ .cgroup = " system.slice,workload.slice" }};
852+
853+ auto engine = compile ();
854+ ASSERT_TRUE (engine);
855+
856+ // Ruleset Cgroup only gets added in runOnce. Nothing should be prerun now
857+ engine->prerun (context);
858+ EXPECT_EQ (prerun_count, 0 );
859+ EXPECT_EQ (prerun_count_map.size (), 0 );
860+ EXPECT_EQ (count, 0 );
861+ EXPECT_EQ (count_map.size (), 0 );
862+
863+ // The newly added per-cgroup rulesets should be immediately prerun.
864+ engine->runOnce (context);
865+ EXPECT_EQ (prerun_count, 4 ); // 2 cgroup rulesets x 2 plugins
866+ EXPECT_EQ (prerun_count_map.size (), 2 );
867+ EXPECT_EQ (prerun_count_map.at (system_slice), 2 );
868+ EXPECT_EQ (prerun_count_map.at (workload_slice), 2 );
869+ EXPECT_EQ (count, 2 ); // 2 cgroup rulesets x 1 action
870+ EXPECT_EQ (count_map.size (), 2 );
871+ EXPECT_EQ (count_map.at (system_slice), 1 );
872+ EXPECT_EQ (count_map.at (workload_slice), 1 );
873+
874+ // After the first runOnce, the per-cgroup rulesets should be prerun.
875+ engine->prerun (context);
876+ // Second prerun, everything doubled
877+ EXPECT_EQ (prerun_count, 8 );
878+ EXPECT_EQ (prerun_count_map.size (), 2 );
879+ EXPECT_EQ (prerun_count_map.at (system_slice), 4 );
880+ EXPECT_EQ (prerun_count_map.at (workload_slice), 4 );
881+ // No run yet, values should be the same
882+ EXPECT_EQ (count, 2 );
883+ EXPECT_EQ (count_map.size (), 2 );
884+ EXPECT_EQ (count_map.at (system_slice), 1 );
885+ EXPECT_EQ (count_map.at (workload_slice), 1 );
886+
887+ // The second runOnce should not prerun the existing rulesets.
888+ engine->runOnce (context);
889+ EXPECT_EQ (prerun_count, 8 );
890+ EXPECT_EQ (prerun_count_map.size (), 2 );
891+ EXPECT_EQ (prerun_count_map.at (system_slice), 4 );
892+ EXPECT_EQ (prerun_count_map.at (workload_slice), 4 );
893+ // Second run, everything doubled
894+ EXPECT_EQ (count, 4 );
895+ EXPECT_EQ (count_map.size (), 2 );
896+ EXPECT_EQ (count_map.at (system_slice), 2 );
897+ EXPECT_EQ (count_map.at (workload_slice), 2 );
898+ }
899+
808900TEST_F (CompilerTest, NoInitPlugin) {
809901 IR ::Detector noinit;
810902 noinit.name = " NoInit" ;
0 commit comments