sys-cpu 0.6.4 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,12 @@
1
+ == 0.7.0 - 14-Dec-2011
2
+ * Code base now uses FFI. However, HP-UX is not currently supported.
3
+ HP-UX users should continue to use the 0.6.x version. Note that
4
+ the code base remains unchanged on Linux and Windows.
5
+ * The cpu_type method has been replaced with the architecture method
6
+ on Solaris to keep the interface more in line with other platforms.
7
+ * The type method has been changed to cpu_type on Windows.
8
+ * Some Rakefile and test suite updates.
9
+
1
10
  == 0.6.4 - 27-Sep-2011
2
11
  * The CPU.freq method now works on OSX.
3
12
  * The CPU.model method on OSX has been altered. Previously it
data/README CHANGED
@@ -36,6 +36,10 @@
36
36
  Unlike other platforms, you can get load averages for an individual cpu in
37
37
  multi-cpu systems. See documentation for more details.
38
38
 
39
+ Note that version 0.7.x and later will not work on HP-UX because of the
40
+ switch to FFI and the lack of a testing platform. However, version 0.6.x
41
+ will work just fine.
42
+
39
43
  == MS Windows
40
44
  This is a pure Ruby implementation using the win32ole package + WMI. The C
41
45
  version has been scrapped.
@@ -48,11 +52,11 @@
48
52
 
49
53
  = Acknowledgements
50
54
  Thanks go to the MPlayer team for some source code that helped me on
51
- certain versions of FreeBSD.
55
+ certain versions of FreeBSD in the original C version.
52
56
 
53
57
  = Known Bugs
54
58
  None that I'm aware of. Please report bugs on the project page at
55
- http://www.rubyforge.org/projects/sysutils.
59
+ https://github.com/djberg96/sys-cpu
56
60
 
57
61
  = Future Plans
58
62
  Add iterative CPU.processors method.
data/Rakefile CHANGED
@@ -4,29 +4,7 @@ require 'rake/testtask'
4
4
  require 'rbconfig'
5
5
  include Config
6
6
 
7
- CLEAN.include(
8
- '**/*.gem', # Gem files
9
- '**/*.rbc', # Rubinius
10
- 'ext/cpu.c', # Temporary file
11
- '**/*.o', # C object file
12
- '**/*.log', # Ruby extension build log
13
- '**/Makefile', # C Makefile
14
- '**/conftest.dSYM', # OS X build directory
15
- "**/*.#{CONFIG['DLEXT']}" # C shared object
16
- )
17
-
18
- desc "Build the sys-cpu library on UNIX systems"
19
- task :build => [:clean] do
20
- Dir.chdir('ext') do
21
- unless CONFIG['host_os'] =~ /mswin|win32|mingw|cygwin|dos|windows|linux/i
22
- ruby 'extconf.rb'
23
- sh 'make'
24
- build_file = 'cpu.' + CONFIG['DLEXT']
25
- Dir.mkdir('sys') unless File.exists?('sys')
26
- FileUtils.cp(build_file, 'sys')
27
- end
28
- end
29
- end
7
+ CLEAN.include('**/*.gem', '**/*.rbc', '**/*.rbx')
30
8
 
31
9
  namespace 'gem' do
32
10
  desc "Create the sys-cpu gem"
@@ -43,32 +21,25 @@ namespace 'gem' do
43
21
  end
44
22
 
45
23
  desc "Run the example program"
46
- task :example => [:build] do
47
- Dir.mkdir('sys') unless File.exists?('sys')
48
- if CONFIG['host_os'] =~ /mswin|win32|mingw|cygwin|dos|windows|linux/i
49
- if CONFIG['host_os'].match('linux')
50
- cp 'lib/linux/sys/cpu.rb', 'sys'
51
- else
52
- cp 'lib/windows/sys/cpu.rb', 'sys'
53
- end
54
- else
55
- build_file = 'ext/cpu.' + CONFIG['DLEXT']
56
- cp build_file, 'sys'
57
- end
58
-
24
+ task :example => [:clean] do
59
25
  case CONFIG['host_os']
