File Coverage

blib/lib/Linux/Cpuinfo.pm
Criterion Covered Total %
statement 112 115 97.3
branch 27 34 79.4
condition 13 20 65.0
subroutine 17 17 100.0
pod 4 4 100.0
total 173 190 91.0


line stmt bran cond sub pod time code
1             #******************************************************************************
2             #*
3             #* GELLYFISH SOFTWARE
4             #*
5             #*
6             #******************************************************************************
7             #*
8             #* PROGRAM : Linux::Cpuinfo
9             #*
10             #* AUTHOR : JNS
11             #*
12             #* DESCRIPTION : Object Oriented interface to /proc/cpuinfo
13             #*
14             #*****************************************************************************
15              
16             package Linux::Cpuinfo;
17              
18             =head1 NAME
19              
20             Linux::Cpuinfo - Object Oriented Interface to /proc/cpuinfo
21              
22             =head1 SYNOPSIS
23              
24             # Old interface ( for single processor devices )
25              
26             use Linux::Cpuinfo;
27              
28             my $cpu = Linux::Cpuinfo->new();
29              
30             die ('Could not find cpu info (does /proc/cpuinfo exists?)')
31             unless ref $cpu;
32              
33             print $cpu->model_name();
34              
35              
36             # New Interface ( copes with SMP ).
37              
38             my $cpuinfo = Linux::Cpuinfo->new();
39              
40             $cnt = $cpuinfo->num_cpus(); # > 1 for an SMP system
41              
42              
43             foreach my $cpu ( $cpuinfo->cpus() )
44             {
45             print $cpu->bogomips(),"\n";
46             }
47              
48             =head1 DESCRIPTION
49              
50             On Linux systems various information about the CPU ( or CPUs ) in the
51             computer can be gleaned from C. This module provides an
52             object oriented interface to that information for relatively simple use
53             in Perl programs.
54              
55             =head2 METHODS
56              
57             The interface has changed between revisions 1.2 and 1.3 of this module
58             in order to deal with systems with multiple CPUs - now the details of a
59             CPU are acquired by the methods of the Linux::Cpuinfo::Cpu objects returned
60             by the C and C methods of this class. However in order to
61             retain backward compatibility if the methods described for Linux::Cpuinfo::Cpu
62             are called a Linux::Cpuinfo object then it will work as previously - returning
63             the details of the sole CPU on a single processor system and the last discovered
64             CPU on system with multiple processors ( this was the implicit behaviour on
65             previous versions). Whilst not strictly deprecated this interface is not
66             the recommended one.
67              
68             =over 4
69              
70             =cut
71              
72 4     4   46903 use 5.006;
  4         11  
  4         125  
73              
74 4     4   14 use strict;
  4         7  
  4         116  
75 4     4   30 use warnings;
  4         5  
  4         97  
76              
77 4     4   16 use Carp;
  4         4  
  4         2719  
