19
19
MSR_IA32_MISC_ENABLE_TURBO_DISABLE_BIT = 38
20
20
21
21
OS_LINUX = sys .platform .startswith ('linux' )
22
+ PLATFORM_X86 = platform .machine () in ('x86' , 'x86_64' , 'amd64' )
22
23
23
24
24
25
def is_root ():
@@ -119,21 +120,23 @@ def write(self, tune):
119
120
pass
120
121
121
122
123
+ class IntelPstateOperation (Operation ):
124
+ @staticmethod
125
+ def available ():
126
+ return use_intel_pstate ()
127
+
128
+
122
129
class TurboBoostMSR (Operation ):
123
130
"""
124
- Get/Set Turbo Boost mode of Intel CPUs using /dev/cpu/N/msr.
131
+ Get/Set Turbo Boost mode of x86 CPUs using /dev/cpu/N/msr
125
132
"""
126
133
127
134
@staticmethod
128
135
def available ():
129
- return (
130
- OS_LINUX and
131
- not use_intel_pstate () and
132
- platform .machine () in ('x86' , 'x86_64' , 'amd64' )
133
- )
136
+ return OS_LINUX and PLATFORM_X86 and not use_intel_pstate ()
134
137
135
138
def __init__ (self , system ):
136
- Operation .__init__ (self , 'Turbo Boost (MSR)' , system )
139
+ super () .__init__ ('Turbo Boost (MSR)' , system )
137
140
self .cpu_states = {}
138
141
self .have_device = True
139
142
@@ -266,18 +269,14 @@ def write(self, tune):
266
269
break
267
270
268
271
269
- class TurboBoostIntelPstate (Operation ):
272
+ class TurboBoostIntelPstate (IntelPstateOperation ):
270
273
"""
271
274
Get/Set Turbo Boost mode of Intel CPUs by reading from/writing into
272
275
/sys/devices/system/cpu/intel_pstate/no_turbo of the intel_pstate driver.
273
276
"""
274
277
275
- @staticmethod
276
- def available ():
277
- return use_intel_pstate ()
278
-
279
278
def __init__ (self , system ):
280
- Operation .__init__ (self , 'Turbo Boost (intel_pstate)' , system )
279
+ super () .__init__ ('Turbo Boost (intel_pstate)' , system )
281
280
self .path = sysfs_path ("devices/system/cpu/intel_pstate/no_turbo" )
282
281
self .enabled = None
283
282
@@ -337,54 +336,92 @@ def write(self, tune):
337
336
self .log_action ("Turbo Boost %s: %s" % (action , msg ))
338
337
339
338
340
- class CPUGovernorIntelPstate (Operation ):
339
+ class CPUGovernor (Operation ):
341
340
"""
342
- Get/Set CPU scaling governor of the intel_pstate driver.
341
+ Get/Set CPU scaling governor
343
342
"""
344
343
BENCHMARK_GOVERNOR = 'performance'
345
344
346
345
@staticmethod
347
346
def available ():
348
- return use_intel_pstate ()
347
+ return os .path .exists (
348
+ sysfs_path ("devices/system/cpu/cpu0/cpufreq/scaling_governor" )
349
+ )
349
350
350
351
def __init__ (self , system ):
351
- Operation .__init__ (self , 'CPU scaling governor (intel_pstate)' ,
352
- system )
353
- self .path = sysfs_path ("devices/system/cpu/cpu0/cpufreq/scaling_governor" )
354
- self .governor = None
355
-
356
- def read_governor (self ):
357
- governor = self .read_first_line (self .path )
358
- if governor :
359
- self .governor = governor
360
- else :
361
- self .error ("Unable to read CPU scaling governor from %s" % self .path )
352
+ super ().__init__ ('CPU scaling governor' , system )
353
+ self .device_syspath = sysfs_path ("devices/system/cpu" )
354
+
355
+ def read_governor (self , cpu ):
356
+ filename = os .path .join (self .device_syspath , 'cpu%s/cpufreq/scaling_governor' % cpu )
357
+ try :
358
+ with open (filename , "r" ) as fp :
359
+ return fp .readline ().rstrip ()
360
+ except OSError as exc :
361
+ self .check_permission_error (exc )
362
+ self .error ("Unable to read CPU scaling governor from %s" % filename )
363
+ return None
362
364
363
365
def show (self ):
364
- self .read_governor ()
365
- if not self .governor :
366
+ cpus = {}
367
+ for cpu in range (self .system .logical_cpu_count ):
368
+ governor = self .read_governor (cpu )
369
+ if governor is not None :
370
+ cpus [cpu ] = governor
371
+
372
+ infos = format_cpu_infos (cpus )
373
+ if not infos :
366
374
return
375
+ self .log_state ('; ' .join (infos ))
367
376
368
- self .log_state (self .governor )
369
- self .tuned_for_benchmarks = (self .governor == self .BENCHMARK_GOVERNOR )
377
+ self .tuned_for_benchmarks = all (
378
+ governor == self .BENCHMARK_GOVERNOR for governor in cpus .values ()
379
+ )
370
380
if not self .tuned_for_benchmarks :
371
381
self .advice ('Use CPU scaling governor %r'
372
382
% self .BENCHMARK_GOVERNOR )
373
383
374
- def write (self , tune ):
375
- self .read_governor ()
376
- if not self .governor :
377
- return
384
+ def write_governor (self , filename , new_governor ):
385
+ with open (filename , "r" ) as fp :
386
+ governor = fp .readline ().rstrip ()
378
387
379
- new_governor = 'performance' if tune else 'powersave'
380
- if new_governor == self .governor :
381
- return
388
+ if new_governor == governor :
389
+ return False
390
+
391
+ with open (filename , "w" ) as fp :
392
+ fp .write (new_governor )
393
+ return True
394
+
395
+ def write_cpu (self , cpu , tune ):
396
+ governor = self .read_governor (cpu )
397
+ if not governor :
398
+ self .warning ("Unable to read governor of CPU %s" % (cpu ))
399
+ return False
400
+
401
+ new_governor = self .BENCHMARK_GOVERNOR if tune else "powersave"
402
+ filename = os .path .join (self .device_syspath , 'cpu%s/cpufreq/scaling_governor' % cpu )
382
403
try :
383
- write_text ( self .path , new_governor )
404
+ return self .write_governor ( filename , new_governor )
384
405
except OSError as exc :
385
- self .error ("Failed to set the CPU scaling governor: %s" % exc )
386
- else :
387
- self .log_action ("CPU scaling governor set to %s" % new_governor )
406
+ self .check_permission_error (exc )
407
+ self .error ("Unable to write governor of CPU %s: %s"
408
+ % (cpu , exc ))
409
+
410
+ def write (self , tune ):
411
+ modified = []
412
+ for cpu in self .system .cpus :
413
+ if self .write_cpu (cpu , tune ):
414
+ modified .append (cpu )
415
+ if self .permission_error :
416
+ break
417
+
418
+ if modified :
419
+ cpus = format_cpu_list (modified )
420
+ if tune :
421
+ action = "set to performance"
422
+ else :
423
+ action = "reset to powersave"
424
+ self .log_action ("CPU scaling governor of CPUs %s %s" % (cpus , action ))
388
425
389
426
390
427
class LinuxScheduler (Operation ):
@@ -398,7 +435,7 @@ def available():
398
435
return OS_LINUX
399
436
400
437
def __init__ (self , system ):
401
- Operation .__init__ (self , 'Linux scheduler' , system )
438
+ super () .__init__ ('Linux scheduler' , system )
402
439
self .ncpu = None
403
440
self .linux_version = None
404
441
@@ -473,7 +510,7 @@ def available(cls):
473
510
return os .path .exists (cls .path )
474
511
475
512
def __init__ (self , system ):
476
- Operation .__init__ (self , 'ASLR' , system )
513
+ super () .__init__ ('ASLR' , system )
477
514
478
515
def show (self ):
479
516
line = self .read_first_line (self .path )
@@ -519,7 +556,7 @@ def available():
519
556
return os .path .exists (sysfs_path ("devices/system/cpu/cpu0/cpufreq" ))
520
557
521
558
def __init__ (self , system ):
522
- Operation .__init__ (self , 'CPU Frequency' , system )
559
+ super () .__init__ ('CPU Frequency' , system )
523
560
self .device_syspath = sysfs_path ("devices/system/cpu" )
524
561
525
562
def read_cpu (self , cpu ):
@@ -617,7 +654,7 @@ def available(cls):
617
654
return os .path .exists (cls .irq_path )
618
655
619
656
def __init__ (self , system ):
620
- Operation .__init__ (self , 'IRQ affinity' , system )
657
+ super () .__init__ ('IRQ affinity' , system )
621
658
self .irq_affinity_path = os .path .join (self .irq_path , "%s/smp_affinity" )
622
659
self .default_affinity_path = os .path .join (self .irq_path , 'default_smp_affinity' )
623
660
@@ -828,13 +865,10 @@ def write(self, tune):
828
865
self .write_irqs (cpus )
829
866
830
867
831
- class CheckNOHZFullIntelPstate (Operation ):
832
- @staticmethod
833
- def available ():
834
- return use_intel_pstate ()
868
+ class CheckNOHZFullIntelPstate (IntelPstateOperation ):
835
869
836
870
def __init__ (self , system ):
837
- Operation .__init__ (self , 'Check nohz_full' , system )
871
+ super () .__init__ ('Check nohz_full' , system )
838
872
839
873
def show (self ):
840
874
nohz_full = self .read_first_line (sysfs_path ('devices/system/cpu/nohz_full' ))
@@ -865,7 +899,7 @@ def available(cls):
865
899
return os .path .exists (cls .path )
866
900
867
901
def __init__ (self , system ):
868
- Operation .__init__ (self , 'Power supply' , system )
902
+ super () .__init__ ('Power supply' , system )
869
903
870
904
def read_power_supply (self ):
871
905
# Python implementation of the on_ac_power shell script
@@ -912,7 +946,7 @@ def available(cls):
912
946
return os .path .exists (cls .path )
913
947
914
948
def __init__ (self , system ):
915
- Operation .__init__ (self , 'Perf event' , system )
949
+ super () .__init__ ('Perf event' , system )
916
950
917
951
def read_max_sample_rate (self ):
918
952
line = self .read_first_line (self .path )
@@ -950,18 +984,24 @@ def write(self, tune):
950
984
951
985
952
986
OPERATIONS = [
987
+ # Generic operations
953
988
PerfEvent ,
954
989
ASLR ,
955
990
LinuxScheduler ,
956
991
CPUFrequency ,
992
+ IRQAffinity ,
993
+ PowerSupply ,
994
+
957
995
# Setting the CPU scaling governor resets no_turbo
958
996
# and so must be set before Turbo Boost
959
- CPUGovernorIntelPstate ,
997
+ CPUGovernor ,
998
+
999
+ # Intel Pstate Operations
960
1000
TurboBoostIntelPstate ,
961
1001
CheckNOHZFullIntelPstate ,
1002
+
1003
+ # X86 Operations
962
1004
TurboBoostMSR ,
963
- IRQAffinity ,
964
- PowerSupply ,
965
1005
]
966
1006
967
1007
0 commit comments