60
- when /bsd|darwin|mach|osx/i
61
- file = 'examples/example_sys_cpu_bsd.rb'
62
- when /hpux/i
63
- file = 'examples/example_sys_cpu_hpux.rb'
64
- when /linux/i
65
- file = 'examples/example_sys_cpu_linux.rb'
66
- when /sunos|solaris/i
67
- file = 'examples/example_sys_cpu_sunos.rb'
68
- when /mswin|win32|cygwin|mingw|dos/i
69
- file = 'examples/example_sys_cpu_windows.rb'
26
+ when /bsd|darwin|osx/i
27
+ file = "examples/example_sys_cpu_bsd.rb"
28
+ sh "ruby -Ilib/unix #{file}"
29
+ when /hpux/i
30
+ file = "examples/example_sys_cpu_hpux.rb"
31
+ sh "ruby -Ilib/unix #{file}"
32
+ when /linux/i
33
+ file = "examples/example_sys_cpu_linux.rb"
34
+ sh "ruby -Ilib/linux #{file}"
35
+ when /windows|win32|cygwin|mingw|dos/i
36
+ file = "examples/example_sys_cpu_windows.rb"
37
+ sh "ruby -Ilib/windows #{file}"
38
+ when /sunos|solaris/i
39
+ file = "examples/example_sys_cpu_sunos.rb"
40
+ sh "ruby -Ilib/unix #{file}"
70
41
  end
71
- sh "ruby -I. -Iext -Ilib #{file}"
42
+
72
43
  end
73
44
 
74
45
  Rake::TestTask.new do |t|
@@ -77,9 +48,7 @@ Rake::TestTask.new do |t|
77
48
  elsif CONFIG['host_os'] =~ /linux/i
78
49
  t.libs << 'lib/linux'
79
50
  else
80
- task :test => :build
81
- t.libs << 'ext'
82
- t.libs.delete('lib')
51
+ t.libs << 'lib/unix'
83
52
  end
84
53
 
85
54
  t.libs << 'test'
@@ -9,7 +9,7 @@
9
9
  puts "Mhz: " + CPU.cpu_freq(0).to_s
10
10
  puts "State: " + CPU.state(0)
11
11
  puts "Number of cpu's on this system: " + CPU.num_cpu.to_s
12
- puts "CPU type: " + CPU.type
12
+ puts "CPU type: " + CPU.architecture
13
13
  puts "FPU type: " + CPU.fpu_type
14
14
  puts "CPU model: " + CPU.model
15
15
  puts "Load averages: " + CPU.load_avg.join(", ")
@@ -23,7 +23,7 @@ CPU.freq(cpu_num=0)
23
23
  Returns an integer indicating the speed (i.e. frequency in Mhz) of
24
24
  'cpu_num', or CPU 0 if no number is provided.
25
25
 
26
- CPU.type
26
+ CPU.architecture
27
27
  Returns a string indicating the type of processor. This is the
28
28
  architecture (e.g. sparcv9), not the exact model (e.g. Ultra-IIe).
29
29
  Returns nil if not found.
@@ -14,7 +14,7 @@
14
14
  puts "CPU Speed (Frequency): " + CPU.freq(0).to_s
15
15
  puts "Load avg: " + CPU.load_avg.to_s
16
16
  puts "Num CPU: " + CPU.num_cpu.to_s
17
- puts "Type: " + CPU.type
17
+ puts "Type: " + CPU.cpu_type
18
18
  puts "Model: " + CPU.model
19
19
  puts "Architecture: " + CPU.architecture
20
20
 
@@ -98,7 +98,7 @@ CPU.processors(host=localhost){ |cpu| ... }
98
98
  Note that not all of these members will necessarily be defined. See the
99
99
  NOTES section below.
100
100
 
101
- CPU.type(host=localhost)
101
+ CPU.cpu_type(host=localhost)
102
102
  Returns a string indicating the type of processor, e.g. GenuineIntel.
103
103
 
104
104
  == Exception Classes
@@ -6,7 +6,8 @@
6
6
  #
7
7
  # Modify as you see fit.
8
8
  #######################################################################
9
- require "sys/cpu"
9
+ require 'sys/cpu'
10
+ require 'pp'
10
11
  include Sys
11
12
 
12
13
  puts "VERSION: " + CPU::VERSION
@@ -14,11 +15,11 @@ puts "========"
14
15
 
15
16
  puts "Architecture: " + CPU.architecture.to_s
16
17
  puts "CPU Speed (Frequency): " + CPU.freq.to_s
