1
1
/* CPU frequency determination.
3
Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3
Copyright 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5
5
This file is part of the GNU MP Library.
17
17
You should have received a copy of the GNU Lesser General Public License
18
18
along with the GNU MP Library; see the file COPYING.LIB. If not, write to
19
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20
MA 02111-1307, USA. */
19
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
MA 02110-1301, USA. */
23
/* Currently we don't get a CPU frequency on the following systems,
25
alphaev5-cray-unicosmk2.0.6.X
26
times() has been seen at 13.33 ns (75 MHz), which is probably not the
27
cpu frequency. Measuring the cycle counter against that would be
28
possible though. But currently we don't use the cycle counter due to
29
unicos having int==8bytes where tune/alpha.asm assumes int==4bytes.
31
m68040-unknown-netbsd1.4.1
32
Not sure if the system even knows the cpu frequency. There's no
33
cycle counter to measure, though we could perhaps make a loop taking
34
a known number of cycles and measure that.
38
powerpc604-ibm-aix4.3.1.0
39
powerpc604-ibm-aix4.3.3.0
40
powerpc630-ibm-aix4.3.3.0
41
powerpc-unknown-netbsd1.6
42
Don't know where any info hides on these. mftb is not related to the
43
cpu frequency so doesn't help.
45
sparc-unknown-linux-gnu [maybe]
46
Don't know where any info hides on this.
49
The times() call seems to be for instance 2.22 nanoseconds, which
50
might be the cpu frequency (450 mhz), but need to confirm that.
22
54
#include "config.h"
57
#include <invent.h> /* for IRIX invent_cpuinfo_t */
25
61
#include <stdlib.h> /* for getenv, qsort */
62
#include <string.h> /* for memcmp */
27
65
#include <unistd.h> /* for sysconf */
30
68
#include <sys/types.h>
32
#include <sys/param.h> /* for constants needed by NetBSD <sys/sysctl.h> */
70
#if HAVE_SYS_ATTRIBUTES_H
71
#include <sys/attributes.h> /* for IRIX attr_get(), needs sys/types.h */
74
#if HAVE_SYS_IOGRAPH_H
75
#include <sys/iograph.h> /* for IRIX INFO_LBL_DETAIL_INVENT */
78
#if HAVE_SYS_PARAM_H /* for constants needed by NetBSD <sys/sysctl.h> */
79
#include <sys/param.h> /* and needed by HPUX <sys/pstat.h> */
83
#include <sys/pstat.h> /* for HPUX pstat_getprocessor() */
34
86
#if HAVE_SYS_SYSCTL_H
35
87
#include <sys/sysctl.h> /* for sysctlbyname() */
54
106
#include <sys/processor.h> /* for solaris processor_info_t */
109
/* On AIX 5.1 with gcc 2.9-aix51-020209 in -maix64 mode, <sys/sysinfo.h>
110
gets an error about "fill" in "struct cpuinfo" having a negative size,
111
apparently due to __64BIT_KERNEL not being defined because _KERNEL is not
112
defined. Avoid this file if we don't actually need it, which we don't on
113
AIX since there's no getsysinfo there. */
114
#if HAVE_SYS_SYSINFO_H && HAVE_GETSYSINFO
115
#include <sys/sysinfo.h> /* for OSF getsysinfo */
118
#if HAVE_MACHINE_HAL_SYSINFO_H
119
#include <machine/hal_sysinfo.h> /* for OSF GSI_CPU_INFO, struct cpu_info */
57
122
/* Remove definitions from NetBSD <sys/param.h>, to avoid conflicts with
168
/* getsysinfo is available on OSF, or 4.0 and up at least.
169
The man page (on 4.0) suggests a 0 return indicates information not
170
available, but that seems to be the normal return for GSI_CPU_INFO. */
172
freq_getsysinfo (int help)
178
HELP ("getsysinfo() GSI_CPU_INFO");
181
if (getsysinfo (GSI_CPU_INFO, (caddr_t) &c, sizeof (c),
182
&start, NULL, NULL) != -1)
184
speed_cycletime = 1e-6 / (double) c.mhz;
185
if (speed_option_verbose)
186
printf ("Using getsysinfo() GSI_CPU_INFO %u for cycle time %.3g\n",
187
c.mhz, speed_cycletime);
195
/* In HPUX 10 and up, pstat_getprocessor() psp_iticksperclktick is the
196
number of CPU cycles (ie. the CR16 register) per CLK_TCK. HPUX 9 doesn't
197
have that field in pst_processor though, and has no apparent
201
freq_pstat_getprocessor (int help)
203
#if HAVE_PSTAT_GETPROCESSOR && HAVE_PSP_ITICKSPERCLKTICK
204
struct pst_processor p;
206
HELP ("pstat_getprocessor() psp_iticksperclktick");
208
if (pstat_getprocessor (&p, sizeof(p), 1, 0) != -1)
211
speed_cycletime = 1.0 / (c * p.psp_iticksperclktick);
212
if (speed_option_verbose)
213
printf ("Using pstat_getprocessor() psp_iticksperclktick %lu and clk_tck %ld for cycle time %.3g\n",
214
(unsigned long) p.psp_iticksperclktick, c,
103
223
/* i386 FreeBSD 2.2.8 sysctlbyname machdep.i586_freq is in Hertz.
104
224
There's no obvious defines available to get this from plain sysctl. */
115
235
if (sysctlbyname ("machdep.i586_freq", &val, &size, NULL, 0) == 0
116
236
&& size == sizeof(val))
238
speed_cycletime = 1.0 / (double) val;
118
239
if (speed_option_verbose)
119
240
printf ("Using sysctlbyname() machdep.i586_freq %u for cycle time %.3g\n",
120
241
val, speed_cycletime);
121
speed_cycletime = 1.0 / (double) val;
142
262
if (sysctlbyname ("machdep.tsc_freq", &val, &size, NULL, 0) == 0
143
263
&& size == sizeof(val))
265
speed_cycletime = 1.0 / (double) val;
145
266
if (speed_option_verbose)
146
267
printf ("Using sysctlbyname() machdep.tsc_freq %u for cycle time %.3g\n",
147
268
val, speed_cycletime);
148
speed_cycletime = 1.0 / (double) val;
171
291
size = sizeof(val);
172
292
if (sysctl (mib, 2, &val, &size, NULL, 0) == 0)
294
speed_cycletime = 1.0 / (double) val;
174
295
if (speed_option_verbose)
175
296
printf ("Using sysctl() hw.cpufrequency %u for cycle time %.3g\n",
176
297
val, speed_cycletime);
177
speed_cycletime = 1.0 / (double) val;
185
/* Alpha FreeBSD 4.1 and NetBSD 1.4 sysctl- hw.model string gives "Digital
186
AlphaPC 164LX 599 MHz". NetBSD 1.4 doesn't seem to have sysctlbyname, so
305
/* The following ssyctl hw.model strings have been observed,
307
Alpha FreeBSD 4.1: Digital AlphaPC 164LX 599 MHz
308
NetBSD 1.4: Digital AlphaPC 164LX 599 MHz
309
NetBSD 1.6.1: CY7C601 @ 40 MHz, TMS390C602A FPU
311
NetBSD 1.4 doesn't seem to have sysctlbyname, so sysctl() is used. */
190
314
freq_sysctl_hw_model (int help)
204
328
size = sizeof(str);
205
329
if (sysctl (mib, 2, str, &size, NULL, 0) == 0)
207
/* find the second last space */
209
for (i = 0; i < 2; i++)
331
for (p = str; *p != '\0'; p++)
334
if (sscanf (p, "%u MHz%n", &val, &end) == 1 && end != 0)
336
speed_cycletime = 1e-6 / (double) val;
337
if (speed_option_verbose)
338
printf ("Using sysctl() hw.model %u for cycle time %.3g\n",
339
val, speed_cycletime);
221
if (sscanf (p, "%u MHz", &val) != 1)
224
if (speed_option_verbose)
225
printf ("Using sysctl() hw.model %u for cycle time %.3g\n",
226
val, speed_cycletime);
227
speed_cycletime = 1e-6 / (double) val;
285
if (sscanf (buf, "clock : %lfMHz\n", &val) == 1)
401
if (sscanf (buf, "clock : %lfMHz\n%n", &val, &end) == 1 && end != 0)
287
403
speed_cycletime = 1e-6 / val;
288
404
if (speed_option_verbose)
326
443
while (fgets (buf, sizeof (buf), fp) != NULL)
328
if (sscanf (buf, " cpu0 is a \"%lf MHz", &val) == 1)
446
if (sscanf (buf, " cpu0 is a \"%lf MHz%n", &val, &end) == 1
330
449
speed_cycletime = 1e-6 / val;
331
450
if (speed_option_verbose)
361
482
while (fgets (buf, sizeof (buf), fp) != NULL)
363
if (sscanf (buf, " The speed of the CPU is approximately %lfMhz",
485
if (sscanf (buf, " The speed of the CPU is approximately %lfMhz%n",
486
&val, &end) == 1 && end != 0)
366
488
speed_cycletime = 1e-6 / val;
367
489
if (speed_option_verbose)
381
/* "hinv -c processor" for IRIX.
382
The first line printed is for instance "2 195 MHZ IP27 Processors". */
503
/* attr_get("/hw/cpunum/0",INFO_LBL_DETAIL_INVENT) ic_cpu_info.cpufq for
504
IRIX 6.5. Past versions don't have INFO_LBL_DETAIL_INVENT,
505
invent_cpuinfo_t, or /hw/cpunum/0.
507
The same information is available from the "hinv -c processor" command,
508
but it seems better to make a system call where possible. */
384
freq_irix_hinv (int help)
511
freq_attr_get_invent (int help)
393
HELP ("IRIX \"hinv -c processor\" output");
395
/* Error messages are sent to /dev/null in case hinv doesn't exist. The
396
brackets are necessary for some shells. */
397
if ((fp = popen ("(hinv -c processor) 2>/dev/null", "r")) != NULL)
514
#if HAVE_ATTR_GET && HAVE_INVENT_H && defined (INFO_LBL_DETAIL_INVENT)
515
invent_cpuinfo_t inv;
518
HELP ("attr_get(\"/hw/cpunum/0\") ic_cpu_info.cpufq");
521
if (attr_get ("/hw/cpunum/0", INFO_LBL_DETAIL_INVENT,
522
(char *) &inv, &len, 0) == 0
523
&& len == sizeof (inv)
524
&& inv.ic_gen.ig_invclass == INV_PROCESSOR)
399
while (fgets (buf, sizeof (buf), fp) != NULL)
401
if (sscanf (buf, "%d %lf MHZ", &nproc, &val) == 2)
403
speed_cycletime = 1e-6 / val;
404
if (speed_option_verbose)
405
printf ("Using hinv -c processor \"%.2f MHZ\" for cycle time %.3g\n", val, speed_cycletime);
526
val = inv.ic_cpu_info.cpufq;
527
speed_cycletime = 1e-6 / val;
528
if (speed_option_verbose)
529
printf ("Using attr_get(\"/hw/cpunum/0\") ic_cpu_info.cpufq %d MHz for cycle time %.3g\n", val, speed_cycletime);
588
/* "hinv -c processor" for IRIX. The following lines have been seen,
590
1 150 MHZ IP20 Processor
591
2 195 MHZ IP27 Processors
592
Processor 0: 500 MHZ IP35
594
This information is available from attr_get() on IRIX 6.5 (see above),
595
but on IRIX 6.2 it's not clear where to look, so fall back on
599
freq_irix_hinv (int help)
608
HELP ("IRIX \"hinv -c processor\" output");
610
/* Error messages are sent to /dev/null in case hinv doesn't exist. The
611
brackets are necessary for some shells. */
612
if ((fp = popen ("(hinv -c processor) 2>/dev/null", "r")) != NULL)
614
while (fgets (buf, sizeof (buf), fp) != NULL)
617
if (sscanf (buf, "Processor 0: %lf MHZ%n", &val, &end) == 1
621
speed_cycletime = 1e-6 / val;
622
if (speed_option_verbose)
623
printf ("Using hinv -c processor \"%.2f MHZ\" for cycle time %.3g\n", val, speed_cycletime);
628
if (sscanf (buf, "%d %lf MHZ%n", &nproc, &val, &end) == 2
468
639
/* processor_info() for Solaris. "psrinfo" is the command-line interface to
469
640
this. "prtconf -vp" gives similar information.
514
/* "get" is called repeatedly until it ticks over, just in case on a fast
515
processor it takes less than a microsecond, though this is probably
516
unlikely if it's a system call.
518
speed_cyclecounter is called on the same side of the "get" for the start
519
and end measurements. It doesn't matter how long it takes from the "get"
520
sample to the cycles sample, since that period will cancel out in the
521
difference calculation (assuming it's the same each time).
523
Letting the test run for more than a process time slice is probably only
524
going to reduce accuracy, especially for getrusage when the cycle counter
525
is real time, or for gettimeofday if the cycle counter is in fact process
526
time. Use CLK_TCK/2 as a reasonable stop.
528
It'd be desirable to be quite accurate here. The default speed_precision
529
for a cycle counter is 10000 cycles, so to mix that with getrusage or
530
gettimeofday the frequency should be at least that accurate. But running
531
measurements for 10000 microseconds (or more) is too long. Be satisfied
532
with just a half clock tick (5000 microseconds usually). */
534
#define FREQ_MEASURE_ONE(name, type, get, sec, usec) \
536
type st1, st, et1, et; \
537
unsigned sc[2], ec[2]; \
538
long dt, half_tick; \
541
half_tick = (1000000L / clk_tck()) / 2; \
546
} while (usec(st) == usec(st1) && sec(st) == sec(st1)); \
548
speed_cyclecounter (sc); \
555
} while (usec(et) == usec(et1) && sec(et) == sec(et1)); \
557
speed_cyclecounter (ec); \
559
dc = speed_cyclecounter_diff (ec, sc); \
561
/* allow secs to cancel before multiplying */ \
562
dt = sec(et) - sec(st); \
563
dt = dt * 100000L + (usec(et) - usec(st)); \
565
if (dt >= half_tick) \
569
cyc = dt * 1e-6 / dc; \
571
if (speed_option_verbose >= 2) \
572
printf ("freq_measure_%s_one() dc=%.6g dt=%ld cyc=%.6g\n", \
573
name, dc, dt, cyc); \
575
return dt * 1e-6 / dc; \
579
685
#if HAVE_SPEED_CYCLECOUNTER && HAVE_GETTIMEOFDAY
581
687
freq_measure_gettimeofday_one (void)
584
690
#define timeval_tv_sec(t) ((t).tv_sec)
585
691
#define timeval_tv_usec(t) ((t).tv_usec)
586
692
FREQ_MEASURE_ONE ("gettimeofday", struct timeval,
587
call_gettimeofday, timeval_tv_sec, timeval_tv_usec);
693
call_gettimeofday, speed_cyclecounter,
694
timeval_tv_sec, timeval_tv_usec);
596
703
#define rusage_tv_sec(t) ((t).ru_utime.tv_sec)
597
704
#define rusage_tv_usec(t) ((t).ru_utime.tv_usec)
598
705
FREQ_MEASURE_ONE ("getrusage", struct rusage,
599
call_getrusage, rusage_tv_sec, rusage_tv_usec);
706
call_getrusage, speed_cyclecounter,
707
rusage_tv_sec, rusage_tv_usec);
627
735
if (t[j+MEASURE_MATCH-1] <= t[j] * MEASURE_TOLERANCE)
629
737
/* use the average of the range found */
630
speed_cycletime = (t[j+MEASURE_MATCH-1] + t[j]) / 2.0;
631
if (speed_option_verbose)
632
printf ("Using %s() measured cycle counter %.4g (%.2f MHz)\n",
633
name, speed_cycletime, 1e-6/speed_cycletime);
738
return (t[j+MEASURE_MATCH-1] + t[j]) / 2.0;
642
746
freq_measure_getrusage (int help)
644
748
#if HAVE_SPEED_CYCLECOUNTER && HAVE_GETRUSAGE
645
751
if (! getrusage_microseconds_p ())
647
753
if (! cycles_works_p ())
650
756
HELP ("cycle counter measured with microsecond getrusage()");
652
return freq_measure ("getrusage", freq_measure_getrusage_one);
758
cycletime = freq_measure ("getrusage", freq_measure_getrusage_one);
759
if (cycletime == -1.0)
762
speed_cycletime = cycletime;
763
if (speed_option_verbose)
764
printf ("Using getrusage() measured cycle counter %.4g (%.2f MHz)\n",
765
speed_cycletime, 1e-6/speed_cycletime);
667
784
HELP ("cycle counter measured with microsecond gettimeofday()");
669
return freq_measure ("gettimeofday", freq_measure_gettimeofday_one);
786
cycletime = freq_measure ("gettimeofday", freq_measure_gettimeofday_one);
787
if (cycletime == -1.0)
790
speed_cycletime = cycletime;
791
if (speed_option_verbose)
792
printf ("Using gettimeofday() measured cycle counter %.4g (%.2f MHz)\n",
793
speed_cycletime, 1e-6/speed_cycletime);
689
814
anything the system gives. */
690
815
freq_environment (help)
817
|| freq_attr_get_invent (help)
818
|| freq_getsysinfo (help)
819
|| freq_pstat_getprocessor (help)
692
820
|| freq_sysctl_hw_model (help)
693
821
|| freq_sysctl_hw_cpufrequency (help)
694
822
|| freq_sysctlbyname_i586_freq (help)