hyperctl 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +9 -0
- data/Gemfile +3 -0
- data/README.md +200 -0
- data/Rakefile +14 -0
- data/bin/hyperctl +90 -0
- data/hyperctl.gemspec +33 -0
- data/lib/hyperctl/sysfs.rb +189 -0
- data/lib/hyperctl/version.rb +3 -0
- data/lib/hyperctl.rb +43 -0
- data/spec/hyperctl_spec.rb +123 -0
- data/spec/hyperctl_sysfs_spec.rb +154 -0
- data/spec/spec_helper.rb +102 -0
- metadata +178 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: bd42c9d0ce6995577336ac5d079c38b2dbcf5f0b
|
4
|
+
data.tar.gz: d71520d05bb74c3bb584868fbdb9663be22b7b6c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d90ca4e32248d536a58eb2a9f463e69caa9cbf8617d2d9e0b86358f38f95e2727292476c0ac94ba5acceadf373ee4c6db6075f7cacbd19acfbad78f63bc856d8
|
7
|
+
data.tar.gz: f3fdfd9fbc3ee5c449efddcd8af2daf59ed74123efe78769add4bffd3d9e7ae87942133907d3504cc65c51fb7a8f4783f2313056f63eaa2d2e511b2c24d4d523
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
Ruby hyperctl Gem
|
2
|
+
=================
|
3
|
+
|
4
|
+
[](https://travis-ci.org/jhoblitt/hyperctl)
|
5
|
+
|
6
|
+
#### Table of Contents
|
7
|
+
|
8
|
+
1. [Summary](#summary)
|
9
|
+
2. [Description](#description)
|
10
|
+
3. [Install](#install)
|
11
|
+
4. [Usage](#usage)
|
12
|
+
5. [Versioning](#versioning)
|
13
|
+
6. [Support](#support)
|
14
|
+
7. [Contributing](#contributing)
|
15
|
+
8. [See Also](#see-also)
|
16
|
+
|
17
|
+
Summary
|
18
|
+
-------
|
19
|
+
|
20
|
+
A utility for enabling/disabling hyperthreading
|
21
|
+
|
22
|
+
|
23
|
+
Description
|
24
|
+
-----------
|
25
|
+
|
26
|
+
This Gem provides a simple cli utility named `hyperctl` that can check the
|
27
|
+
status of and [with appropriate permissions] enable/disable
|
28
|
+
hyperthreading/SMT/sibling cores on Linux via the
|
29
|
+
[`sysfs`](https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt)
|
30
|
+
pseudo filesystem. It should be compatible with most modern Linux
|
31
|
+
distributions as long as `sysfs` is mounted at `/sysfs`.
|
32
|
+
|
33
|
+
|
34
|
+
Install
|
35
|
+
-------
|
36
|
+
|
37
|
+
### via rubygems
|
38
|
+
|
39
|
+
gem install hyperctl
|
40
|
+
|
41
|
+
### from git repo with bundler
|
42
|
+
|
43
|
+
bundle install
|
44
|
+
bundle exec rake install
|
45
|
+
|
46
|
+
|
47
|
+
Usage
|
48
|
+
-----
|
49
|
+
|
50
|
+
### `hyperctl`
|
51
|
+
|
52
|
+
Usage:
|
53
|
+
hyperctl
|
54
|
+
hyperctl (--enable | --disable) [--quiet]
|
55
|
+
hyperctl --status (--enable | --disable) [--quiet]
|
56
|
+
hyperctl -h | --help
|
57
|
+
hyperctl --version
|
58
|
+
|
59
|
+
Options:
|
60
|
+
--enable Enable hyperthreading.
|
61
|
+
--disable Diable hyperthreading.
|
62
|
+
--status Report hyperthreading state.
|
63
|
+
--quiet Suppress stdout.
|
64
|
+
--version Show version.
|
65
|
+
-h --help Show this screen.
|
66
|
+
|
67
|
+
#### Exit codes
|
68
|
+
|
69
|
+
* `0` - success
|
70
|
+
* `1` - option parsing related error
|
71
|
+
* `2` - system error (Eg., permission denied)
|
72
|
+
* `3` - status does not match desired state
|
73
|
+
|
74
|
+
#### no options
|
75
|
+
|
76
|
+
Prints the current status of hyperthreading on the system to the `stdout`.
|
77
|
+
Exits with `0` if no errors were encountered.
|
78
|
+
|
79
|
+
$ hyperctl
|
80
|
+
cpu0 : enabled - hypertheading: enabled
|
81
|
+
cpu1 : enabled - hypertheading: enabled
|
82
|
+
cpu2 : enabled - hypertheading: enabled
|
83
|
+
cpu3 : enabled - hypertheading: enabled
|
84
|
+
cpu4 : enabled - hypertheading: enabled
|
85
|
+
cpu5 : enabled - hypertheading: enabled
|
86
|
+
cpu6 : enabled - hypertheading: enabled
|
87
|
+
cpu7 : enabled - hypertheading: enabled
|
88
|
+
|
89
|
+
#### `(--enable | --disable) [--quiet]`
|
90
|
+
|
91
|
+
Attempt to enable or disable all hyperthread/SMT/sibling cores on the system.
|
92
|
+
Exits with `0` upon success, `2` for system errors, or `3` for state change
|
93
|
+
failures (unlikely).
|
94
|
+
|
95
|
+
With appropriate permissions to modify the appropriate sysfs entries:
|
96
|
+
|
97
|
+
$ sudo hyperctl --disable
|
98
|
+
cpu0 : enabled - hypertheading: disabled
|
99
|
+
cpu1 : enabled - hypertheading: disabled
|
100
|
+
cpu2 : enabled - hypertheading: disabled
|
101
|
+
cpu3 : enabled - hypertheading: disabled
|
102
|
+
cpu4 : disabled - hypertheading: disabled
|
103
|
+
cpu5 : disabled - hypertheading: disabled
|
104
|
+
cpu6 : disabled - hypertheading: disabled
|
105
|
+
cpu7 : disabled - hypertheading: disabled
|
106
|
+
$ echo $?
|
107
|
+
0
|
108
|
+
|
109
|
+
Without appropriate permissions:
|
110
|
+
|
111
|
+
$ hyperctl --disable
|
112
|
+
Permission denied @ rb_sysopen - /sys/devices/system/cpu/cpu4/online
|
113
|
+
$ echo $?
|
114
|
+
2
|
115
|
+
|
116
|
+
#### `--status (--enable | --disable) [--quiet]`
|
117
|
+
|
118
|
+
Checks the status of hyperthread/SMT/sibling cores on the system. Exits with
|
119
|
+
`0` if the state matches the `(--enable | --disable)` option, otherwise with
|
120
|
+
`3`
|
121
|
+
|
122
|
+
System already in `--disable` state:
|
123
|
+
|
124
|
+
$ sudo hyperctl --status --disable
|
125
|
+
cpu0 : enabled - hypertheading: disabled
|
126
|
+
cpu1 : enabled - hypertheading: disabled
|
127
|
+
cpu2 : enabled - hypertheading: disabled
|
128
|
+
cpu3 : enabled - hypertheading: disabled
|
129
|
+
cpu4 : disabled - hypertheading: disabled
|
130
|
+
cpu5 : disabled - hypertheading: disabled
|
131
|
+
cpu6 : disabled - hypertheading: disabled
|
132
|
+
cpu7 : disabled - hypertheading: disabled
|
133
|
+
$ echo $?
|
134
|
+
0
|
135
|
+
|
136
|
+
System not in `--enable` state:
|
137
|
+
|
138
|
+
$ sudo hyperctl --status --enable
|
139
|
+
cpu0 : enabled - hypertheading: disabled
|
140
|
+
cpu1 : enabled - hypertheading: disabled
|
141
|
+
cpu2 : enabled - hypertheading: disabled
|
142
|
+
cpu3 : enabled - hypertheading: disabled
|
143
|
+
cpu4 : disabled - hypertheading: disabled
|
144
|
+
cpu5 : disabled - hypertheading: disabled
|
145
|
+
cpu6 : disabled - hypertheading: disabled
|
146
|
+
cpu7 : disabled - hypertheading: disabled
|
147
|
+
$ echo $?
|
148
|
+
3
|
149
|
+
|
150
|
+
#### `[--quiet]`
|
151
|
+
|
152
|
+
Suppresses the `stdout` status message. Intended for usage from scripts.
|
153
|
+
|
154
|
+
$ sudo hyperctl --status --enable --quiet
|
155
|
+
$ echo $?
|
156
|
+
3
|
157
|
+
|
158
|
+
$ sudo hyperctl --status --disable --quiet
|
159
|
+
$ echo $?
|
160
|
+
0
|
161
|
+
|
162
|
+
|
163
|
+
Versioning
|
164
|
+
----------
|
165
|
+
|
166
|
+
This Gem is versioned according to the [Semantic Versioning
|
167
|
+
2.0.0](http://semver.org/spec/v2.0.0.html) specification.
|
168
|
+
|
169
|
+
|
170
|
+
Support
|
171
|
+
-------
|
172
|
+
|
173
|
+
Please log tickets and issues at [github](https://github.com/jhoblitt/hyperctl)
|
174
|
+
|
175
|
+
|
176
|
+
Contributing
|
177
|
+
------------
|
178
|
+
|
179
|
+
1. Fork it on github
|
180
|
+
2. Make a local clone of your fork
|
181
|
+
3. Create a topic branch. Eg, `feature/mousetrap`
|
182
|
+
4. Make/commit changes
|
183
|
+
* Commit messages should be in
|
184
|
+
[imperative tense](http://git-scm.com/book/ch5-2.html)
|
185
|
+
* Check that `Rspec` unit tests are not broken and coverage is added for
|
186
|
+
new features - `bundle exec rake spec`
|
187
|
+
* Documentation of API/features is updated as appropriate in the README
|
188
|
+
5. When the feature is complete, rebase / squash the branch history as
|
189
|
+
necessary to remove "fix typo", "oops", "whitespace" and other trivial
|
190
|
+
commits
|
191
|
+
6. Push the topic branch to github
|
192
|
+
7. Open a Pull Request (PR) from the *topic branch* onto parent repo's `master`
|
193
|
+
branch
|
194
|
+
|
195
|
+
|
196
|
+
See Also
|
197
|
+
--------
|
198
|
+
|
199
|
+
* [Linux sysfs docs](https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt)
|
200
|
+
* [Linux cpu-hotplug docs](https://www.kernel.org/doc/Documentation/cpu-hotplug.txt)
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'yard'
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
YARD::Rake::YardocTask.new do |t|
|
8
|
+
t.files = ['lib/**/*.rb']
|
9
|
+
t.stats_options = ['--list-undoc']
|
10
|
+
end
|
11
|
+
|
12
|
+
task :default => [
|
13
|
+
:spec,
|
14
|
+
]
|
data/bin/hyperctl
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'hyperctl'
|
4
|
+
require "docopt"
|
5
|
+
|
6
|
+
doc = <<DOCOPT
|
7
|
+
#{__FILE__}
|
8
|
+
|
9
|
+
Usage:
|
10
|
+
#{__FILE__}
|
11
|
+
#{__FILE__} (--enable | --disable) [--quiet]
|
12
|
+
#{__FILE__} --status (--enable | --disable) [--quiet]
|
13
|
+
#{__FILE__} -h | --help
|
14
|
+
#{__FILE__} --version
|
15
|
+
|
16
|
+
Options:
|
17
|
+
--enable Enable hyperthreading.
|
18
|
+
--disable Diable hyperthreading.
|
19
|
+
--status Report hyperthreading state.
|
20
|
+
--quiet Suppress stdout.
|
21
|
+
--version Show version.
|
22
|
+
-h --help Show this screen.
|
23
|
+
|
24
|
+
DOCOPT
|
25
|
+
|
26
|
+
|
27
|
+
@options = {}
|
28
|
+
begin
|
29
|
+
@options = Docopt::docopt(doc)
|
30
|
+
rescue Docopt::Exit => e
|
31
|
+
puts e.message
|
32
|
+
exit 1
|
33
|
+
end
|
34
|
+
|
35
|
+
if @options['--version']
|
36
|
+
puts Hyperctl::VERSION
|
37
|
+
exit 0
|
38
|
+
end
|
39
|
+
|
40
|
+
hctl = Hyperctl::Sysfs.new
|
41
|
+
|
42
|
+
exit_code = 0
|
43
|
+
|
44
|
+
begin
|
45
|
+
if @options['--status']
|
46
|
+
exit_code = check_status(hctl)
|
47
|
+
elsif @options['--enable'] || @options['--disable']
|
48
|
+
exit_code = change_state(hctl)
|
49
|
+
end
|
50
|
+
|
51
|
+
unless @options['--quiet']
|
52
|
+
text = Hyperctl.status(hctl)
|
53
|
+
puts text
|
54
|
+
end
|
55
|
+
rescue Errno::EACCES => e
|
56
|
+
puts e.message
|
57
|
+
exit 2
|
58
|
+
end
|
59
|
+
|
60
|
+
exit exit_code
|
61
|
+
|
62
|
+
BEGIN {
|
63
|
+
def change_state(hctl)
|
64
|
+
if @options['--enable']
|
65
|
+
Hyperctl.enable(hctl)
|
66
|
+
hctl.refresh
|
67
|
+
return check_status(hctl)
|
68
|
+
end
|
69
|
+
|
70
|
+
if @options['--disable']
|
71
|
+
Hyperctl.disable(hctl)
|
72
|
+
hctl.refresh
|
73
|
+
return check_status(hctl)
|
74
|
+
end
|
75
|
+
|
76
|
+
raise
|
77
|
+
end
|
78
|
+
|
79
|
+
def check_status(hctl)
|
80
|
+
if @options['--enable']
|
81
|
+
return hctl.all_cores_enabled? ? 0 : 3
|
82
|
+
end
|
83
|
+
|
84
|
+
if @options['--disable']
|
85
|
+
return hctl.all_siblings_disabled? ? 0 : 3
|
86
|
+
end
|
87
|
+
|
88
|
+
raise
|
89
|
+
end
|
90
|
+
}
|
data/hyperctl.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
2
|
+
require 'hyperctl/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'hyperctl'
|
6
|
+
s.version = Hyperctl::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ['Joshua Hoblitt']
|
9
|
+
s.email = ['jhoblitt@cpan.org']
|
10
|
+
s.homepage = 'https://github.com/jhoblitt/hyperctl'
|
11
|
+
s.summary = %q{A utility for enabling/disabling hyperthreading}
|
12
|
+
s.description = %q{This Gem provides a simple cli utility named `hyperctl`
|
13
|
+
that can check the status of and [with appropriate permissions] enable/disable
|
14
|
+
hyperthreading/SMT/sibling cores on Linux via the `sysfs` pseudo filesystem.
|
15
|
+
It should be compatible with most modern Linux distributions as long as `sysfs` is mounted at `/sysfs`.}
|
16
|
+
s.license = 'Apache 2.0'
|
17
|
+
|
18
|
+
s.required_ruby_version = '>= 1.8.7'
|
19
|
+
s.add_runtime_dependency('docopt', '~> 0.5.0')
|
20
|
+
s.add_development_dependency('rspec', '~> 3.0')
|
21
|
+
s.add_development_dependency('rspec-expectations', '~> 3.0')
|
22
|
+
s.add_development_dependency('rspec-mocks', '~> 3.0')
|
23
|
+
s.add_development_dependency('rake', '~> 10.0')
|
24
|
+
s.add_development_dependency('fakefs', '~> 0.5.2')
|
25
|
+
s.add_development_dependency('mocha', '~> 1.0')
|
26
|
+
s.add_development_dependency('yard', '~> 0.8')
|
27
|
+
|
28
|
+
s.rubygems_version = '>= 1.6.1'
|
29
|
+
s.files = `git ls-files`.split("\n")
|
30
|
+
s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
|
31
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
32
|
+
s.require_path = 'lib'
|
33
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
class Hyperctl::Sysfs
|
2
|
+
attr_accessor :cpu_info
|
3
|
+
|
4
|
+
# @api private
|
5
|
+
def initialize
|
6
|
+
@cpu_info = refresh
|
7
|
+
end
|
8
|
+
|
9
|
+
# Refresh the `cpu_info` [Hash] of the current CPU states
|
10
|
+
#
|
11
|
+
# @return [Hash] of cpu status
|
12
|
+
# @api public
|
13
|
+
def refresh
|
14
|
+
info = {}
|
15
|
+
|
16
|
+
# get a listing of all cpu cores
|
17
|
+
cpu_dirs = Dir.glob('/sys/devices/system/cpu/cpu[0-9]*')
|
18
|
+
|
19
|
+
cpu_dirs.each do |d|
|
20
|
+
# find the "name" of the cpu based on the sysfs dir. Eg, cpu15
|
21
|
+
cpu_name = File.basename d
|
22
|
+
cpu_idx = cpu_name.to_sym
|
23
|
+
info[cpu_idx] = { :name => cpu_name }
|
24
|
+
|
25
|
+
# find the numeric core_id. Eg, 15 in sysfs as
|
26
|
+
# /sys/devices/system/cpu/cpu3/topology/core_id but we can parse it from
|
27
|
+
# the path
|
28
|
+
core_id = cpu_name.match(/cpu(\d+)/)[1].to_i
|
29
|
+
info[cpu_idx][:core_id] = core_id
|
30
|
+
|
31
|
+
# is the cpu online?
|
32
|
+
# if a CPU is online, /sys/devices/system/cpu/cpu1/online will be 1,
|
33
|
+
# otherwise 0. cpu0 appears to be special and does not have the online
|
34
|
+
# sysfs entry on any of the systems I inspected. I suspect that it might
|
35
|
+
# get this attribute if CONFIG_BOOTPARAM_HOTPLUG_CPU0 is enabled per
|
36
|
+
# https://www.kernel.org/doc/Documentation/cpu-hotplug.txt
|
37
|
+
path = File.join(d, 'online')
|
38
|
+
online = false
|
39
|
+
if File.exist?(path)
|
40
|
+
online = to_bool(File.read(path).chomp)
|
41
|
+
elsif core_id == 0
|
42
|
+
# cpu0 gets a special pass if the online attr is missing
|
43
|
+
online = true
|
44
|
+
end
|
45
|
+
info[cpu_idx][:online] = online
|
46
|
+
|
47
|
+
next unless online
|
48
|
+
|
49
|
+
# does the cpu have any [SMT] siblings?
|
50
|
+
# The attr /sys/devices/system/cpu/cpu6/topology/thread_siblings_list
|
51
|
+
# will list all siblings including the cpu's own core_id This attr is not
|
52
|
+
# present if the cpu is offline This attr is not present under EL5.x
|
53
|
+
# (2.6.18-164.el5PAE) on the one system I inspected that appears to have
|
54
|
+
# HT disabled in the bios (/proc/cpuinfo shows the ht cpu flag but
|
55
|
+
# there's no siblings list)
|
56
|
+
path = File.join(d, 'topology/thread_siblings_list')
|
57
|
+
if File.exist?(path)
|
58
|
+
sibs = File.read(path).chomp.split(',')
|
59
|
+
# convert core_id(s) to be numeric
|
60
|
+
sibs.map! {|s| s.to_i }
|
61
|
+
# remove the cpu's core_id from the list
|
62
|
+
sibs = sibs - [ core_id ]
|
63
|
+
unless sibs.empty?
|
64
|
+
info[cpu_idx][:thread_siblings_list] = sibs
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
@cpu_info = info
|
70
|
+
end
|
71
|
+
|
72
|
+
# List of all CPUs in system by numeric core id
|
73
|
+
#
|
74
|
+
# @return [Array<Integer>] of core ids
|
75
|
+
# @api public
|
76
|
+
def cores
|
77
|
+
cores = []
|
78
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
79
|
+
cores << cpu_info[k][:core_id]
|
80
|
+
end
|
81
|
+
|
82
|
+
return cores
|
83
|
+
end
|
84
|
+
|
85
|
+
# List of online CPUs in system by numeric core id
|
86
|
+
#
|
87
|
+
# @return [Array<Integer>] of core ids
|
88
|
+
# @api public
|
89
|
+
def online_cores
|
90
|
+
cores = []
|
91
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
92
|
+
core_id = cpu_info[k][:core_id]
|
93
|
+
if cpu_info[k][:online] == true
|
94
|
+
cores << core_id
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
return cores
|
99
|
+
end
|
100
|
+
|
101
|
+
# List of offline CPUs in system by numeric core id
|
102
|
+
#
|
103
|
+
# @return [Array<Integer>] of core ids
|
104
|
+
# @api public
|
105
|
+
def offline_cores
|
106
|
+
cores = []
|
107
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
108
|
+
core_id = cpu_info[k][:core_id]
|
109
|
+
if cpu_info[k][:online] == false
|
110
|
+
cores << core_id
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
return cores
|
115
|
+
end
|
116
|
+
|
117
|
+
# List of sibling (aka hyperthread/SMT) CPUs in system by numeric core id
|
118
|
+
#
|
119
|
+
# @return [Array<Integer>] of core ids
|
120
|
+
# @api public
|
121
|
+
def sibling_cores
|
122
|
+
cores = []
|
123
|
+
checked_cores = []
|
124
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
125
|
+
cpu = cpu_info[k]
|
126
|
+
checked_cores << cpu[:core_id]
|
127
|
+
|
128
|
+
if cpu.has_key?(:thread_siblings_list)
|
129
|
+
(cpu[:thread_siblings_list] - checked_cores).each do |core_id|
|
130
|
+
# check to see if the core is already disabled
|
131
|
+
# XXX this probably isn't nessicary as a disabled core appears to #
|
132
|
+
# never be listed as a sibiling
|
133
|
+
if cpu_info[k][:online] == true
|
134
|
+
cores << core_id
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
return cores
|
141
|
+
end
|
142
|
+
|
143
|
+
# Are all phyical/hyperthread/SMT/sibling cores enabled?
|
144
|
+
#
|
145
|
+
# @return [Bool] of status
|
146
|
+
# @api public
|
147
|
+
def all_cores_enabled?
|
148
|
+
cores.count == online_cores.count
|
149
|
+
end
|
150
|
+
|
151
|
+
# Are all hyperthread/SMT/sibling cores Disabled?
|
152
|
+
#
|
153
|
+
# @return [Bool] of status
|
154
|
+
# @api public
|
155
|
+
def all_siblings_disabled?
|
156
|
+
sibling_cores.empty?
|
157
|
+
end
|
158
|
+
|
159
|
+
# Enable a CPU by numeric core id
|
160
|
+
#
|
161
|
+
# @param core_id [Integer]
|
162
|
+
# @api public
|
163
|
+
def self.enable_core(core_id)
|
164
|
+
set_core(core_id, '1')
|
165
|
+
end
|
166
|
+
|
167
|
+
# Disable a CPU by numeric core id
|
168
|
+
#
|
169
|
+
# @param core_id [Integer]
|
170
|
+
# @api public
|
171
|
+
def self.disable_core(core_id)
|
172
|
+
set_core(core_id, '0')
|
173
|
+
end
|
174
|
+
|
175
|
+
private
|
176
|
+
|
177
|
+
def to_bool(s)
|
178
|
+
return true if s =~ /^1$/
|
179
|
+
return false
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.set_core(core_id, state)
|
183
|
+
path = File.join('/sys/devices/system/cpu', "cpu#{core_id.to_s}", 'online')
|
184
|
+
# doesn't work in ruby 1.8.7: File.write(path, '0')
|
185
|
+
File.open(path, 'w') do |f|
|
186
|
+
f.write(state)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end # class Hyperctl::Sysfs
|
data/lib/hyperctl.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'hyperctl/sysfs'
|
2
|
+
|
3
|
+
module Hyperctl
|
4
|
+
# Enable all sibling cores
|
5
|
+
#
|
6
|
+
# @param hctl [Hyperctl::Sysfs] object
|
7
|
+
# @api public
|
8
|
+
def self.enable(hctl)
|
9
|
+
# as far as I can tell, there's no way to discover the topology information
|
10
|
+
# for which cores and siblings if either of them is disabled. So we are
|
11
|
+
# just trying to enable everything that is disabled...
|
12
|
+
cores = hctl.offline_cores
|
13
|
+
cores.each {|core_id| Hyperctl::Sysfs.enable_core(core_id) }
|
14
|
+
end
|
15
|
+
|
16
|
+
# Disable all sibling cores
|
17
|
+
#
|
18
|
+
# @param hctl [Hyperctl::Sysfs] object
|
19
|
+
# @api public
|
20
|
+
def self.disable(hctl)
|
21
|
+
cores = hctl.sibling_cores
|
22
|
+
cores.each {|core_id| Hyperctl::Sysfs.disable_core(core_id) }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Generate a pretty formatted string of sibling core status
|
26
|
+
#
|
27
|
+
# @param hctl [Hyperctl::Sysfs] object
|
28
|
+
# @return [String] the generated string
|
29
|
+
# @api public
|
30
|
+
def self.status(hctl)
|
31
|
+
cpu_info = hctl.cpu_info
|
32
|
+
text = ""
|
33
|
+
cpu_info.each_key.sort_by {|k| cpu_info[k][:core_id] }.each do |k|
|
34
|
+
cpu = cpu_info[k]
|
35
|
+
state = cpu[:online] ? 'enabled' : 'disabled'
|
36
|
+
ht = cpu.has_key?(:thread_siblings_list) ? 'enabled' : 'disabled'
|
37
|
+
text << "#{sprintf('%-5s',k.to_s)}: #{sprintf('%-8s', state)}"
|
38
|
+
text << " - hypertheading: #{ht}\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
return text
|
42
|
+
end
|
43
|
+
end # module Hyperctl
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hyperctl do
|
4
|
+
let(:hctl) { Hyperctl::Sysfs.new }
|
5
|
+
|
6
|
+
describe '#status' do
|
7
|
+
context '8 physical cores with HT enabled' do
|
8
|
+
include_context "cpuinfo_8core_w_ht"
|
9
|
+
|
10
|
+
text =<<EOS
|
11
|
+
cpu0 : enabled - hypertheading: enabled
|
12
|
+
cpu1 : enabled - hypertheading: enabled
|
13
|
+
cpu2 : enabled - hypertheading: enabled
|
14
|
+
cpu3 : enabled - hypertheading: enabled
|
15
|
+
cpu4 : enabled - hypertheading: enabled
|
16
|
+
cpu5 : enabled - hypertheading: enabled
|
17
|
+
cpu6 : enabled - hypertheading: enabled
|
18
|
+
cpu7 : enabled - hypertheading: enabled
|
19
|
+
cpu8 : enabled - hypertheading: enabled
|
20
|
+
cpu9 : enabled - hypertheading: enabled
|
21
|
+
cpu10: enabled - hypertheading: enabled
|
22
|
+
cpu11: enabled - hypertheading: enabled
|
23
|
+
cpu12: enabled - hypertheading: enabled
|
24
|
+
cpu13: enabled - hypertheading: enabled
|
25
|
+
cpu14: enabled - hypertheading: enabled
|
26
|
+
cpu15: enabled - hypertheading: enabled
|
27
|
+
EOS
|
28
|
+
it do
|
29
|
+
hctl.stubs(:cpu_info).returns(info)
|
30
|
+
expect(Hyperctl.status(hctl)).to eq(text)
|
31
|
+
end
|
32
|
+
end # 8 physical cores with HT enabled
|
33
|
+
|
34
|
+
context '12 physical cores with HT disabled' do
|
35
|
+
include_context "cpuinfo_12core_wo_ht"
|
36
|
+
text =<<EOS
|
37
|
+
cpu0 : enabled - hypertheading: disabled
|
38
|
+
cpu1 : enabled - hypertheading: disabled
|
39
|
+
cpu2 : enabled - hypertheading: disabled
|
40
|
+
cpu3 : enabled - hypertheading: disabled
|
41
|
+
cpu4 : enabled - hypertheading: disabled
|
42
|
+
cpu5 : enabled - hypertheading: disabled
|
43
|
+
cpu6 : enabled - hypertheading: disabled
|
44
|
+
cpu7 : enabled - hypertheading: disabled
|
45
|
+
cpu8 : enabled - hypertheading: disabled
|
46
|
+
cpu9 : enabled - hypertheading: disabled
|
47
|
+
cpu10: enabled - hypertheading: disabled
|
48
|
+
cpu11: enabled - hypertheading: disabled
|
49
|
+
cpu12: disabled - hypertheading: disabled
|
50
|
+
cpu13: disabled - hypertheading: disabled
|
51
|
+
cpu14: disabled - hypertheading: disabled
|
52
|
+
cpu15: disabled - hypertheading: disabled
|
53
|
+
cpu16: disabled - hypertheading: disabled
|
54
|
+
cpu17: disabled - hypertheading: disabled
|
55
|
+
cpu18: disabled - hypertheading: disabled
|
56
|
+
cpu19: disabled - hypertheading: disabled
|
57
|
+
cpu20: disabled - hypertheading: disabled
|
58
|
+
cpu21: disabled - hypertheading: disabled
|
59
|
+
cpu22: disabled - hypertheading: disabled
|
60
|
+
cpu23: disabled - hypertheading: disabled
|
61
|
+
EOS
|
62
|
+
it do
|
63
|
+
hctl.stubs(:cpu_info).returns(info)
|
64
|
+
|
65
|
+
expect(Hyperctl.status(hctl)).to eq(text)
|
66
|
+
end
|
67
|
+
end # 12 physical cores with HT disabled
|
68
|
+
end #status
|
69
|
+
|
70
|
+
describe '#disable' do
|
71
|
+
context '8 physical cores with HT enabled' do
|
72
|
+
include_context "cpuinfo_8core_w_ht"
|
73
|
+
|
74
|
+
it 'should turn cores off' do
|
75
|
+
hctl.stubs(:cpu_info).returns(info)
|
76
|
+
8.upto(15).each do |core_id|
|
77
|
+
Hyperctl::Sysfs.expects(:disable_core).with(core_id).once
|
78
|
+
end
|
79
|
+
|
80
|
+
Hyperctl.disable(hctl)
|
81
|
+
end
|
82
|
+
end # 8 physical cores with HT enabled
|
83
|
+
|
84
|
+
context '12 physical cores with HT disabled' do
|
85
|
+
include_context "cpuinfo_12core_wo_ht"
|
86
|
+
|
87
|
+
it 'should do nothing' do
|
88
|
+
# all SMT cores are already disabled
|
89
|
+
hctl.stubs(:cpu_info).returns(info)
|
90
|
+
Hyperctl::Sysfs.expects(:disable_core).never
|
91
|
+
|
92
|
+
Hyperctl.disable(hctl)
|
93
|
+
end
|
94
|
+
end # 12 physical cores with HT disabled
|
95
|
+
end #disable
|
96
|
+
|
97
|
+
describe '#enable' do
|
98
|
+
context '8 physical cores with HT enabled' do
|
99
|
+
include_context "cpuinfo_8core_w_ht"
|
100
|
+
|
101
|
+
it 'should do nothing' do
|
102
|
+
# all SMT cores are already enabled
|
103
|
+
hctl.stubs(:cpu_info).returns(info)
|
104
|
+
Hyperctl::Sysfs.expects(:enable_core).never
|
105
|
+
|
106
|
+
Hyperctl.enable(hctl)
|
107
|
+
end
|
108
|
+
end # 8 physical cores with HT enabled
|
109
|
+
|
110
|
+
context '12 physical cores with HT disabled' do
|
111
|
+
include_context "cpuinfo_12core_wo_ht"
|
112
|
+
|
113
|
+
it 'should turn cores on' do
|
114
|
+
hctl.stubs(:cpu_info).returns(info)
|
115
|
+
12.upto(23).each do |core_id|
|
116
|
+
Hyperctl::Sysfs.expects(:enable_core).with(core_id).once
|
117
|
+
end
|
118
|
+
|
119
|
+
Hyperctl.enable(hctl)
|
120
|
+
end
|
121
|
+
end # 12 physical cores with HT disabled
|
122
|
+
end #enable
|
123
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
# pp must be required before fakefs
|
3
|
+
# see: https://github.com/defunkt/fakefs/issues/99
|
4
|
+
require 'pp'
|
5
|
+
require 'fakefs/spec_helpers'
|
6
|
+
|
7
|
+
describe Hyperctl::Sysfs do
|
8
|
+
let(:hctl) { Hyperctl::Sysfs.new }
|
9
|
+
include FakeFS::SpecHelpers
|
10
|
+
|
11
|
+
context 'on a 8 physical core w/ HT enabled system' do
|
12
|
+
include_context "sysfs_8core_w_ht"
|
13
|
+
include_context "cpuinfo_8core_w_ht"
|
14
|
+
|
15
|
+
context 'fakefs sanity checks' do
|
16
|
+
it { expect(File.exists?(sysfs('cpu1', 'online'))).to be true }
|
17
|
+
it { expect(File.exists?(sysfs('cpu1', 'topology/thread_siblings_list'))).to be true }
|
18
|
+
it { expect(sysfs('cpu1', 'topology/thread_siblings_list')).to contain(/1,9/) }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#new' do
|
22
|
+
it 'finds all the cores' do
|
23
|
+
expect(hctl.cpu_info).to eq(info)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#disable_core' do
|
28
|
+
it 'disbles core_id 15' do
|
29
|
+
Hyperctl::Sysfs.disable_core(15)
|
30
|
+
|
31
|
+
expect(sysfs('cpu15', 'online')).to contain(/^0$/)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context '#cores' do
|
36
|
+
it 'lists all cores' do
|
37
|
+
expect(hctl.cores).to eq((0 .. 15).to_a)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context '#online_cores' do
|
42
|
+
it 'lists all enabled cores' do
|
43
|
+
expect(hctl.online_cores).to eq((0 .. 15).to_a)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context '#offline_cores' do
|
48
|
+
it 'lists all disabled cores' do
|
49
|
+
expect(hctl.offline_cores).to eq []
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context '#sibling_cores' do
|
54
|
+
it 'lists all smt cores' do
|
55
|
+
expect(hctl.sibling_cores).to eq((8 .. 15).to_a)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context '#all_cores_enabled?' do
|
60
|
+
it 'returns true' do
|
61
|
+
expect(hctl.all_cores_enabled?).to be true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context '#all_siblings_disabled?' do
|
66
|
+
it 'returns false' do
|
67
|
+
expect(hctl.all_siblings_disabled?).to be false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context '#enable_core' do
|
72
|
+
it 'enables core_id 15' do
|
73
|
+
Hyperctl::Sysfs.enable_core(15)
|
74
|
+
|
75
|
+
expect(sysfs('cpu15', 'online')).to contain(/^1$/)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end # on a 8 physical core w/ HT enabled system
|
79
|
+
|
80
|
+
context 'on a 12 physical core w/ HT diabled system' do
|
81
|
+
include_context "sysfs_12core_wo_ht"
|
82
|
+
include_context "cpuinfo_12core_wo_ht"
|
83
|
+
|
84
|
+
context 'fakefs sanity checks' do
|
85
|
+
it { expect(File.exists?(sysfs('cpu0', 'online'))).to be false }
|
86
|
+
it { expect(File.exists?(sysfs('cpu0', 'topology/thread_siblings_list'))).to be true }
|
87
|
+
|
88
|
+
it { expect(File.exists?(sysfs('cpu1', 'online'))).to be true }
|
89
|
+
it { expect(File.exists?(sysfs('cpu1', 'topology/thread_siblings_list'))).to be true }
|
90
|
+
|
91
|
+
it { expect(File.exists?(sysfs('cpu23', 'online'))).to be true }
|
92
|
+
it { expect(File.exists?(sysfs('cpu23', 'topology/thread_siblings_list'))).to be false }
|
93
|
+
end
|
94
|
+
|
95
|
+
context '#new' do
|
96
|
+
it 'finds all the cores' do
|
97
|
+
hctl = Hyperctl::Sysfs.new
|
98
|
+
expect(hctl.cpu_info).to eq(info)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context '#disable_core' do
|
103
|
+
it 'disbles core_id 15' do
|
104
|
+
Hyperctl::Sysfs.disable_core(15)
|
105
|
+
|
106
|
+
expect(sysfs('cpu15', 'online')).to contain(/^0$/)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context '#cores' do
|
111
|
+
it 'lists all cores' do
|
112
|
+
expect(hctl.cores).to eq((0 .. 23).to_a)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context '#online_cores' do
|
117
|
+
it 'lists all enabled cores' do
|
118
|
+
expect(hctl.online_cores).to eq((0 .. 11).to_a)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context '#offline_cores' do
|
123
|
+
it 'lists all disabled cores' do
|
124
|
+
expect(hctl.offline_cores).to eq((12 .. 23).to_a)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context '#sibling_cores' do
|
129
|
+
it 'lists all smt cores' do
|
130
|
+
expect(hctl.sibling_cores).to eq []
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context '#all_cores_enabled?' do
|
135
|
+
it 'returns false' do
|
136
|
+
expect(hctl.all_cores_enabled?).to be false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context '#all_siblings_disabled?' do
|
141
|
+
it 'returns true' do
|
142
|
+
expect(hctl.all_siblings_disabled?).to be true
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context '#enable_core' do
|
147
|
+
it 'enables core_id 15' do
|
148
|
+
Hyperctl::Sysfs.enable_core(15)
|
149
|
+
|
150
|
+
expect(sysfs('cpu15', 'online')).to contain(/^1$/)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end # on a 12 physical core w/ HT disabled system
|
154
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'hyperctl'
|
2
|
+
|
3
|
+
RSpec.configure do |config|
|
4
|
+
config.mock_framework = :mocha
|
5
|
+
end
|
6
|
+
|
7
|
+
def sysfs(cpu_name, attr)
|
8
|
+
File.join('/sys/devices/system/cpu/', cpu_name, attr)
|
9
|
+
end
|
10
|
+
|
11
|
+
def mksysfs(cpu_name, attr, value)
|
12
|
+
path = sysfs(cpu_name, attr)
|
13
|
+
dir = File.dirname path
|
14
|
+
FileUtils.mkdir_p dir
|
15
|
+
File.open(path, 'w+') do |f|
|
16
|
+
f.write(value)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
RSpec::Matchers.define :contain do |content|
|
21
|
+
match do |path|
|
22
|
+
File.read(path) =~ content
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# 2.6.32-431.5.1.el6.x86_64
|
27
|
+
# 2 x Intel(R) Xeon(R) CPU E5-2643 0 @ 3.30GHz
|
28
|
+
RSpec.shared_context 'sysfs_8core_w_ht' do
|
29
|
+
before do
|
30
|
+
0.upto(15).each do |core_id|
|
31
|
+
next if core_id == 0
|
32
|
+
mksysfs("cpu#{core_id}", 'online', "1\n")
|
33
|
+
end
|
34
|
+
0.upto(7).each do |core_id|
|
35
|
+
mksysfs("cpu#{core_id}", 'topology/thread_siblings_list', "#{core_id},#{core_id + 8}\n")
|
36
|
+
end
|
37
|
+
8.upto(15).each do |core_id|
|
38
|
+
mksysfs("cpu#{core_id}", 'topology/thread_siblings_list', "#{core_id},#{core_id - 8}\n")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
RSpec.shared_context 'cpuinfo_8core_w_ht' do
|
44
|
+
info = {}
|
45
|
+
0.upto(7).each do |core_id|
|
46
|
+
name = "cpu#{core_id}"
|
47
|
+
info[name.to_sym] = {
|
48
|
+
:core_id => core_id,
|
49
|
+
:online => true,
|
50
|
+
:thread_siblings_list => [ core_id + 8 ],
|
51
|
+
:name => name,
|
52
|
+
}
|
53
|
+
end
|
54
|
+
8.upto(15).each do |core_id|
|
55
|
+
name = "cpu#{core_id}"
|
56
|
+
info[name.to_sym] = {
|
57
|
+
:core_id => core_id,
|
58
|
+
:online => true,
|
59
|
+
:thread_siblings_list => [ core_id - 8 ],
|
60
|
+
:name => name,
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
let(:info) { info }
|
65
|
+
end
|
66
|
+
|
67
|
+
# 2.6.32-431.5.1.el6.x86_64
|
68
|
+
# 2 x Intel(R) Xeon(R) CPU X5675 @ 3.07GHz
|
69
|
+
RSpec.shared_context 'sysfs_12core_wo_ht' do
|
70
|
+
before do
|
71
|
+
0.upto(11).each do |core_id|
|
72
|
+
mksysfs("cpu#{core_id}", 'topology/thread_siblings_list', "#{core_id}\n")
|
73
|
+
next if core_id == 0
|
74
|
+
mksysfs("cpu#{core_id}", 'online', "1\n")
|
75
|
+
end
|
76
|
+
12.upto(23).each do |core_id|
|
77
|
+
mksysfs("cpu#{core_id}", 'online', "0\n")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
RSpec.shared_context 'cpuinfo_12core_wo_ht' do
|
83
|
+
info = {}
|
84
|
+
0.upto(11).each do |core_id|
|
85
|
+
name = "cpu#{core_id}"
|
86
|
+
info[name.to_sym] = {
|
87
|
+
:core_id => core_id,
|
88
|
+
:online => true,
|
89
|
+
:name => name,
|
90
|
+
}
|
91
|
+
end
|
92
|
+
12.upto(23).each do |core_id|
|
93
|
+
name = "cpu#{core_id}"
|
94
|
+
info[name.to_sym] = {
|
95
|
+
:core_id => core_id,
|
96
|
+
:online => false,
|
97
|
+
:name => name,
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
let(:info) { info }
|
102
|
+
end
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hyperctl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joshua Hoblitt
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: docopt
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.5.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.5.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-expectations
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-mocks
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: fakefs
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.5.2
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.5.2
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mocha
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: yard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.8'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.8'
|
125
|
+
description: |-
|
126
|
+
This Gem provides a simple cli utility named `hyperctl`
|
127
|
+
that can check the status of and [with appropriate permissions] enable/disable
|
128
|
+
hyperthreading/SMT/sibling cores on Linux via the `sysfs` pseudo filesystem.
|
129
|
+
It should be compatible with most modern Linux distributions as long as `sysfs` is mounted at `/sysfs`.
|
130
|
+
email:
|
131
|
+
- jhoblitt@cpan.org
|
132
|
+
executables:
|
133
|
+
- hyperctl
|
134
|
+
extensions: []
|
135
|
+
extra_rdoc_files: []
|
136
|
+
files:
|
137
|
+
- ".gitignore"
|
138
|
+
- ".travis.yml"
|
139
|
+
- Gemfile
|
140
|
+
- README.md
|
141
|
+
- Rakefile
|
142
|
+
- bin/hyperctl
|
143
|
+
- hyperctl.gemspec
|
144
|
+
- lib/hyperctl.rb
|
145
|
+
- lib/hyperctl/sysfs.rb
|
146
|
+
- lib/hyperctl/version.rb
|
147
|
+
- spec/hyperctl_spec.rb
|
148
|
+
- spec/hyperctl_sysfs_spec.rb
|
149
|
+
- spec/spec_helper.rb
|
150
|
+
homepage: https://github.com/jhoblitt/hyperctl
|
151
|
+
licenses:
|
152
|
+
- Apache 2.0
|
153
|
+
metadata: {}
|
154
|
+
post_install_message:
|
155
|
+
rdoc_options: []
|
156
|
+
require_paths:
|
157
|
+
- lib
|
158
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: 1.8.7
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
requirements: []
|
169
|
+
rubyforge_project:
|
170
|
+
rubygems_version: 2.4.4
|
171
|
+
signing_key:
|
172
|
+
specification_version: 4
|
173
|
+
summary: A utility for enabling/disabling hyperthreading
|
174
|
+
test_files:
|
175
|
+
- spec/hyperctl_spec.rb
|
176
|
+
- spec/hyperctl_sysfs_spec.rb
|
177
|
+
- spec/spec_helper.rb
|
178
|
+
has_rdoc:
|