1 # Copyright 2017-2017 ARM Limited 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 # 15 16 from bart.common.Utils import select_window 17 18 from test import LisaTest, experiment_test 19 20 WORKLOAD_DURATION_S = 5 21 22 REQUIRED_CPU_ACTIVE_TIME_PCT = 95 23 24 class HeavyLoadTest(LisaTest): 25 """ 26 Test an EAS system under heavy load 27 28 Runs N 100% RT-App threads where N is the number of CPUs, and checks that 29 those tasks were spread across all CPUs in the system by asserting that all 30 CPUs were fully utilized up until the first task completed. 31 """ 32 33 test_conf = { 34 'ftrace' : { 35 'events' : ['cpu_idle', 'sched_switch'], 36 }, 37 'modules' : ['cgroups'], # Required by freeze_userspace flag 38 } 39 40 experiments_conf = { 41 "wloads" : { 42 "n_heavy_tasks" : { 43 "type" : "rt-app", 44 "conf" : { 45 "class" : "profile", 46 "params" : { 47 "wmig" : { 48 "kind" : "Periodic", 49 "params" : { 50 "duty_cycle_pct": 100, 51 "duration_s": WORKLOAD_DURATION_S, 52 }, 53 # Create one task for each cpu 54 "tasks" : "cpus", 55 }, 56 }, 57 }, 58 }, 59 }, 60 "confs" : [{ 61 'tag' : 'energy_aware', 62 'flags' : ['ftrace', 'freeze_userspace'], 63 'sched_features' : 'ENERGY_AWARE', 64 }] 65 } 66 67 @classmethod 68 def setUpClass(cls, *args, **kwargs): 69 super(HeavyLoadTest, cls).runExperiments(*args, **kwargs) 70 71 @experiment_test 72 def test_tasks_spread(self, experiment, tasks): 73 trace = self.get_trace(experiment) 74 start, _ = self.get_window(experiment) 75 end = min(self.get_end_times(experiment).values()) 76 duration = end - start 77 78 total_cpu_time = 0 79 active_proportions = [] 80 for cpu, _ in enumerate(self.target.core_names): 81 cpu_active = trace.getCPUActiveSignal(cpu) 82 if cpu_active is None: 83 raise RuntimeError( 84 "Couldn't get CPU-active signal. " 85 "Is the 'cpu_idle' ftrace event enabled in the kernel?") 86 87 # Add extra events to cpu_active signal so that it matches the 88 # window exactly 89 new_index = sorted(cpu_active.index.tolist() + [start, end]) 90 cpu_active = cpu_active.reindex(new_index, method='ffill') 91 92 active_time = trace.integrate_square_wave(cpu_active[start:end]) 93 active_proportions.append(active_time / duration) 94 95 if any(a < (REQUIRED_CPU_ACTIVE_TIME_PCT / 100.) 96 for a in active_proportions): 97 98 proportions_str = "" 99 for cpu, _ in enumerate(self.target.core_names): 100 proportions_str += " {:3d} {:5.1f}%\n".format( 101 cpu, active_proportions[cpu]*100) 102 103 raise AssertionError( 104 "Some CPUs were less than {}% utilized\n" 105 " CPU active proportions:\n{}".format( 106 REQUIRED_CPU_ACTIVE_TIME_PCT, proportions_str)) 107