1#!/usr/bin/env python3 2''' Reusable functions related to sched mc FVT are put together 3''' 4 5import os 6import sys 7import re 8from time import time 9 10__author__ = "Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>" 11__author__ = "Poornima Nayak <mpnayak@linux.vnet.ibm.com>" 12 13 14cpu_map = {} 15stats_start = {} 16stats_stop = {} 17stats_percentage = {} 18intr_start = [] 19intr_stop = [] 20cpu_count = 0 21socket_count = 0 22cpu1_max_intr = 0 23cpu2_max_intr = 0 24intr_stat_timer_0 = [] 25siblings_list = [] 26 27def clear_dmesg(): 28 ''' 29 Clears dmesg 30 ''' 31 try: 32 os.system('dmesg -c >/dev/null') 33 except OSError as e: 34 print('Clearing dmesg failed', e) 35 sys.exit(1) 36 37def count_num_cpu(): 38 ''' Returns number of cpu's in system 39 ''' 40 try: 41 cpuinfo = open('/proc/cpuinfo', 'r') 42 global cpu_count 43 for line in cpuinfo: 44 if line.startswith('processor'): 45 cpu_count += 1 46 cpuinfo.close() 47 except IOError as e: 48 print("Could not get cpu count", e) 49 sys.exit(1) 50 51def count_num_sockets(): 52 ''' Returns number of cpu's in system 53 ''' 54 socket_list = [] 55 global socket_count 56 try: 57 for i in range(0, cpu_count): 58 phy_pkg_file = '/sys/devices/system/cpu/cpu%s' % i 59 phy_pkg_file += '/topology/physical_package_id' 60 socket_id = open(phy_pkg_file).read().rstrip() 61 if socket_id not in socket_list: 62 socket_list.append(socket_id) 63 socket_count = socket_count + 1 64 except Exception as details: 65 print("INFO: Failed to get number of sockets in system", details) 66 sys.exit(1) 67 68def is_multi_socket(): 69 '''Return 1 if the system is multi socket else return 0 70 ''' 71 try: 72 if socket_count > 1: 73 return 1 74 else: 75 return 0 76 except Exception: 77 print("Failed to check if system is multi socket system") 78 sys.exit(1) 79 80def is_hyper_threaded(): 81 '''Return 1 if the system is hyper threaded else return 0 82 ''' 83 try: 84 file_cpuinfo = open("/proc/cpuinfo", 'r') 85 for line in file_cpuinfo: 86 if line.startswith('siblings'): 87 siblings = line.split(":") 88 if line.startswith('cpu cores'): 89 cpu_cores = line.split(":") 90 break 91 if int( siblings[1] ) / int( cpu_cores[1] )> 1: 92 file_cpuinfo.close() 93 return 1 94 else: 95 return 0 96 except Exception: 97 print("Failed to check if system is hyper-threaded") 98 sys.exit(1) 99 100def is_multi_core(): 101 ''' Return true if system has sockets has multiple cores 102 ''' 103 104 try: 105 file_cpuinfo = open("/proc/cpuinfo", 'r') 106 for line in file_cpuinfo: 107 if line.startswith('siblings'): 108 siblings = line.split(":") 109 if line.startswith('cpu cores'): 110 cpu_cores = line.split(":") 111 break 112 113 if int( siblings[1] ) == int( cpu_cores[1] ): 114 if int( cpu_cores[1] ) > 1: 115 multi_core = 1 116 else: 117 multi_core = 0 118 else: 119 num_of_cpus = int(siblings[1]) / int(cpu_cores[1]) 120 if num_of_cpus > 1: 121 multi_core = 1 122 else: 123 multi_core = 0 124 file_cpuinfo.close() 125 return multi_core 126 except Exception: 127 print("Failed to check if system is multi core system") 128 sys.exit(1) 129 130def get_hyper_thread_count(): 131 ''' Return number of threads in CPU. For eg for x3950 this function 132 would return 2. In future if 4 threads are supported in CPU, this 133 routine would return 4 134 ''' 135 try: 136 file_cpuinfo = open("/proc/cpuinfo", 'r') 137 for line in file_cpuinfo: 138 if line.startswith('siblings'): 139 siblings = line.split(":") 140 if line.startswith('cpu cores'): 141 cpu_cores = line.split(":") 142 break 143 return( int( siblings[1] ) / int( cpu_cores[1] ) ) 144 except Exception: 145 print("Failed to check if system is hyper-threaded") 146 sys.exit(1) 147 148def map_cpuid_pkgid(): 149 ''' Routine to map physical package id to cpu id 150 ''' 151 if is_hyper_threaded(): 152 core_info = {} 153 try: 154 for i in range(0, cpu_count): 155 phy_pkg_file = '/sys/devices/system/cpu/cpu%s' % i 156 phy_pkg_file += '/topology/physical_package_id' 157 core_file = '/sys/devices/system/cpu/cpu%s' % i 158 core_file += '/topology/core_id' 159 core_id = open(core_file).read().rstrip() 160 cpu_phy_id = open(phy_pkg_file).read().rstrip() 161 if not cpu_phy_id in list(cpu_map.keys()): 162 core_info = {} 163 else: 164 core_info = cpu_map[cpu_phy_id] 165 if not core_id in list(core_info.keys()): 166 core_info[core_id] = [i] 167 else: 168 core_info[core_id].append(i) 169 cpu_map[cpu_phy_id] = core_info 170 except Exception as details: 171 print("Package, core & cpu map table creation failed", e) 172 sys.exit(1) 173 else: 174 for i in range(0, cpu_count): 175 try: 176 phy_pkg_file = '/sys/devices/system/cpu/cpu%s' %i 177 phy_pkg_file += '/topology/physical_package_id' 178 cpu_phy_id = open(phy_pkg_file).read().rstrip() 179 if not cpu_phy_id in list(cpu_map.keys()): 180 cpu_map[cpu_phy_id] = [i] 181 else: 182 cpu_map[cpu_phy_id].append(i) 183 except IOError as e: 184 print("Mapping of CPU to pkg id failed", e) 185 sys.exit(1) 186 187 188def generate_sibling_list(): 189 ''' Routine to generate siblings list 190 ''' 191 try: 192 for i in range(0, cpu_count): 193 siblings_file = '/sys/devices/system/cpu/cpu%s' % i 194 siblings_file += '/topology/thread_siblings_list' 195 threads_sibs = open(siblings_file).read().rstrip() 196 thread_ids = threads_sibs.split("-") 197 198 if not thread_ids in siblings_list: 199 siblings_list.append(thread_ids) 200 except Exception as details: 201 print("Exception in generate_siblings_list", details) 202 sys.exit(1) 203 204def get_siblings(cpu_id): 205 ''' Return siblings of cpu_id 206 ''' 207 try: 208 cpus = "" 209 for i in range(0, len(siblings_list)): 210 for cpu in siblings_list[i]: 211 if cpu_id == cpu: 212 for j in siblings_list[i]: 213 # Exclude cpu_id in the list of siblings 214 if j != cpu_id: 215 cpus += j 216 return cpus 217 return cpus 218 except Exception as details: 219 print("Exception in get_siblings", details) 220 sys.exit(1) 221 222def get_proc_data(stats_list): 223 ''' Read /proc/stat info and store in dictionary 224 ''' 225 try: 226 file_procstat = open("/proc/stat", 'r') 227 for line in file_procstat: 228 if line.startswith('cpu'): 229 data = line.split() 230 stats_list[data[0]] = data 231 file_procstat.close() 232 except OSError as e: 233 print("Could not read statistics", e) 234 sys.exit(1) 235 236def get_proc_loc_count(loc_stats): 237 ''' Read /proc/interrupts info and store in list 238 ''' 239 try: 240 file_procstat = open("/proc/interrupts", 'r') 241 for line in file_procstat: 242 if line.startswith(' LOC:') or line.startswith('LOC:'): 243 data = line.split() 244 for i in range(0, cpu_count): 245 # To skip LOC 246 loc_stats.append(data[i+1]) 247 file_procstat.close() 248 return 249 except Exception as details: 250 print("Could not read interrupt statistics", details) 251 sys.exit(1) 252 253 254def set_sched_mc_power(sched_mc_level): 255 ''' Routine to set sched_mc_power_savings to required level 256 ''' 257 try: 258 os.system('echo %s > \ 259 /sys/devices/system/cpu/sched_mc_power_savings 2>/dev/null' 260 % sched_mc_level) 261 262 get_proc_data(stats_start) 263 except OSError as e: 264 print("Could not set sched_mc_power_savings to", sched_mc_level, e) 265 sys.exit(1) 266 267def set_sched_smt_power(sched_smt_level): 268 ''' Routine to set sched_smt_power_savings to required level 269 ''' 270 try: 271 os.system('echo %s > \ 272 /sys/devices/system/cpu/sched_smt_power_savings 2>/dev/null' 273 % sched_smt_level) 274 275 get_proc_data(stats_start) 276 except OSError as e: 277 print("Could not set sched_smt_power_savings to", sched_smt_level, e) 278 sys.exit(1) 279 280def set_timer_migration_interface(value): 281 ''' Set value of timer migration interface to a value 282 passed as argument 283 ''' 284 try: 285 os.system('echo %s > \ 286 /proc/sys/kernel/timer_migration 2>/dev/null' % value) 287 except OSError as e: 288 print("Could not set timer_migration to ", value, e) 289 sys.exit(1) 290 291def get_job_count(stress, workload, sched_smt): 292 ''' Returns number of jobs/threads to be triggered 293 ''' 294 295 try: 296 if stress == "thread": 297 threads = get_hyper_thread_count() 298 if stress == "partial": 299 threads = cpu_count / socket_count 300 if is_hyper_threaded(): 301 if workload == "ebizzy" and int(sched_smt) ==0: 302 threads = threads / get_hyper_thread_count() 303 if workload == "kernbench" and int(sched_smt) < 2: 304 threads = threads / get_hyper_thread_count() 305 if stress == "full": 306 threads = cpu_count 307 if stress == "single_job": 308 threads = 1 309 duration = 180 310 return threads 311 except Exception as details: 312 print("get job count failed ", details) 313 sys.exit(1) 314 315def trigger_ebizzy (sched_smt, stress, duration, background, pinned): 316 ''' Triggers ebizzy workload for sched_mc=1 317 testing 318 ''' 319 try: 320 threads = get_job_count(stress, "ebizzy", sched_smt) 321 workload = "ebizzy" 322 olddir = os.getcwd() 323 path = '%s/testcases/bin' % os.environ['LTPROOT'] 324 os.chdir(path) 325 workload_file = "" 326 for file_name in os.listdir('.'): 327 if file_name == workload: 328 workload_file = file_name 329 break 330 if workload_file == "": 331 print("INFO: ebizzy benchmark not found") 332 os.chdir(olddir) 333 sys.exit(1) 334 get_proc_data(stats_start) 335 get_proc_loc_count(intr_start) 336 try: 337 if background == "yes": 338 succ = os.system('./ebizzy -t%s -s4096 -S %s >/dev/null &' 339 % (threads, duration)) 340 else: 341 if pinned == "yes": 342 succ = os.system('taskset -c %s ./ebizzy -t%s -s4096 -S %s >/dev/null' 343 % (cpu_count -1, threads, duration)) 344 else: 345 succ = os.system('./ebizzy -t%s -s4096 -S %s >/dev/null' 346 % (threads, duration)) 347 348 if succ == 0: 349 print("INFO: ebizzy workload triggerd") 350 os.chdir(olddir) 351 #Commented bcoz it doesnt make sense to capture it when workload triggered 352 #in background 353 #get_proc_loc_count(intr_stop) 354 #get_proc_data(stats_stop) 355 else: 356 print("INFO: ebizzy workload triggerd failed") 357 os.chdir(olddir) 358 sys.exit(1) 359 except Exception as details: 360 print("Ebizzy workload trigger failed ", details) 361 sys.exit(1) 362 except Exception as details: 363 print("Ebizzy workload trigger failed ", details) 364 sys.exit(1) 365 366def trigger_kernbench (sched_smt, stress, background, pinned, perf_test): 367 ''' Trigger load on system like kernbench. 368 Copys existing copy of LTP into as LTP2 and then builds it 369 with make -j 370 ''' 371 olddir = os.getcwd() 372 try: 373 threads = get_job_count(stress, "kernbench", sched_smt) 374 375 dst_path = "/root" 376 workload = "kernbench" 377 olddir = os.getcwd() 378 path = '%s/testcases/bin' % os.environ['LTPROOT'] 379 os.chdir(path) 380 workload_file = "" 381 for file_name in os.listdir('.'): 382 if file_name == workload: 383 workload_file = file_name 384 break 385 if workload_file != "": 386 benchmark_path = path 387 else: 388 print("INFO: kernbench benchmark not found") 389 os.chdir(olddir) 390 sys.exit(1) 391 392 os.chdir(dst_path) 393 linux_source_dir="" 394 for file_name in os.listdir('.'): 395 if file_name.find("linux-2.6") != -1 and os.path.isdir(file_name): 396 linux_source_dir=file_name 397 break 398 if linux_source_dir != "": 399 os.chdir(linux_source_dir) 400 else: 401 print("INFO: Linux kernel source not found in /root. Workload\ 402 Kernbench cannot be executed") 403 sys.exit(1) 404 405 get_proc_data(stats_start) 406 get_proc_loc_count(intr_start) 407 if pinned == "yes": 408 os.system ( 'taskset -c %s %s/kernbench -o %s -M -H -n 1 \ 409 >/dev/null 2>&1 &' % (cpu_count-1, benchmark_path, threads)) 410 411 # We have to delete import in future 412 import time 413 time.sleep(240) 414 stop_wkld("kernbench") 415 else: 416 if background == "yes": 417 os.system ( '%s/kernbench -o %s -M -H -n 1 >/dev/null 2>&1 &' \ 418 % (benchmark_path, threads)) 419 else: 420 if perf_test == "yes": 421 os.system ( '%s/kernbench -o %s -M -H -n 1 >/dev/null 2>&1' \ 422 % (benchmark_path, threads)) 423 else: 424 os.system ( '%s/kernbench -o %s -M -H -n 1 >/dev/null 2>&1 &' \ 425 % (benchmark_path, threads)) 426 # We have to delete import in future 427 import time 428 time.sleep(240) 429 stop_wkld("kernbench") 430 431 print("INFO: Workload kernbench triggerd") 432 os.chdir(olddir) 433 except Exception as details: 434 print("Workload kernbench trigger failed ", details) 435 sys.exit(1) 436 437def trigger_workld(sched_smt, workload, stress, duration, background, pinned, perf_test): 438 ''' Triggers workload passed as argument. Number of threads 439 triggered is based on stress value. 440 ''' 441 try: 442 if workload == "ebizzy": 443 trigger_ebizzy (sched_smt, stress, duration, background, pinned) 444 if workload == "kernbench": 445 trigger_kernbench (sched_smt, stress, background, pinned, perf_test) 446 except Exception as details: 447 print("INFO: Trigger workload failed", details) 448 sys.exit(1) 449 450def generate_report(): 451 ''' Generate report of CPU utilization 452 ''' 453 cpu_labels = ('cpu', 'user', 'nice', 'system', 'idle', 'iowait', 'irq', 454 'softirq', 'x', 'y') 455 if (not os.path.exists('/procstat')): 456 os.mkdir('/procstat') 457 458 get_proc_data(stats_stop) 459 460 reportfile = open('/procstat/cpu-utilisation', 'a') 461 debugfile = open('/procstat/cpu-utilisation.debug', 'a') 462 for l in stats_stop: 463 percentage_list = [] 464 total = 0 465 for i in range(1, len(stats_stop[l])): 466 stats_stop[l][i] = int(stats_stop[l][i]) - int(stats_start[l][i]) 467 total += stats_stop[l][i] 468 percentage_list.append(l) 469 for i in range(1, len(stats_stop[l])): 470 percentage_list.append(float(stats_stop[l][i])*100/total) 471 472 stats_percentage[l] = percentage_list 473 474 for i in range(0, len(cpu_labels)): 475 print(cpu_labels[i], '\t', end=' ', file=debugfile) 476 print(file=debugfile) 477 for l in sorted(stats_stop.keys()): 478 print(l, '\t', end=' ', file=debugfile) 479 for i in range(1, len(stats_stop[l])): 480 print(stats_stop[l][i], '\t', end=' ', file=debugfile) 481 print(file=debugfile) 482 483 for i in range(0, len(cpu_labels)): 484 print(cpu_labels[i], '\t', end=' ', file=reportfile) 485 print(file=reportfile) 486 for l in sorted(stats_percentage.keys()): 487 print(l, '\t', end=' ', file=reportfile) 488 for i in range(1, len(stats_percentage[l])): 489 print(" %3.4f" % stats_percentage[l][i], end=' ', file=reportfile) 490 print(file=reportfile) 491 492 #Now get the package ID information 493 try: 494 print("cpu_map: ", cpu_map, file=debugfile) 495 keyvalfile = open('/procstat/keyval', 'a') 496 print("nr_packages=%d" % len(cpu_map), file=keyvalfile) 497 print("system-idle=%3.4f" % (stats_percentage['cpu'][4]), file=keyvalfile) 498 for pkg in sorted(cpu_map.keys()): 499 if is_hyper_threaded(): 500 for core in sorted(cpu_map[pkg].keys()): 501 total_idle = 0 502 total = 0 503 for cpu in cpu_map[pkg][core]: 504 total_idle += stats_stop["cpu%d" % cpu][4] 505 for i in range(1, len(stats_stop["cpu%d" % cpu])): 506 total += stats_stop["cpu%d" % cpu][i] 507 else: 508 total_idle = 0 509 total = 0 510 for cpu in cpu_map[pkg]: 511 total_idle += stats_stop["cpu%d" % cpu][4] 512 for i in range(1, len(stats_stop["cpu%d" % cpu])): 513 total += stats_stop["cpu%d" % cpu][i] 514 print("Package: ", pkg, "Idle %3.4f%%" \ 515 % (float(total_idle)*100/total), file=reportfile) 516 print("package-%s=%3.4f" % \ 517 (pkg, (float(total_idle)*100/total)), file=keyvalfile) 518 except Exception as details: 519 print("Generating utilization report failed: ", details) 520 sys.exit(1) 521 522 #Add record delimiter '\n' before closing these files 523 print(file=debugfile) 524 debugfile.close() 525 print(file=reportfile) 526 reportfile.close() 527 print(file=keyvalfile) 528 keyvalfile.close() 529 530def generate_loc_intr_report(): 531 ''' Generate interrupt report of CPU's 532 ''' 533 try: 534 if (not os.path.exists('/procstat')): 535 os.mkdir('/procstat') 536 537 get_proc_loc_count(intr_stop) 538 539 reportfile = open('/procstat/cpu-loc_interrupts', 'a') 540 print("==============================================", file=reportfile) 541 print(" Local timer interrupt stats ", file=reportfile) 542 print("==============================================", file=reportfile) 543 544 for i in range(0, cpu_count): 545 intr_stop[i] = int(intr_stop[i]) - int(intr_start[i]) 546 print("CPU%s: %s" %(i, intr_stop[i]), file=reportfile) 547 print(file=reportfile) 548 reportfile.close() 549 except Exception as details: 550 print("Generating interrupt report failed: ", details) 551 sys.exit(1) 552 553def record_loc_intr_count(): 554 ''' Record Interrupt statistics when timer_migration 555 was disabled 556 ''' 557 try: 558 global intr_start, intr_stop 559 for i in range(0, cpu_count): 560 intr_stat_timer_0.append(intr_stop[i]) 561 intr_start = [] 562 intr_stop = [] 563 except Exception as details: 564 print("INFO: Record interrupt statistics when timer_migration=0",details) 565 566def expand_range(range_val): 567 ''' 568 Expand the range of value into actual numbers 569 ''' 570 ids_list = list() 571 try: 572 sep_comma = range_val.split(",") 573 for i in range(0, len(sep_comma)): 574 hyphen_values = sep_comma[i].split("-") 575 if len(hyphen_values) == 1: 576 ids_list.append(int(hyphen_values[0])) 577 else: 578 for j in range(int(hyphen_values[0]), int(hyphen_values[1])+1): 579 ids_list.append(j) 580 return(ids_list) 581 except Exception as details: 582 print("INFO: expand_pkg_grps failed ", details) 583 584def is_quad_core(): 585 ''' 586 Read /proc/cpuinfo and check if system is Quad core 587 ''' 588 try: 589 cpuinfo = open('/proc/cpuinfo', 'r') 590 for line in cpuinfo: 591 if line.startswith('cpu cores'): 592 cores = line.split("cpu cores") 593 num_cores = cores[1].split(":") 594 cpuinfo.close() 595 if int(num_cores[1]) == 4: 596 return(1) 597 else: 598 return(0) 599 except IOError as e: 600 print("Failed to get cpu core information", e) 601 sys.exit(1) 602 603def validate_cpugrp_map(cpu_group, sched_mc_level, sched_smt_level): 604 ''' 605 Verify if cpugrp belong to same package 606 ''' 607 modi_cpu_grp = cpu_group[:] 608 try: 609 if is_hyper_threaded(): 610 for pkg in sorted(cpu_map.keys()): 611 # if CPU utilized is across package this condition will be true 612 if len(modi_cpu_grp) != len(cpu_group): 613 break 614 for core in sorted(cpu_map[pkg].keys()): 615 core_cpus = cpu_map[pkg][core] 616 if core_cpus == modi_cpu_grp: 617 return 0 618 else: 619 #if CPUs used across the cores 620 for i in range(0, len(core_cpus)): 621 if core_cpus[i] in modi_cpu_grp: 622 modi_cpu_grp.remove(core_cpus[i]) 623 if len(modi_cpu_grp) == 0: 624 return 0 625 #This code has to be deleted 626 #else: 627 # If sched_smt == 0 then its oky if threads run 628 # in different cores of same package 629 #if sched_smt_level > 0 : 630 #return 1 631 else: 632 for pkg in sorted(cpu_map.keys()): 633 pkg_cpus = cpu_map[pkg] 634 if len(cpu_group) == len(pkg_cpus): 635 if pkg_cpus == cpu_group: 636 return(0) 637 else: 638 if int(cpus_utilized[0]) in cpu_map[pkg] or int(cpus_utilized[1]) in cpu_map[pkg]: 639 return(0) 640 641 return(1) 642 643 except Exception as details: 644 print("Exception in validate_cpugrp_map: ", details) 645 sys.exit(1) 646 647 648def verify_sched_domain_dmesg(sched_mc_level, sched_smt_level): 649 ''' 650 Read sched domain information from dmesg. 651 ''' 652 cpu_group = list() 653 try: 654 dmesg_info = os.popen('dmesg').read() 655 if dmesg_info != "": 656 lines = dmesg_info.split('\n') 657 for i in range(0, len(lines)): 658 if lines[i].endswith('CPU'): 659 groups = lines[i+1].split("groups:") 660 group_info = groups[1] 661 if group_info.find("(") != -1: 662 openindex=group_info.index("(") 663 closeindex=group_info.index(")") 664 group_info=group_info.replace\ 665 (group_info[openindex:closeindex+1],"") 666 667 subgroup = group_info.split(",") 668 for j in range(0, len(subgroup)): 669 cpu_group = expand_range(subgroup[j]) 670 status = validate_cpugrp_map(cpu_group, sched_mc_level,\ 671 sched_smt_level) 672 if status == 1: 673 if is_quad_core() == 1: 674 if int(sched_mc_level) == 0: 675 return(0) 676 else: 677 return(1) 678 else: 679 return(1) 680 return(0) 681 else: 682 return(1) 683 except Exception as details: 684 print("Reading dmesg failed", details) 685 sys.exit(1) 686 687def get_cpu_utilization(cpu): 688 ''' Return cpu utilization of cpu_id 689 ''' 690 try: 691 for l in sorted(stats_percentage.keys()): 692 if cpu == stats_percentage[l][0]: 693 return stats_percentage[l][1] 694 return -1 695 except Exception as details: 696 print("Exception in get_cpu_utilization", details) 697 sys.exit(1) 698 699def validate_cpu_consolidation(stress, work_ld, sched_mc_level, sched_smt_level): 700 ''' Verify if cpu's on which threads executed belong to same 701 package 702 ''' 703 cpus_utilized = list() 704 threads = get_job_count(stress, work_ld, sched_smt_level) 705 try: 706 for l in sorted(stats_percentage.keys()): 707 #modify threshold 708 cpu_id = stats_percentage[l][0].split("cpu") 709 if cpu_id[1] == '': 710 continue 711 if int(cpu_id[1]) in cpus_utilized: 712 continue 713 if is_hyper_threaded(): 714 if work_ld == "kernbench" and sched_smt_level < sched_mc_level: 715 siblings = get_siblings(cpu_id[1]) 716 if siblings != "": 717 sib_list = siblings.split() 718 utilization = int(stats_percentage[l][1]) 719 for i in range(0, len(sib_list)): 720 utilization += int(get_cpu_utilization("cpu%s" %sib_list[i])) 721 else: 722 utilization = stats_percentage[l][1] 723 if utilization > 40: 724 cpus_utilized.append(int(cpu_id[1])) 725 if siblings != "": 726 for i in range(0, len(sib_list)): 727 cpus_utilized.append(int(sib_list[i])) 728 else: 729 # This threshold wuld be modified based on results 730 if stats_percentage[l][1] > 40: 731 cpus_utilized.append(int(cpu_id[1])) 732 else: 733 if work_ld == "kernbench" : 734 if stats_percentage[l][1] > 50: 735 cpus_utilized.append(int(cpu_id[1])) 736 else: 737 if stats_percentage[l][1] > 70: 738 cpus_utilized.append(int(cpu_id[1])) 739 cpus_utilized.sort() 740 print("INFO: CPU's utilized ", cpus_utilized) 741 742 # If length of CPU's utilized is not = number of jobs exit with 1 743 if len(cpus_utilized) < threads: 744 return 1 745 746 status = validate_cpugrp_map(cpus_utilized, sched_mc_level, \ 747 sched_smt_level) 748 if status == 1: 749 print("INFO: CPUs utilized is not in same package or core") 750 751 return(status) 752 except Exception as details: 753 print("Exception in validate_cpu_consolidation: ", details) 754 sys.exit(1) 755 756def get_cpuid_max_intr_count(): 757 '''Return the cpu id's of two cpu's with highest number of intr''' 758 try: 759 highest = 0 760 second_highest = 0 761 cpus_utilized = [] 762 763 #Skipping CPU0 as it is generally high 764 for i in range(1, cpu_count): 765 if int(intr_stop[i]) > int(highest): 766 if highest != 0: 767 second_highest = highest 768 cpu2_max_intr = cpu1_max_intr 769 highest = int(intr_stop[i]) 770 cpu1_max_intr = i 771 else: 772 if int(intr_stop[i]) > int(second_highest): 773 second_highest = int(intr_stop[i]) 774 cpu2_max_intr = i 775 cpus_utilized.append(cpu1_max_intr) 776 cpus_utilized.append(cpu2_max_intr) 777 778 for i in range(1, cpu_count): 779 if i != cpu1_max_intr and i != cpu2_max_intr: 780 diff = second_highest - intr_stop[i] 781 ''' Threshold of difference has to be manipulated ''' 782 if diff < 10000: 783 print("INFO: Diff in interrupt count is below threshold") 784 cpus_utilized = [] 785 return cpus_utilized 786 print("INFO: Interrupt count in other CPU's low as expected") 787 return cpus_utilized 788 except Exception as details: 789 print("Exception in get_cpuid_max_intr_count: ", details) 790 sys.exit(1) 791 792def validate_ilb (sched_mc_level, sched_smt_level): 793 ''' Validate if ilb is running in same package where work load is running 794 ''' 795 try: 796 cpus_utilized = get_cpuid_max_intr_count() 797 if not cpus_utilized: 798 return 1 799 800 status = validate_cpugrp_map(cpus_utilized, sched_mc_level, sched_smt_level) 801 return status 802 except Exception as details: 803 print("Exception in validate_ilb: ", details) 804 sys.exit(1) 805 806def reset_schedmc(): 807 ''' Routine to reset sched_mc_power_savings to Zero level 808 ''' 809 try: 810 os.system('echo 0 > \ 811 /sys/devices/system/cpu/sched_mc_power_savings 2>/dev/null') 812 except OSError as e: 813 print("Could not set sched_mc_power_savings to 0", e) 814 sys.exit(1) 815 816def reset_schedsmt(): 817 ''' Routine to reset sched_smt_power_savings to Zero level 818 ''' 819 try: 820 os.system('echo 0 > \ 821 /sys/devices/system/cpu/sched_smt_power_savings 2>/dev/null') 822 except OSError as e: 823 print("Could not set sched_smt_power_savings to 0", e) 824 sys.exit(1) 825 826def stop_wkld(work_ld): 827 ''' Kill workload triggered in background 828 ''' 829 try: 830 os.system('pkill %s 2>/dev/null' %work_ld) 831 if work_ld == "kernbench": 832 os.system('pkill make 2>/dev/null') 833 except OSError as e: 834 print("Exception in stop_wkld", e) 835 sys.exit(1) 836