cpuinfo 1.0.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.
@@ -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