17
- puts "Load Average: " + CPU.load_average.to_s
18
+ puts "Load Average: " + CPU.load_avg.to_s
18
19
  puts "Model: " + CPU.model.to_s
19
- puts "Type: " + CPU.type.to_s
20
+ puts "Type: " + CPU.cpu_type.to_s
20
21
  puts "Num CPU: " + CPU.num_cpu.to_s
21
22
 
22
23
  CPU.processors{ |cpu|
23
- p cpu
24
+ pp cpu
24
25
  }
@@ -42,7 +42,7 @@ module Sys
42
42
  class CPU
43
43
 
44
44
  # The version of the sys-cpu library.
45
- VERSION = '0.6.4'
45
+ VERSION = '0.7.0'
46
46
 
47
47
  # :stopdoc:
48
48
 
@@ -0,0 +1,347 @@
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
+ # The version of the sys-cpu library
13
+ VERSION = '0.7.0'
14
+
15
+ CTL_HW = 6 # Generic hardware/cpu
16
+
17
+ HW_MACHINE = 1 # Machine class
18
+ HW_MODEL = 2 # Specific machine model
19
+ HW_NCPU = 3 # Number of CPU's
20
+ HW_CPU_FREQ = 15 # CPU frequency
21
+
22
+ if RbConfig::CONFIG['host_os'] =~ /bsd/
23
+ HW_MACHINE_ARCH = 11 # Machine architecture
24
+ else
25
+ HW_MACHINE_ARCH = 12 # Machine architecture
26
+ end
27
+
28
+ SI_MACHINE = 5
29
+ SI_ARCHITECTURE = 6
30
+ SC_NPROCESSORS_ONLN = 15
31
+
32
+ P_OFFLINE = 1
33
+ P_ONLINE = 2
34
+ P_FAULTED = 4
35
+ P_POWEROFF = 5
36
+ P_NOINTR = 6
37
+ P_SPARE = 7
38
+
39
+ CPU_ARCH_ABI64 = 0x01000000
40
+ CPU_TYPE_X86 = 7
41
+ CPU_TYPE_X86_64 = (CPU_TYPE_X86 | CPU_ARCH_ABI64)
42
+ CPU_TYPE_SPARC = 14
43
+ CPU_TYPE_POWERPC = 18
44
+ CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64
45
+
46
+ begin
47
+ attach_function(
48
+ :sysctl,
49
+ [:pointer, :uint, :pointer, :pointer, :pointer, :size_t],
50
+ :int
51
+ )
52
+ private_class_method :sysctl
53
+ rescue FFI::NotFoundError
54
+ # Do nothing, not supported on this platform.
55
+ end
56
+
57
+ begin
58
+ attach_function(
59
+ :sysctlbyname,
60
+ [:string, :pointer, :pointer, :pointer, :size_t],
61
+ :int
62
+ )
63
+ private_class_method :sysctlbyname
64
+ rescue FFI::NotFoundError
65
+ # Do nothing, not supported on this platform.
66
+ end
67
+
68
+ # Solaris
69
+ begin
70
+ attach_function :getloadavg, [:pointer, :int], :int
71
+ attach_function :processor_info, [:int, :pointer], :int
72
+ attach_function :sysconf, [:int], :long
73
+ attach_function :sysinfo, [:int, :pointer, :long], :int
74
+
75
+ private_class_method :getloadavg
76
+ private_class_method :processor_info
77
+ private_class_method :sysconf
78
+ private_class_method :sysinfo
79
+ rescue FFI::NotFoundError
80
+ # Do nothing, not supported on this platform.
81
+ end
82
+
83
+ class ProcInfo < FFI::Struct
84
+ layout(
85
+ :pi_state, :int,
86
+ :pi_processor_type, [:char, 16],
87
+ :pi_fputypes, [:char, 32],
88
+ :pi_clock, :int
89
+ )
90
+ end
91
+
92
+ def self.architecture
93
+ if respond_to?(:sysinfo, true)
94
+ buf = 0.chr * 257
95
+
96
+ if sysinfo(SI_ARCHITECTURE, buf, buf.size) < 0
97
+ raise Error, "sysinfo function failed"
98
+ end
99
+
100
+ buf.strip
101
+ elsif respond_to?(:sysctlbyname, true)
102
+ optr = FFI::MemoryPointer.new(:char, 256)
103
+ size = FFI::MemoryPointer.new(:size_t)
104
+
105
+ size.write_int(optr.size)
106
+
107
+ if RbConfig::CONFIG['host_os'] =~ /darwin/i
108
+ name = 'hw.machine'
109
+ else
110
+ name = 'hw.machine_arch'
111
+ end
112
+
113
+ if sysctlbyname(name, optr, size, nil, 0) < 0
114
+ raise Error, "sysctlbyname function failed"
115
+ end
116
+
117
+ optr.read_string
118
+ else
119
+ buf = 0.chr * 64
120
+ mib = FFI::MemoryPointer.new(:int, 2)
121
+ size = FFI::MemoryPointer.new(:long, 1)
122
+
123
+ mib.write_array_of_int([CTL_HW, HW_MACHINE_ARCH])
124
+ size.write_int(buf.size)
125
+
126
+ if sysctl(mib, 2, buf, size, nil, 0) < 0
127
+ raise Error, "sysctl function failed"
128
+ end
129
+
130
+ buf.strip
131
+ end
132
+ end
133
+
134
+ def self.num_cpu
135
+ if respond_to?(:sysctlbyname, true)
136
+ optr = FFI::MemoryPointer.new(:long)
137
+ size = FFI::MemoryPointer.new(:size_t)
138
+
139
+ size.write_long(optr.size)
140
+
141
+ if sysctlbyname('hw.ncpu', optr, size, nil, 0) < 0
142
+ raise Error, "sysctlbyname failed"
143
+ end
144
+
145
+ optr.read_long
146
+ elsif respond_to?(:sysconf, true)
147
+ num = sysconf(SC_NPROCESSORS_ONLN)
148
+
149
+ if num < 0
150
+ raise Error, "sysconf function failed"
151
+ end
152
+
153
+ num
154
+ else
155
+ buf = 0.chr * 4
156
+ mib = FFI::MemoryPointer.new(:int, 2)
157
+ size = FFI::MemoryPointer.new(:long, 1)
158
+
159
+ mib.write_array_of_int([CTL_HW, HW_NCPU])
160
+ size.write_int(buf.size)
161
+
162
+ if sysctl(mib, 2, buf, size, nil, 0) < 0
163
+ raise Error, "sysctl function failed"
164
+ end
165
+
166
+ buf.strip.unpack("C").first
167
+ end
168
+ end
169
+
170
+ def self.machine
171
+ if respond_to?(:sysctl, true)
172
+ buf = 0.chr * 32
173
+ mib = FFI::MemoryPointer.new(:int, 2)
174
+ size = FFI::MemoryPointer.new(:long, 1)
175
+
176
+ mib.write_array_of_int([CTL_HW, HW_MACHINE])
177
+ size.write_int(buf.size)
178
+
179
+ if sysctl(mib, 2, buf, size, nil, 0) < 0
180
+ raise Error, "sysctl function failed"
181
+ end
182
+
183
+ buf.strip
184
+ else
185
+ buf = 0.chr * 257
186
+
187
+ if sysinfo(SI_MACHINE, buf, buf.size) < 0
188
+ raise Error, "sysinfo function failed"
189
+ end
190
+
191
+ buf.strip
192
+ end
193
+ end
194
+
195
+ def self.model
196
+ if RbConfig::CONFIG['host_os'] =~ /darwin/i
197
+ ptr = FFI::MemoryPointer.new(:long)
198
+ size = FFI::MemoryPointer.new(:size_t)
199
+
200
+ size.write_long(ptr.size)
201
+
202
+ if sysctlbyname("hw.cputype", ptr, size, nil, 0) < 0
203
+ raise "sysctlbyname function failed"
204
+ end
205
+
206
+ case ptr.read_long
207
+ when CPU_TYPE_X86, CPU_TYPE_X86_64
208
+ "Intel"
209
+ when CPU_TYPE_SPARC
210
+ "Sparc"
211
+ when CPU_TYPE_POWERPC, CPU_TYPE_POWERPC64
212
+ "PowerPC"
213
+ else
214
+ "Unknown"
215
+ end
216
+ else
217
+ if respond_to?(:sysctl, true)
218
+ buf = 0.chr * 64
219
+ mib = FFI::MemoryPointer.new(:int, 2)
220
+ size = FFI::MemoryPointer.new(:long, 1)
221
+
222
+ mib.write_array_of_int([CTL_HW, HW_MODEL])
223
+ size.write_int(buf.size)
224
+
225
+ if sysctl(mib, 2, buf, size, nil, 0) < 0
226
+ raise Error, "sysctl function failed"
227
+ end
228
+
229
+ buf.strip
230
+ else
231
+ pinfo = ProcInfo.new
232
+
233
+ # Some systems start at 0, some at 1
234
+ if processor_info(0, pinfo) < 0
235
+ if processor_info(1, pinfo) < 0
236
+ raise Error, "process_info function failed"
237
+ end
238
+ end
239
+
240
+ pinfo[:pi_processor_type].to_s
241
+ end
242
+ end
243
+ end
244
+
245
+ def self.freq
246
+ if respond_to?(:sysctlbyname, true)
247
+ optr = FFI::MemoryPointer.new(:long)
248
+ size = FFI::MemoryPointer.new(:size_t)
249
+
250
+ size.write_long(optr.size)
251
+
252
+ if RbConfig::CONFIG['host_os'] =~ /bsd/i
253
+ name = 'hw.clockrate'
254
+ else
255
+ name = 'hw.cpufrequency'
256
+ end
257
+
258
+ if sysctlbyname(name, optr, size, nil, 0) < 0
259
+ raise Error, "sysctlbyname failed"
260
+ end
261
+
262
+ if RbConfig::CONFIG['host_os'] =~ /darwin/i
263
+ optr.read_long / 1000000
264
+ else
265
+ optr.read_long
266
+ end
267
+ elsif respond_to?(:sysctl, true)
268
+ buf = 0.chr * 16
269
+ mib = FFI::MemoryPointer.new(:int, 2)
270
+ size = FFI::MemoryPointer.new(:long, 1)
271
+
272
+ mib.write_array_of_int([CTL_HW, HW_CPU_FREQ])
273
+ size.write_int(buf.size)
274
+
275
+ if sysctl(mib, 2, buf, size, nil, 0) < 0
276
+ raise Error, "sysctl function failed"
277
+ end
278
+
279
+ buf.unpack("I*").first / 1000000
280
+ else
281
+ pinfo = ProcInfo.new
282
+
283
+ # Some systems start at 0, some at 1
284
+ if processor_info(0, pinfo) < 0
285
+ if processor_info(1, pinfo) < 0
286
+ raise Error, "process_info function failed"
287
+ end
288
+ end
289
+
290
+ pinfo[:pi_clock].to_i
291
+ end
292
+ end
293
+
294
+ def self.load_avg
295
+ if respond_to?(:getloadavg, true)
296
+ loadavg = FFI::MemoryPointer.new(:double, 3)
297
+
298
+ if getloadavg(loadavg, loadavg.size) < 0
299
+ raise Error, "getloadavg function failed"
300
+ end
301
+
302
+ loadavg.get_array_of_double(0, 3)
303
+ end
304
+ end
305
+
306
+ def self.fpu_type
307
+ raise NoMethodError unless respond_to?(:processor_info, true)
308
+
309
+ pinfo = ProcInfo.new
310
+
311
+ if processor_info(0, pinfo) < 0
312
+ if processor_info(1, pinfo) < 0
313
+ raise Error, "process_info function failed"
314
+ end
315
+ end
316
+
317
+ pinfo[:pi_fputypes].to_s
318
+ end
319
+
320
+ def self.state(num = 0)
321
+ raise NoMethodError unless respond_to?(:processor_info, true)
322
+
323
+ pinfo = ProcInfo.new
324
+
325
+ if processor_info(num, pinfo) < 0
326
+ raise Error, "process_info function failed"
327
+ end
328
+
329
+ case pinfo[:pi_state].to_i
330
+ when P_ONLINE
331
+ "online"
332
+ when P_OFFLINE
333
+ "offline"
334
+ when P_POWEROFF
335
+ "poweroff"
336
+ when P_FAULTED
337
+ "faulted"
338
+ when P_NOINTR
339
+ "nointr"
340
+ when P_SPARE
341
+ "spare"
342
+ else
343
+ "unknown"
344
+ end
345
+ end
346
+ end
347
+ end