78              
79              
80             our $AUTOLOAD;
81              
82             our $VERSION = '1.12';
83              
84             $VERSION = eval $VERSION;
85              
86             =item cpuinfo
87              
88             Returns a blessed object suitable for calling the rest of the methods on or
89             a false value if for some reason C cant be opened. The first
90             argument can be an alternative file that provides identical information. You
91             may also supply a hashref containing other arguments - the valid keys are
92              
93             =over 2
94              
95             =item NoFatal
96              
97             The default behaviour is for the method to croak if an attribute is requested
98             that is not available on this particular CPU. If this argument is supplied
99             with a true value then the method will return undef instead.
100              
101             =back
102              
103             =cut
104              
105             sub cpuinfo
106             {
107 16     16 1 6615 my ( $proto, $file, $args ) = @_;
108              
109 16   33     96 my $class = ref($proto) || $proto;
110              
111 16         19 my $self;
112              
113 16 100 100     90 if ( $file and ref($file) and ref($file) eq 'HASH' )
      66        
114             {
115 1         1 $args = $file;
116 1         2 $file = undef;
117             }
118              
119 16   100     45 $file ||= '/proc/cpuinfo';
120              
121 16 50 33     467 if ( -e $file and -f $file )
122             {
123              
124 16 50       364 if ( open( CPUINFO, $file ) )
125             {
126 16         30 $self = {};
127              
128 16         72 local $/ = '';
129              
130 16         50 $self->{_private}->{num_cpus} = 0;
131              
132 16         32 $self->{_cpuinfo} = [];
133              
134 16         460 while ()
135             {
136 70         82 chomp;
137              
138              
139 70         66 my $cpuinfo = {};
140              
141 70         374 foreach my $cpuline ( split /\n/ )
142             {
143 1520         4181 my ( $attribute, $value ) = split /\s*:\s*/, $cpuline;
144              
145 1520         2255 $attribute =~ s/\s+/_/;
146 1520         1356 $attribute = lc($attribute);
147              
148 1520 100 100     4609 if ( $value && $value =~ /^(no|not available|yes)$/ )
149             {
150 208 100       273 $value = $value eq 'yes' ? 1 : 0;
151             }
152              
153 1520 100       1679 if ( $attribute eq 'flags' )
154             {
155 58         338 @{ $cpuinfo->{flags} } = split / /, $value;
  58         350  
156             }
157             else
158             {
159 1462         2300 $cpuinfo->{$attribute} = $value;
160             }
161              
162             }
163             # This is a lot uglier than it needs to be. The perl 6
164             # version is 6 lines.
165             # It seems that single core arm6 or 7 cores highlight
166             # a bug where there is a spurious \n in there
167             # The alert will correctly surmise this breaks for assymetric
168             # cpus
169            
170 70         148 my $ok_to_add = 1;
171 70 100       61 if ( @{ $self->{_cpuinfo} } )
  70         138  
172             {
173 54 100       42 if (keys %{$self->{_cpuinfo}->[-1]->{_data}} != keys %{$cpuinfo} )
  54         101  
  54         465  
174             {
175 4         3 foreach my $key ( keys %{$cpuinfo} )
  4         8  
176             {
177 12         20 $self->{_cpuinfo}->[-1]->{_data}->{$key} = $cpuinfo->{$key};
178             }
179 4         5 $ok_to_add = 0;
180             }
181             }
182 70 100       175 if ( $ok_to_add )
183             {
184 66         136 my $cpuinfo_cpu = Linux::Cpuinfo::Cpu->new( $cpuinfo, $args );
185 66         75 $self->{_private}->{num_cpus}++;
186 66         46 push @{ $self->{_cpuinfo} }, $cpuinfo_cpu;
  66         964  
187             }
188             }
189              
190 16         28 bless $self, $class;
191 16         238 close CPUINFO; # can this fail
192             }
193             }
194              
195 16         81 return $self;
196             }
197              
198             # just in case anyone is a lame as me :)
199              
200             *new = \&cpuinfo;
201              
202             =item num_cpus
203              
204             Returns the number of CPUs reported for this system.
205              
206             =cut
207              
208             sub num_cpus
209             {
210 22     22 1 6680 my ($self) = @_;
211              
212 22         84 return $self->{_private}->{num_cpus};
213             }
214              
215             =item cpu SCALAR $cpu
216              
217             Returns an object of type Linux::Cpuinfo::Cpu corresponding to the CPU of
218             index $cpu ( where $cpu >= 0 and $cpu < num_cpus() ) - if $cpu is omitted
219             this will return an object correspnding to the last CPU found.
220              
221             If $cpu is out of bounds with respect to the number of CPUs then it will
222             be set to the first or last CPU ( depending whether $cpu was < 0 or >num_cpus )
223              
224             =cut
225              
226             sub cpu
227             {
228 1     1 1 428 my ( $self, $cpu ) = @_;
229              
230 1 50       4 if ( defined $cpu )
231             {
232 1 50       3 $cpu = 0 if ( $cpu < 0 );
233 1 50       1 $cpu = $#{ $self->{_cpuinfo} } if $cpu > $#{ $self->{_cpuinfo} };
  0         0  
  1         7  
234             }
235             else
236             {
237 0         0 $cpu = $#{ $self->{_cpuinfo} };
  0         0  
238             }
239              
240 1         3 return $self->{_cpuinfo}->[$cpu];
241             }
242              
243             =item cpus
244              
245             Returns a list containing objects of type Linux::Cpuinfo::Cpu corresponding
246             to the CPUs discovered in this system. If the method is called in a scalar
247             context it will return a reference to an array of those objects.
248              
249             =cut
250              
251             sub cpus
252             {
253 13     13 1 760 my ($self) = @_;
254              
255 13 100       31 if ( wantarray() )
256             {
257 10         12 return @{ $self->{_cpuinfo} };
  10         29  
258             }
259             else
260             {
261 3         51 return $self->{_cpuinfo};
262             }
263             }
264              
265             sub AUTOLOAD
266             {
267              
268 2     2   959 my ($self) = @_;
269              
270 2 50       9 return if $AUTOLOAD =~ /DESTROY/;
271              
272 2         12 my ($method) = $AUTOLOAD =~ /.*::(.+?)$/;
273              
274             {
275 4     4   19 no strict 'refs';
  4         7  
  4         472  
  2         3  
276              
277 2         10 *{$AUTOLOAD} = sub {
278 3     3   507 my ($self) = @_;
279 3         12 return $self->{_cpuinfo}->[ $#{ $self->{_cpuinfo} } ]->$method();
  3         19  
280 2         9 };
281             }
282 2         2 goto &{$AUTOLOAD};
  2         7  
283             }
284              
285             # The following are autoloaded methods of the Linux::Cpuinfo::Cpu class
286              
287             =back
288              
289             =head2 PER CPU METHODS OF Linux::Cpuinfo::Cpu
290              
291             Note that not all of the methods listed here are available on all CPU
292             types. For instance, MIPS CPUs have no cpuid instruction, but might
293             sport a byte order attribute.
294              
295             There are also some other methods available for some CPUs which aren't
296             listed here.
297              
298             =over 4
299              
300             =item processor
301              
302             This is the index of the processor this information is for, it will be zero
303             for a the first CPU (which is the only one on single-proccessor systems), one
304             for the second and so on.
305              
306             =item vendor_id
307              
308             This is a vendor defined string for X86 CPUs such as 'GenuineIntel' or
309             'AuthenticAMD'. 12 bytes long, since it is returned via three 32 byte long
310             registers.
311              
312             =item cpu_family
313              
314             This should return an integer that will indicate the 'family' of the
315             processor - This is for instance '6' for a Pentium III. Might be undefined for
316             non-X86 CPUs.
317              
318             =item model or cpu_model
319              
320             An integer that is probably vendor dependent that indicates their version
321             of the above cpu_family
322              
323             =item model_name
324              
325             A string such as 'Pentium III (Coppermine)'.
326              
327             =item stepping
328              
329             I'm lead to believe this is a version increment used by intel.
330              
331             =item cpu_mhz
332              
333             I guess this is self explanatory - it might however be different to what
334             it says on the box. The Mhz is measured at boot time by the kernel and
335             represents the true Mhz at that time.
336              
337             =item bus_mhz
338              
339             The MHz of the bus system.
340              
341             =item cache_size
342              
343             The cache size for this processor - it might well have the units appended
344             ( such as 'KB' )
345              
346             =item fdiv_bug
347              
348             True if this bug is present in the processor.
349              
350             =item hlt_bug
351              
352             True if this bug is present in the processor.
353              
354             =item sep_bug
355              
356             True if this bug is present in the processor.
357              
358             =item f00f_bug
359              
360             True if this bug is present in the processor.
361              
362             =item coma_bug
363              
364             True if this bug is present in the processor.
365              
366             =item fpu
367              
368             True if the CPU has a floating point unit.
369              
370             =item fpu_exception
371              
372             True if the floating point unit can throw an exception.
373              
374             =item cpuid_level
375              
376             The C assembler instruction is only present on X86 CPUs. This attribute
377             represents the level of the instruction that is supported by the CPU. The first
378             CPUs had only level 1, newer chips have more levels and can thus return more
379             information.
380              
381             =item wp
382              
383             No idea what this is on X86 CPUs.
384              
385             =item flags
386              
387             This is the set of flags that the CPU supports - this is returned as an
388             array reference.
389              
390             =item byte_order
391              
392             The byte order of the CPU, might be little endian or big endian, or undefined
393             for unknown.
394              
395             =item bogomips
396              
397             A system constant calculated when the kernel is booted - it is a (rather poor)
398             measure of the CPU's performance.
399              
400             =back
401              
402             =cut
403              
404             package Linux::Cpuinfo::Cpu;
405              
406 4     4   16 use strict;
  4         4  
  4         95  
407 4     4   13 use Carp;
  4         4  
  4         662  
408              
409             our $AUTOLOAD;
410              
411             sub new
412             {
413 66     66   87 my ( $proto, $cpuinfo, $args ) = @_;
414              
415 66   33     197 my $class = ref($proto) || $proto;
416              
417 66         65 my $self = {};
418              
419 66         86 $self->{_args} = $args;
420 66         67 $self->{_data} = $cpuinfo;
421              
422 66         109 bless $self, $class;
423              
424 66         86 return $self;
425              
426             }
427              
428             sub AUTOLOAD
429             {
430              
431 85     85   59395 my ($self) = @_;
432              
433 85 50       274 return if $AUTOLOAD =~ /DESTROY/;
434              
435 85         492 my ($method) = $AUTOLOAD =~ /.*::(.+?)$/;
436              
437 85 100       213 if ( exists $self->{_data}->{$method} )
438             {
439 4     4   18 no strict 'refs';
  4         5  
  4         479  
440              
441 83         257 *{$AUTOLOAD} = sub {
442 212     212   87997 my ($self) = @_;
443 212         1132 return $self->{_data}->{$method};
444 83         293 };
445              
446 83         91 goto &{$AUTOLOAD};
  83         227  
447              
448             }
449             else
450             {
451              
452 2 100       5 if ( $self->{_args}->{NoFatal} )
453             {
454 1         3 return undef;
455             }
456             else
457             {
458 1         135 croak(
459             sprintf(
460             q(Can't locate object method "%s" via package "%s"),
461             $method, ref($self)
462             )
463             );
464             }
465              
466             }
467             }
468              
469             1;
470             __END__