cpuinfo 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cd3fd6b47290969e1e19c3496854d3c342a0e56fa8e1fcbea7507c5a85ea8d35
4
+ data.tar.gz: 9571570022400c4c331d586258a586a1641d204ca843a223d496a542f675d07a
5
+ SHA512:
6
+ metadata.gz: c0e005b310cb5bd98a833a889f7d9d5fe8858eae76635498b5be429062b2c6a9f83da019e3326982ad2991d3d3128565729794a288f6506ba23695eefe258b85
7
+ data.tar.gz: 3008f847eae9563e727ef684240a44466f6b445e844790c0b4952853857751fb2a1785c5adfcb69774c735048bd05ae0d6a35672037bb965d2783401291eeb1f
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Matthias Winkelmann
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,12 @@
1
+ # CPUInfo
2
+
3
+ RubyGem for parsing /proc/cpuinfo
4
+
5
+ ## Examples
6
+
7
+ ```
8
+ require 'cpuinfo`
9
+ CPUInfo::CPUS.first.attributes.each do |name, value|
10
+ puts "%s : %s" % [name, value]
11
+ end
12
+ ```
@@ -0,0 +1,11 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'test'
8
+ t.test_files = FileList['test/test.rb']
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'cpuinfo'
5
+ spec.version = '1.0.0'
6
+ spec.author = 'Matthias Winkelmann'
7
+ spec.email = 'm@matthi.coffee'
8
+ spec.license = 'MIT'
9
+ spec.homepage = 'https://github.com/MatthiasWinkelmann/cpuinfo'
10
+ spec.summary = 'A Ruby interface to system CPU info'
11
+ # spec.test_file = 'test/test.rb'
12
+ spec.files = Dir['**/*'].reject{ |f| f.include?('git') }
13
+
14
+ # spec.extra_rdoc_files = ['README.md']
15
+
16
+ spec.add_development_dependency('minitest', '~>5.11')
17
+ spec.add_development_dependency('rake', '~>12.3')
18
+
19
+ spec.description = <<-EOF
20
+ Very basic parsing of /proc/cpuinfo for now.
21
+ EOF
22
+ end
@@ -0,0 +1,75 @@
1
+ module CPUInfo
2
+
3
+ class CPUS
4
+
5
+ def self.cpus
6
+ @@cpus ||= self.parse_cpuinfo
7
+ end
8
+
9
+ def self.[](*parameters)
10
+ (self.cpus).public_send(:[], *parameters)
11
+ end
12
+
13
+ def to_s
14
+ self.cpus.map(&:to_s).join("\n\n")
15
+ end
16
+
17
+ def self.method_missing(sym, *parameters)
18
+ self.cpus.public_send(sym, *parameters) if self.cpus.respond_to? sym
19
+ end
20
+
21
+ class CPU
22
+ attr_reader :attributes
23
+ def initialize(cpuinfo)
24
+ @attributes = {}
25
+ cpuinfo.lines.each do |line|
26
+ matches = /^([^:]+):(.+)\n/.match(line)
27
+ next unless matches
28
+ attribute = matches[1].strip.gsub(/[^a-zA-Z_]/,'_')
29
+ value = matches[2].strip
30
+ if value =~ /^[0-9]+(\.0*)?$/
31
+ value = value.to_i
32
+ elsif value =~ /^[0-9\.]$/
33
+ value = value.to_f
34
+ elsif ['no', 'false'].include? value.downcase
35
+ value = false
36
+ elsif ['yes', 'true'].include? value.downcase
37
+ value = true
38
+ elsif attribute == 'flags'
39
+ value = CPUFlags.new value
40
+ end
41
+ @attributes[attribute.to_sym] = value
42
+ end
43
+ end
44
+
45
+ def method_missing(sym, *parameters)
46
+ return @attributes[sym.to_sym] if parameters.empty? && @attributes.key?(sym.to_sym)
47
+ @attributes[:flags].public_send(sym, *parameters)
48
+ end
49
+
50
+ class CPUFlags
51
+
52
+ attr_reader :flags
53
+
54
+ def initialize(flagstring)
55
+ @flags = flagstring.split(' ')
56
+ end
57
+
58
+ def method_missing(method, *params)
59
+ if method[-1] == '?'
60
+ return @flags.include? method[0..-2]
61
+ end
62
+ end
63
+ end
64
+
65
+ end
66
+
67
+ def self.read_cpuinfo
68
+ # IO.read("/proc/cpuinfo")
69
+ end
70
+
71
+ def self.parse_cpuinfo
72
+ self.read_cpuinfo.split(/^processor:\w+\d+:\w+\n/).map {|cpu| CPU.new(cpu) }
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,216 @@
1
+ processor : 0
2
+ vendor_id : GenuineIntel
3
+ cpu family : 6
4
+ model : 85
5
+ model name : Intel Xeon Processor (Skylake)
6
+ stepping : 4
7
+ microcode : 0x1
8
+ cpu MHz : 2100.000
9
+ cache size : 16384 KB
10
+ physical id : 0
11
+ siblings : 8
12
+ core id : 0
13
+ cpu cores : 8
14
+ apicid : 0
15
+ initial apicid : 0
16
+ fpu : yes
17
+ fpu_exception : yes
18
+ cpuid level : 13
19
+ wp : yes
20
+ flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
21
+ bugs : cpu_meltdown spectre_v1 spectre_v2
22
+ bogomips : 4200.00
23
+ clflush size : 64
24
+ cache_alignment : 64
25
+ address sizes : 40 bits physical, 48 bits virtual
26
+ power management:
27
+
28
+ processor : 1
29
+ vendor_id : GenuineIntel
30
+ cpu family : 6
31
+ model : 85
32
+ model name : Intel Xeon Processor (Skylake)
33
+ stepping : 4
34
+ microcode : 0x1
35
+ cpu MHz : 2100.000
36
+ cache size : 16384 KB
37
+ physical id : 0
38
+ siblings : 8
39
+ core id : 1
40
+ cpu cores : 8
41
+ apicid : 1
42
+ initial apicid : 1
43
+ fpu : yes
44
+ fpu_exception : yes
45
+ cpuid level : 13
46
+ wp : yes
47
+ flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
48
+ bugs : cpu_meltdown spectre_v1 spectre_v2
49
+ bogomips : 4200.00
50
+ clflush size : 64
51
+ cache_alignment : 64
52
+ address sizes : 40 bits physical, 48 bits virtual
53
+ power management:
54
+
55
+ processor : 2
56
+ vendor_id : GenuineIntel
57
+ cpu family : 6
58
+ model : 85
59
+ model name : Intel Xeon Processor (Skylake)
60
+ stepping : 4
61
+ microcode : 0x1
62
+ cpu MHz : 2100.000
63
+ cache size : 16384 KB
64
+ physical id : 0
65
+ siblings : 8
66
+ core id : 2
67
+ cpu cores : 8
68
+ apicid : 2
69
+ initial apicid : 2
70
+ fpu : yes
71
+ fpu_exception : yes
72
+ cpuid level : 13
73
+ wp : yes
74
+ flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
75
+ bugs : cpu_meltdown spectre_v1 spectre_v2
76
+ bogomips : 4200.00
77
+ clflush size : 64
78
+ cache_alignment : 64
79
+ address sizes : 40 bits physical, 48 bits virtual
80
+ power management:
81
+
82
+ processor : 3
83
+ vendor_id : GenuineIntel
84
+ cpu family : 6
85
+ model : 85
86
+ model name : Intel Xeon Processor (Skylake)
87
+ stepping : 4
88
+ microcode : 0x1
89
+ cpu MHz : 2100.000
90
+ cache size : 16384 KB
91
+ physical id : 0
92
+ siblings : 8
93
+ core id : 3
94
+ cpu cores : 8
95
+ apicid : 3
96
+ initial apicid : 3
97
+ fpu : yes
98
+ fpu_exception : yes
99
+ cpuid level : 13
100
+ wp : yes
101
+ flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
102
+ bugs : cpu_meltdown spectre_v1 spectre_v2
103
+ bogomips : 4200.00
104
+ clflush size : 64
105
+ cache_alignment : 64
106
+ address sizes : 40 bits physical, 48 bits virtual
107
+ power management:
108
+
109
+ processor : 4
110
+ vendor_id : GenuineIntel
111
+ cpu family : 6
112
+ model : 85
113
+ model name : Intel Xeon Processor (Skylake)
114
+ stepping : 4
115
+ microcode : 0x1
116
+ cpu MHz : 2100.000
117
+ cache size : 16384 KB
118
+ physical id : 0
119
+ siblings : 8
120
+ core id : 4
121
+ cpu cores : 8
122
+ apicid : 4
123
+ initial apicid : 4
124
+ fpu : yes
125
+ fpu_exception : yes
126
+ cpuid level : 13
127
+ wp : yes
128
+ flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
129
+ bugs : cpu_meltdown spectre_v1 spectre_v2
130
+ bogomips : 4200.00
131
+ clflush size : 64
132
+ cache_alignment : 64
133
+ address sizes : 40 bits physical, 48 bits virtual
134
+ power management:
135
+
136
+ processor : 5
137
+ vendor_id : GenuineIntel
138
+ cpu family : 6
139
+ model : 85
140
+ model name : Intel Xeon Processor (Skylake)
141
+ stepping : 4
142
+ microcode : 0x1
143
+ cpu MHz : 2100.000
144
+ cache size : 16384 KB
145
+ physical id : 0
146
+ siblings : 8
147
+ core id : 5
148
+ cpu cores : 8
149
+ apicid : 5
150
+ initial apicid : 5
151
+ fpu : yes
152
+ fpu_exception : yes
153
+ cpuid level : 13
154
+ wp : yes
155
+ flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
156
+ bugs : cpu_meltdown spectre_v1 spectre_v2
157
+ bogomips : 4200.00
158
+ clflush size : 64
159
+ cache_alignment : 64
160
+ address sizes : 40 bits physical, 48 bits virtual
161
+ power management:
162
+
163
+ processor : 6
164
+ vendor_id : GenuineIntel
165
+ cpu family : 6
166
+ model : 85
167
+ model name : Intel Xeon Processor (Skylake)
168
+ stepping : 4
169
+ microcode : 0x1
170
+ cpu MHz : 2100.000
171
+ cache size : 16384 KB
172
+ physical id : 0
173
+ siblings : 8
174
+ core id : 6
175
+ cpu cores : 8
176
+ apicid : 6
177
+ initial apicid : 6
178
+ fpu : yes
179
+ fpu_exception : yes
180
+ cpuid level : 13
181
+ wp : yes
182
+ flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
183
+ bugs : cpu_meltdown spectre_v1 spectre_v2
184
+ bogomips : 4200.00
185
+ clflush size : 64
186
+ cache_alignment : 64
187
+ address sizes : 40 bits physical, 48 bits virtual
188
+ power management:
189
+
190
+ processor : 7
191
+ vendor_id : GenuineIntel
192
+ cpu family : 6
193
+ model : 85
194
+ model name : Intel Xeon Processor (Skylake)
195
+ stepping : 4
196
+ microcode : 0x1
197
+ cpu MHz : 2100.000
198
+ cache size : 16384 KB
199
+ physical id : 0
200
+ siblings : 8
201
+ core id : 7
202
+ cpu cores : 8
203
+ apicid : 7
204
+ initial apicid : 7
205
+ fpu : yes
206
+ fpu_exception : yes
207
+ cpuid level : 13
208
+ wp : yes
209
+ flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f rdseed adx smap clwb avx512cd xsaveopt xsavec xgetbv1 arat
210
+ bugs : cpu_meltdown spectre_v1 spectre_v2
211
+ bogomips : 4200.00
212
+ clflush size : 64
213
+ cache_alignment : 64
214
+ address sizes : 40 bits physical, 48 bits virtual
215
+ power management:
216
+
@@ -0,0 +1,30 @@
1
+ require "minitest/autorun"
2
+ require 'cpuinfo'
3
+
4
+ class TestCPUInfo < Minitest::Test
5
+
6
+ class CPUInfo::CPUS
7
+ def self.read_cpuinfo
8
+ File.read "test/fixtures/cpuinfo"
9
+ end
10
+ end
11
+
12
+ def test_readme
13
+ CPUInfo::CPUS.first.attributes.each do |name, value|
14
+ puts "%s : %s" % [name, value]
15
+ end
16
+ end
17
+
18
+ def test_number_of_cpus
19
+ assert_equal 1, CPUInfo::CPUS.size
20
+ end
21
+
22
+ def test_number_of_attributes
23
+ assert_equal 25, CPUInfo::CPUS[0].attributes.keys.size
24
+ end
25
+
26
+ def test_formats
27
+ puts CPUInfo::CPUS[0]
28
+ assert_kind_of Integer, CPUInfo::CPUS[0].core_id
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ # This is just a stub file that requires the appropriate version
2
+ # depending on which platform you're on.
3
+ require 'rbconfig'
4
+
5
+ module Sys
6
+ class CPU
7
+ # The version of the sys-cpu gem.
8
+ VERSION = '0.7.2'
9
+ end
10
+ end
11
+
12
+ case RbConfig::CONFIG['host_os']
13
+ when /linux/i
14
+ require File.join(File.dirname(__FILE__), 'linux', 'sys', 'cpu')
15
+ when /windows|mswin|mingw|cygwin|dos/i
16
+ require File.join(File.dirname(__FILE__), 'windows', 'sys', 'cpu')
17
+ else
18
+ require File.join(File.dirname(__FILE__), 'unix', 'sys', 'cpu')
19
+ end
@@ -0,0 +1,372 @@
1
+ require 'ffi'
2
+ require 'rbconfig'
3
+
4
+ module Sys
5
+ class CPU
6
+ extend FFI::Library
7
+ ffi_lib FFI::Library::LIBC
8
+
9
+ # Error raised if any of the CPU methods fail.
10
+ class Error < StandardError; end
11
+
12
+ CTL_HW = 6 # Generic hardware/cpu
13
+
14
+ HW_MACHINE = 1 # Machine class
15
+ HW_MODEL = 2 # Specific machine model
16
+ HW_NCPU = 3 # Number of CPU's
17
+ HW_CPU_FREQ = 15 # CPU frequency
18
+
19
+ if RbConfig::CONFIG['host_os'] =~ /bsd/
20
+ HW_MACHINE_ARCH = 11 # Machine architecture
21
+ else
22
+ HW_MACHINE_ARCH = 12 # Machine architecture
23
+ end
24
+
25
+ SI_MACHINE = 5
26
+ SI_ARCHITECTURE = 6
27
+ SC_NPROCESSORS_ONLN = 15
28
+
29
+ P_OFFLINE = 1
30
+ P_ONLINE = 2
31
+ P_FAULTED = 4
32
+ P_POWEROFF = 5
33
+ P_NOINTR = 6
34
+ P_SPARE = 7
35
+
36
+ CPU_ARCH_ABI64 = 0x01000000
37
+ CPU_TYPE_X86 = 7
38
+ CPU_TYPE_X86_64 = (CPU_TYPE_X86 | CPU_ARCH_ABI64)
39
+ CPU_TYPE_SPARC = 14
40
+ CPU_TYPE_POWERPC = 18
41
+ CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64
42
+
43
+ begin
44
+ attach_function(
45
+ :sysctl,
46
+ [:pointer, :uint, :pointer, :pointer, :pointer, :size_t],
47
+ :int
48
+ )
49
+ private_class_method :sysctl
50
+ rescue FFI::NotFoundError
51
+ # Do nothing, not supported on this platform.
52
+ end
53
+
54
+ begin
55
+ attach_function(
56
+ :sysctlbyname,
57
+ [:string, :pointer, :pointer, :pointer, :size_t],
58
+ :int
59
+ )
60
+ private_class_method :sysctlbyname
61
+ rescue FFI::NotFoundError
62
+ # Do nothing, not supported on this platform.
63
+ end
64
+
65
+ # Solaris
66
+ begin
67
+ attach_function :getloadavg, [:pointer, :int], :int
68
+ attach_function :processor_info, [:int, :pointer], :int
69
+ attach_function :sysconf, [:int], :long
70
+ attach_function :sysinfo, [:int, :pointer, :long], :int
71
+
72
+ private_class_method :getloadavg
73
+ private_class_method :processor_info
74
+ private_class_method :sysconf
75
+ private_class_method :sysinfo
76
+ rescue FFI::NotFoundError
77
+ # Do nothing, not supported on this platform.
78
+ end
79
+
80
+ class ProcInfo < FFI::Struct
81
+ layout(
82
+ :pi_state, :int,
83
+ :pi_processor_type, [:char, 16],
84
+ :pi_fputypes, [:char, 32],
85
+ :pi_clock, :int
86
+ )
87
+ end
88
+
89
+ # Returns the cpu's architecture. On most systems this will be identical
90
+ # to the CPU.machine method. On OpenBSD it will be identical to the CPU.model
91
+ # method.
92
+ #
93
+ def self.architecture
94
+ if respond_to?(:sysinfo, true)
95
+ buf = 0.chr * 257
96
+
97
+ if sysinfo(SI_ARCHITECTURE, buf, buf.size) < 0
98
+ raise Error, "sysinfo function failed"
99
+ end
100
+
101
+ buf.strip
102
+ elsif respond_to?(:sysctlbyname, true)
103
+ optr = FFI::MemoryPointer.new(:char, 256)
104
+ size = FFI::MemoryPointer.new(:size_t)
105
+
106
+ size.write_int(optr.size)
107
+
108
+ if RbConfig::CONFIG['host_os'] =~ /darwin/i
109
+ name = 'hw.machine'
110
+ else
111
+ name = 'hw.machine_arch'
112
+ end
113
+
114
+ if sysctlbyname(name, optr, size, nil, 0) < 0
115
+ raise Error, "sysctlbyname function failed"
116
+ end
117
+
118
+ optr.read_string
119
+ else
120
+ buf = 0.chr * 64
121
+ mib = FFI::MemoryPointer.new(:int, 2)
122
+ size = FFI::MemoryPointer.new(:long, 1)
123
+
124
+ mib.write_array_of_int([CTL_HW, HW_MACHINE_ARCH])
125
+ size.write_int(buf.size)
126
+
127
+ if sysctl(mib, 2, buf, size, nil, 0) < 0
128
+ raise Error, "sysctl function failed"
129
+ end
130
+
131
+ buf.strip
132
+ end
133
+ end
134
+
135
+ # Returns the number of cpu's on your system. Note that each core on
136
+ # multi-core systems are counted as a cpu, e.g. one dual core cpu would
137
+ # return 2, not 1.
138
+ #
139
+ def self.num_cpu
140
+ if respond_to?(:sysctlbyname, true)
141
+ optr = FFI::MemoryPointer.new(:long)
142
+ size = FFI::MemoryPointer.new(:size_t)
143
+
144
+ size.write_long(optr.size)
145
+
146
+ if sysctlbyname('hw.ncpu', optr, size, nil, 0) < 0
147
+ raise Error, "sysctlbyname failed"
148
+ end
149
+
150
+ optr.read_long
151
+ elsif respond_to?(:sysconf, true)
152
+ num = sysconf(SC_NPROCESSORS_ONLN)
153
+
154
+ if num < 0
155
+ raise Error, "sysconf function failed"
156
+ end
157
+
158
+ num
159
+ else
160
+ buf = 0.chr * 4
161
+ mib = FFI::MemoryPointer.new(:int, 2)
162
+ size = FFI::MemoryPointer.new(:long, 1)
163
+
164
+ mib.write_array_of_int([CTL_HW, HW_NCPU])
165
+ size.write_int(buf.size)
166
+
167
+ if sysctl(mib, 2, buf, size, nil, 0) < 0
168
+ raise Error, "sysctl function failed"
169
+ end
170
+
171
+ buf.strip.unpack("C").first
172
+ end
173
+ end
174
+
175
+ # Returns the cpu's class type. On most systems this will be identical
176
+ # to the CPU.architecture method. On OpenBSD it will be identical to the
177
+ # CPU.model method.
178
+ #
179
+ def self.machine
180
+ if respond_to?(:sysctl, true)
181
+ buf = 0.chr * 32
182
+ mib = FFI::MemoryPointer.new(:int, 2)
183
+ size = FFI::MemoryPointer.new(:long, 1)
184
+
185
+ mib.write_array_of_int([CTL_HW, HW_MACHINE])
186
+ size.write_int(buf.size)
187
+
188
+ if sysctl(mib, 2, buf, size, nil, 0) < 0
189
+ raise Error, "sysctl function failed"
190
+ end
191
+
192
+ buf.strip
193
+ else
194
+ buf = 0.chr * 257
195
+
196
+ if sysinfo(SI_MACHINE, buf, buf.size) < 0
197
+ raise Error, "sysinfo function failed"
198
+ end
199
+
200
+ buf.strip
201
+ end
202
+ end
203
+
204
+ # Returns a string indicating the cpu model.
205
+ #
206
+ def self.model
207
+ if RbConfig::CONFIG['host_os'] =~ /darwin/i
208
+ ptr = FFI::MemoryPointer.new(:long)
209
+ size = FFI::MemoryPointer.new(:size_t)
210
+
211
+ size.write_long(ptr.size)
212
+
213
+ if sysctlbyname("hw.cputype", ptr, size, nil, 0) < 0
214
+ raise "sysctlbyname function failed"
215
+ end
216
+
217
+ case ptr.read_long
218
+ when CPU_TYPE_X86, CPU_TYPE_X86_64
219
+ "Intel"
220
+ when CPU_TYPE_SPARC
221
+ "Sparc"
222
+ when CPU_TYPE_POWERPC, CPU_TYPE_POWERPC64
223
+ "PowerPC"
224
+ else
225
+ "Unknown"
226
+ end
227
+ else
228
+ if respond_to?(:sysctl, true)
229
+ buf = 0.chr * 64
230
+ mib = FFI::MemoryPointer.new(:int, 2)
231
+ size = FFI::MemoryPointer.new(:long, 1)
232
+
233
+ mib.write_array_of_int([CTL_HW, HW_MODEL])
234
+ size.write_int(buf.size)
235
+
236
+ if sysctl(mib, 2, buf, size, nil, 0) < 0
237
+ raise Error, "sysctl function failed"
238
+ end
239
+
240
+ buf.strip
241
+ else
242
+ pinfo = ProcInfo.new
243
+
244
+ # Some systems start at 0, some at 1
245
+ if processor_info(0, pinfo) < 0
246
+ if processor_info(1, pinfo) < 0
247
+ raise Error, "process_info function failed"
248
+ end
249
+ end
250
+
251
+ pinfo[:pi_processor_type].to_s
252
+ end
253
+ end
254
+ end
255
+
256
+ # Returns an integer indicating the speed of the CPU.
257
+ #
258
+ def self.freq
259
+ if respond_to?(:sysctlbyname, true)
260
+ optr = FFI::MemoryPointer.new(:long)
261
+ size = FFI::MemoryPointer.new(:size_t)
262
+
263
+ size.write_long(optr.size)
264
+
265
+ if RbConfig::CONFIG['host_os'] =~ /bsd/i
266
+ name = 'hw.clockrate'
267
+ else
268
+ name = 'hw.cpufrequency'
269
+ end
270
+
271
+ if sysctlbyname(name, optr, size, nil, 0) < 0
272
+ raise Error, "sysctlbyname failed"
273
+ end
274
+
275
+ if RbConfig::CONFIG['host_os'] =~ /darwin/i
276
+ optr.read_long / 1000000
277
+ else
278
+ optr.read_long
279
+ end
280
+ elsif respond_to?(:sysctl, true)
281
+ buf = 0.chr * 16
282
+ mib = FFI::MemoryPointer.new(:int, 2)
283
+ size = FFI::MemoryPointer.new(:long, 1)
284
+
285
+ mib.write_array_of_int([CTL_HW, HW_CPU_FREQ])
286
+ size.write_int(buf.size)
287
+
288
+ if sysctl(mib, 2, buf, size, nil, 0) < 0
289
+ raise Error, "sysctl function failed"
290
+ end
291
+
292
+ buf.unpack("I*").first / 1000000
293
+ else
294
+ pinfo = ProcInfo.new
295
+
296
+ # Some systems start at 0, some at 1
297
+ if processor_info(0, pinfo) < 0
298
+ if processor_info(1, pinfo) < 0
299
+ raise Error, "process_info function failed"
300
+ end
301
+ end
302
+
303
+ pinfo[:pi_clock].to_i
304
+ end
305
+ end
306
+
307
+ # Returns an array of three floats indicating the 1, 5 and 15 minute load
308
+ # average.
309
+ #
310
+ def self.load_avg
311
+ if respond_to?(:getloadavg, true)
312
+ loadavg = FFI::MemoryPointer.new(:double, 3)
313
+
314
+ if getloadavg(loadavg, loadavg.size) < 0
315
+ raise Error, "getloadavg function failed"
316
+ end
317
+
318
+ loadavg.get_array_of_double(0, 3)
319
+ end
320
+ end
321
+
322
+ # Returns the floating point processor type.
323
+ #
324
+ # Not supported on all platforms.
325
+ #
326
+ def self.fpu_type
327
+ raise NoMethodError unless respond_to?(:processor_info, true)
328
+
329
+ pinfo = ProcInfo.new
330
+
331
+ if processor_info(0, pinfo) < 0
332
+ if processor_info(1, pinfo) < 0
333
+ raise Error, "process_info function failed"
334
+ end
335
+ end
336
+
337
+ pinfo[:pi_fputypes].to_s
338
+ end
339
+
340
+ # Returns the current state of processor +num+, or 0 if no number is
341
+ # specified.
342
+ #
343
+ # Not supported on all platforms.
344
+ #
345
+ def self.state(num = 0)
346
+ raise NoMethodError unless respond_to?(:processor_info, true)
347
+
348
+ pinfo = ProcInfo.new
349
+
350
+ if processor_info(num, pinfo) < 0
351
+ raise Error, "process_info function failed"
352
+ end
353
+
354
+ case pinfo[:pi_state].to_i
355
+ when P_ONLINE
356
+ "online"
357
+ when P_OFFLINE
358
+ "offline"
359
+ when P_POWEROFF
360
+ "poweroff"
361
+ when P_FAULTED
362
+ "faulted"
363
+ when P_NOINTR
364
+ "nointr"
365
+ when P_SPARE
366
+ "spare"
367
+ else
368
+ "unknown"
369
+ end
370
+ end
371
+ end
372
+ end