Home | History | Annotate | Line # | Download | only in tune
freq.c revision 1.1.1.3
      1      1.1  mrg /* CPU frequency determination.
      2      1.1  mrg 
      3  1.1.1.2  mrg Copyright 1999-2004 Free Software Foundation, Inc.
      4      1.1  mrg 
      5      1.1  mrg This file is part of the GNU MP Library.
      6      1.1  mrg 
      7      1.1  mrg The GNU MP Library is free software; you can redistribute it and/or modify
      8  1.1.1.2  mrg it under the terms of either:
      9  1.1.1.2  mrg 
     10  1.1.1.2  mrg   * the GNU Lesser General Public License as published by the Free
     11  1.1.1.2  mrg     Software Foundation; either version 3 of the License, or (at your
     12  1.1.1.2  mrg     option) any later version.
     13  1.1.1.2  mrg 
     14  1.1.1.2  mrg or
     15  1.1.1.2  mrg 
     16  1.1.1.2  mrg   * the GNU General Public License as published by the Free Software
     17  1.1.1.2  mrg     Foundation; either version 2 of the License, or (at your option) any
     18  1.1.1.2  mrg     later version.
     19  1.1.1.2  mrg 
     20  1.1.1.2  mrg or both in parallel, as here.
     21      1.1  mrg 
     22      1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     23      1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     24  1.1.1.2  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     25  1.1.1.2  mrg for more details.
     26      1.1  mrg 
     27  1.1.1.2  mrg You should have received copies of the GNU General Public License and the
     28  1.1.1.2  mrg GNU Lesser General Public License along with the GNU MP Library.  If not,
     29  1.1.1.2  mrg see https://www.gnu.org/licenses/.  */
     30      1.1  mrg 
     31      1.1  mrg 
     32      1.1  mrg /* Currently we don't get a CPU frequency on the following systems,
     33      1.1  mrg 
     34      1.1  mrg    alphaev5-cray-unicosmk2.0.6.X
     35      1.1  mrg        times() has been seen at 13.33 ns (75 MHz), which is probably not the
     36      1.1  mrg        cpu frequency.  Measuring the cycle counter against that would be
     37      1.1  mrg        possible though.  But currently we don't use the cycle counter due to
     38      1.1  mrg        unicos having int==8bytes where tune/alpha.asm assumes int==4bytes.
     39      1.1  mrg 
     40      1.1  mrg    m68040-unknown-netbsd1.4.1
     41      1.1  mrg        Not sure if the system even knows the cpu frequency.  There's no
     42      1.1  mrg        cycle counter to measure, though we could perhaps make a loop taking
     43      1.1  mrg        a known number of cycles and measure that.
     44      1.1  mrg 
     45      1.1  mrg    power-ibm-aix4.2.1.0
     46      1.1  mrg    power2-ibm-aix4.3.1.0
     47      1.1  mrg    powerpc604-ibm-aix4.3.1.0
     48      1.1  mrg    powerpc604-ibm-aix4.3.3.0
     49      1.1  mrg    powerpc630-ibm-aix4.3.3.0
     50      1.1  mrg    powerpc-unknown-netbsd1.6
     51      1.1  mrg        Don't know where any info hides on these.  mftb is not related to the
     52      1.1  mrg        cpu frequency so doesn't help.
     53      1.1  mrg 
     54      1.1  mrg    sparc-unknown-linux-gnu [maybe]
     55      1.1  mrg        Don't know where any info hides on this.
     56      1.1  mrg 
     57      1.1  mrg    t90-cray-unicos10.0.X
     58      1.1  mrg        The times() call seems to be for instance 2.22 nanoseconds, which
     59      1.1  mrg        might be the cpu frequency (450 mhz), but need to confirm that.
     60      1.1  mrg 
     61      1.1  mrg */
     62      1.1  mrg 
     63      1.1  mrg #include "config.h"
     64      1.1  mrg 
     65      1.1  mrg #if HAVE_INVENT_H
     66      1.1  mrg #include <invent.h> /* for IRIX invent_cpuinfo_t */
     67      1.1  mrg #endif
     68      1.1  mrg 
     69      1.1  mrg #include <stdio.h>
     70      1.1  mrg #include <stdlib.h> /* for getenv, qsort */
     71      1.1  mrg #include <string.h> /* for memcmp */
     72      1.1  mrg 
     73      1.1  mrg #if HAVE_UNISTD_H
     74      1.1  mrg #include <unistd.h> /* for sysconf */
     75      1.1  mrg #endif
     76      1.1  mrg 
     77      1.1  mrg #include <sys/types.h>
     78      1.1  mrg 
     79      1.1  mrg #if HAVE_SYS_ATTRIBUTES_H
     80      1.1  mrg #include <sys/attributes.h>   /* for IRIX attr_get(), needs sys/types.h */
     81      1.1  mrg #endif
     82      1.1  mrg 
     83      1.1  mrg #if HAVE_SYS_IOGRAPH_H
     84      1.1  mrg #include <sys/iograph.h>      /* for IRIX INFO_LBL_DETAIL_INVENT */
     85      1.1  mrg #endif
     86      1.1  mrg 
     87      1.1  mrg #if HAVE_SYS_PARAM_H     /* for constants needed by NetBSD <sys/sysctl.h> */
     88      1.1  mrg #include <sys/param.h>   /* and needed by HPUX <sys/pstat.h> */
     89      1.1  mrg #endif
     90      1.1  mrg 
     91      1.1  mrg #if HAVE_SYS_PSTAT_H
     92      1.1  mrg #include <sys/pstat.h>   /* for HPUX pstat_getprocessor() */
     93      1.1  mrg #endif
     94      1.1  mrg 
     95      1.1  mrg #if HAVE_SYS_SYSCTL_H
     96      1.1  mrg #include <sys/sysctl.h>  /* for sysctlbyname() */
     97      1.1  mrg #endif
     98      1.1  mrg 
     99      1.1  mrg #if TIME_WITH_SYS_TIME
    100      1.1  mrg # include <sys/time.h>  /* for struct timeval */
    101      1.1  mrg # include <time.h>
    102      1.1  mrg #else
    103      1.1  mrg # if HAVE_SYS_TIME_H
    104      1.1  mrg #  include <sys/time.h>
    105      1.1  mrg # else
    106      1.1  mrg #  include <time.h>
    107      1.1  mrg # endif
    108      1.1  mrg #endif
    109      1.1  mrg 
    110      1.1  mrg #if HAVE_SYS_RESOURCE_H
    111      1.1  mrg #include <sys/resource.h>  /* for struct rusage */
    112      1.1  mrg #endif
    113      1.1  mrg 
    114      1.1  mrg #if HAVE_SYS_PROCESSOR_H
    115      1.1  mrg #include <sys/processor.h>  /* for solaris processor_info_t */
    116      1.1  mrg #endif
    117      1.1  mrg 
    118      1.1  mrg /* On AIX 5.1 with gcc 2.9-aix51-020209 in -maix64 mode, <sys/sysinfo.h>
    119      1.1  mrg    gets an error about "fill" in "struct cpuinfo" having a negative size,
    120      1.1  mrg    apparently due to __64BIT_KERNEL not being defined because _KERNEL is not
    121      1.1  mrg    defined.  Avoid this file if we don't actually need it, which we don't on
    122      1.1  mrg    AIX since there's no getsysinfo there.  */
    123      1.1  mrg #if HAVE_SYS_SYSINFO_H && HAVE_GETSYSINFO
    124      1.1  mrg #include <sys/sysinfo.h>  /* for OSF getsysinfo */
    125      1.1  mrg #endif
    126      1.1  mrg 
    127      1.1  mrg #if HAVE_MACHINE_HAL_SYSINFO_H
    128      1.1  mrg #include <machine/hal_sysinfo.h>  /* for OSF GSI_CPU_INFO, struct cpu_info */
    129      1.1  mrg #endif
    130      1.1  mrg 
    131      1.1  mrg /* Remove definitions from NetBSD <sys/param.h>, to avoid conflicts with
    132      1.1  mrg    gmp-impl.h. */
    133      1.1  mrg #ifdef MIN
    134      1.1  mrg #undef MIN
    135      1.1  mrg #endif
    136      1.1  mrg #ifdef MAX
    137      1.1  mrg #undef MAX
    138      1.1  mrg #endif
    139      1.1  mrg 
    140      1.1  mrg #include "gmp-impl.h"
    141      1.1  mrg 
    142      1.1  mrg #include "speed.h"
    143      1.1  mrg 
    144      1.1  mrg 
    145      1.1  mrg #define HELP(str)                       \
    146      1.1  mrg   if (help)                             \
    147      1.1  mrg     {                                   \
    148      1.1  mrg       printf ("    - %s\n", str);       \
    149      1.1  mrg       return 0;                         \
    150      1.1  mrg     }
    151      1.1  mrg 
    152      1.1  mrg 
    153      1.1  mrg /* GMP_CPU_FREQUENCY environment variable.  Should be in Hertz and can be
    154      1.1  mrg    floating point, for example "450e6". */
    155      1.1  mrg static int
    156      1.1  mrg freq_environment (int help)
    157      1.1  mrg {
    158      1.1  mrg   char  *e;
    159      1.1  mrg 
    160      1.1  mrg   HELP ("environment variable GMP_CPU_FREQUENCY (in Hertz)");
    161      1.1  mrg 
    162      1.1  mrg   e = getenv ("GMP_CPU_FREQUENCY");
    163      1.1  mrg   if (e == NULL)
    164      1.1  mrg     return 0;
    165      1.1  mrg 
    166      1.1  mrg   speed_cycletime = 1.0 / atof (e);
    167      1.1  mrg 
    168      1.1  mrg   if (speed_option_verbose)
    169      1.1  mrg     printf ("Using GMP_CPU_FREQUENCY %.2f for cycle time %.3g\n",
    170      1.1  mrg             atof (e), speed_cycletime);
    171      1.1  mrg 
    172      1.1  mrg   return 1;
    173      1.1  mrg }
    174      1.1  mrg 
    175      1.1  mrg 
    176      1.1  mrg /* getsysinfo is available on OSF, or 4.0 and up at least.
    177      1.1  mrg    The man page (on 4.0) suggests a 0 return indicates information not
    178      1.1  mrg    available, but that seems to be the normal return for GSI_CPU_INFO.  */
    179      1.1  mrg static int
    180      1.1  mrg freq_getsysinfo (int help)
    181      1.1  mrg {
    182      1.1  mrg #if HAVE_GETSYSINFO
    183      1.1  mrg   struct cpu_info  c;
    184      1.1  mrg   int              start;
    185      1.1  mrg 
    186      1.1  mrg   HELP ("getsysinfo() GSI_CPU_INFO");
    187      1.1  mrg 
    188      1.1  mrg   start = 0;
    189      1.1  mrg   if (getsysinfo (GSI_CPU_INFO, (caddr_t) &c, sizeof (c),
    190      1.1  mrg                   &start, NULL, NULL) != -1)
    191      1.1  mrg     {
    192      1.1  mrg       speed_cycletime = 1e-6 / (double) c.mhz;
    193      1.1  mrg       if (speed_option_verbose)
    194      1.1  mrg         printf ("Using getsysinfo() GSI_CPU_INFO %u for cycle time %.3g\n",
    195      1.1  mrg                 c.mhz, speed_cycletime);
    196      1.1  mrg       return 1;
    197      1.1  mrg     }
    198      1.1  mrg #endif
    199      1.1  mrg   return 0;
    200      1.1  mrg }
    201      1.1  mrg 
    202      1.1  mrg 
    203      1.1  mrg /* In HPUX 10 and up, pstat_getprocessor() psp_iticksperclktick is the
    204      1.1  mrg    number of CPU cycles (ie. the CR16 register) per CLK_TCK.  HPUX 9 doesn't
    205      1.1  mrg    have that field in pst_processor though, and has no apparent
    206      1.1  mrg    equivalent.  */
    207      1.1  mrg 
    208      1.1  mrg static int
    209      1.1  mrg freq_pstat_getprocessor (int help)
    210      1.1  mrg {
    211      1.1  mrg #if HAVE_PSTAT_GETPROCESSOR && HAVE_PSP_ITICKSPERCLKTICK
    212      1.1  mrg   struct pst_processor  p;
    213      1.1  mrg 
    214      1.1  mrg   HELP ("pstat_getprocessor() psp_iticksperclktick");
    215      1.1  mrg 
    216      1.1  mrg   if (pstat_getprocessor (&p, sizeof(p), 1, 0) != -1)
    217      1.1  mrg     {
    218      1.1  mrg       long  c = clk_tck();
    219      1.1  mrg       speed_cycletime = 1.0 / (c * p.psp_iticksperclktick);
    220      1.1  mrg       if (speed_option_verbose)
    221      1.1  mrg         printf ("Using pstat_getprocessor() psp_iticksperclktick %lu and clk_tck %ld for cycle time %.3g\n",
    222      1.1  mrg                 (unsigned long) p.psp_iticksperclktick, c,
    223      1.1  mrg                 speed_cycletime);
    224      1.1  mrg       return 1;
    225      1.1  mrg     }
    226      1.1  mrg #endif
    227      1.1  mrg   return 0;
    228      1.1  mrg }
    229      1.1  mrg 
    230      1.1  mrg 
    231      1.1  mrg /* i386 FreeBSD 2.2.8 sysctlbyname machdep.i586_freq is in Hertz.
    232      1.1  mrg    There's no obvious defines available to get this from plain sysctl.  */
    233      1.1  mrg static int
    234      1.1  mrg freq_sysctlbyname_i586_freq (int help)
    235      1.1  mrg {
    236      1.1  mrg #if HAVE_SYSCTLBYNAME
    237      1.1  mrg   unsigned  val;
    238      1.1  mrg   size_t    size;
    239      1.1  mrg 
    240      1.1  mrg   HELP ("sysctlbyname() machdep.i586_freq");
    241      1.1  mrg 
    242      1.1  mrg   size = sizeof(val);
    243      1.1  mrg   if (sysctlbyname ("machdep.i586_freq", &val, &size, NULL, 0) == 0
    244      1.1  mrg       && size == sizeof(val))
    245      1.1  mrg     {
    246      1.1  mrg       speed_cycletime = 1.0 / (double) val;
    247      1.1  mrg       if (speed_option_verbose)
    248      1.1  mrg         printf ("Using sysctlbyname() machdep.i586_freq %u for cycle time %.3g\n",
    249      1.1  mrg                 val, speed_cycletime);
    250      1.1  mrg       return 1;
    251      1.1  mrg     }
    252      1.1  mrg #endif
    253      1.1  mrg   return 0;
    254      1.1  mrg }
    255      1.1  mrg 
    256      1.1  mrg 
    257      1.1  mrg /* i368 FreeBSD 3.3 sysctlbyname machdep.tsc_freq is in Hertz.
    258      1.1  mrg    There's no obvious defines to get this from plain sysctl.  */
    259      1.1  mrg 
    260      1.1  mrg static int
    261      1.1  mrg freq_sysctlbyname_tsc_freq (int help)
    262      1.1  mrg {
    263      1.1  mrg #if HAVE_SYSCTLBYNAME
    264      1.1  mrg   unsigned  val;
    265      1.1  mrg   size_t    size;
    266      1.1  mrg 
    267      1.1  mrg   HELP ("sysctlbyname() machdep.tsc_freq");
    268      1.1  mrg 
    269      1.1  mrg   size = sizeof(val);
    270      1.1  mrg   if (sysctlbyname ("machdep.tsc_freq", &val, &size, NULL, 0) == 0
    271      1.1  mrg       && size == sizeof(val))
    272      1.1  mrg     {
    273      1.1  mrg       speed_cycletime = 1.0 / (double) val;
    274      1.1  mrg       if (speed_option_verbose)
    275      1.1  mrg         printf ("Using sysctlbyname() machdep.tsc_freq %u for cycle time %.3g\n",
    276      1.1  mrg                 val, speed_cycletime);
    277      1.1  mrg       return 1;
    278      1.1  mrg     }
    279      1.1  mrg #endif
    280      1.1  mrg   return 0;
    281      1.1  mrg }
    282      1.1  mrg 
    283      1.1  mrg 
    284      1.1  mrg /* Apple powerpc Darwin 1.3 sysctl hw.cpufrequency is in hertz.  For some
    285      1.1  mrg    reason only seems to be available from sysctl(), not sysctlbyname().  */
    286      1.1  mrg 
    287      1.1  mrg static int
    288      1.1  mrg freq_sysctl_hw_cpufrequency (int help)
    289      1.1  mrg {
    290      1.1  mrg #if HAVE_SYSCTL && defined (CTL_HW) && defined (HW_CPU_FREQ)
    291      1.1  mrg   int       mib[2];
    292      1.1  mrg   unsigned  val;
    293      1.1  mrg   size_t    size;
    294      1.1  mrg 
    295      1.1  mrg   HELP ("sysctl() hw.cpufrequency");
    296      1.1  mrg 
    297      1.1  mrg   mib[0] = CTL_HW;
    298      1.1  mrg   mib[1] = HW_CPU_FREQ;
    299      1.1  mrg   size = sizeof(val);
    300      1.1  mrg   if (sysctl (mib, 2, &val, &size, NULL, 0) == 0)
    301      1.1  mrg     {
    302      1.1  mrg       speed_cycletime = 1.0 / (double) val;
    303      1.1  mrg       if (speed_option_verbose)
    304      1.1  mrg         printf ("Using sysctl() hw.cpufrequency %u for cycle time %.3g\n",
    305      1.1  mrg                 val, speed_cycletime);
    306      1.1  mrg       return 1;
    307      1.1  mrg     }
    308      1.1  mrg #endif
    309      1.1  mrg   return 0;
    310      1.1  mrg }
    311      1.1  mrg 
    312      1.1  mrg 
    313      1.1  mrg /* The following ssyctl hw.model strings have been observed,
    314      1.1  mrg 
    315      1.1  mrg        Alpha FreeBSD 4.1:   Digital AlphaPC 164LX 599 MHz
    316      1.1  mrg        NetBSD 1.4:          Digital AlphaPC 164LX 599 MHz
    317      1.1  mrg        NetBSD 1.6.1:        CY7C601 @ 40 MHz, TMS390C602A FPU
    318      1.1  mrg 
    319      1.1  mrg    NetBSD 1.4 doesn't seem to have sysctlbyname, so sysctl() is used.  */
    320      1.1  mrg 
    321      1.1  mrg static int
    322      1.1  mrg freq_sysctl_hw_model (int help)
    323      1.1  mrg {
    324      1.1  mrg #if HAVE_SYSCTL && defined (CTL_HW) && defined (HW_MODEL)
    325      1.1  mrg   int       mib[2];
    326      1.1  mrg   char      str[128];
    327      1.1  mrg   unsigned  val;
    328      1.1  mrg   size_t    size;
    329      1.1  mrg   char      *p;
    330      1.1  mrg   int       end;
    331      1.1  mrg 
    332      1.1  mrg   HELP ("sysctl() hw.model");
    333      1.1  mrg 
    334      1.1  mrg   mib[0] = CTL_HW;
    335      1.1  mrg   mib[1] = HW_MODEL;
    336      1.1  mrg   size = sizeof(str);
    337      1.1  mrg   if (sysctl (mib, 2, str, &size, NULL, 0) == 0)
    338      1.1  mrg     {
    339      1.1  mrg       for (p = str; *p != '\0'; p++)
    340      1.1  mrg         {
    341      1.1  mrg           end = 0;
    342      1.1  mrg           if (sscanf (p, "%u MHz%n", &val, &end) == 1 && end != 0)
    343      1.1  mrg             {
    344      1.1  mrg               speed_cycletime = 1e-6 / (double) val;
    345      1.1  mrg               if (speed_option_verbose)
    346      1.1  mrg                 printf ("Using sysctl() hw.model %u for cycle time %.3g\n",
    347      1.1  mrg                         val, speed_cycletime);
    348      1.1  mrg               return 1;
    349      1.1  mrg             }
    350      1.1  mrg         }
    351      1.1  mrg     }
    352      1.1  mrg #endif
    353      1.1  mrg   return 0;
    354      1.1  mrg }
    355      1.1  mrg 
    356      1.1  mrg 
    357      1.1  mrg /* /proc/cpuinfo for linux kernel.
    358      1.1  mrg 
    359      1.1  mrg    Linux doesn't seem to have any system call to get the CPU frequency, at
    360      1.1  mrg    least not in 2.0.x or 2.2.x, so it's necessary to read /proc/cpuinfo.
    361      1.1  mrg 
    362      1.1  mrg    i386 2.0.36 - "bogomips" is the CPU frequency.
    363      1.1  mrg 
    364      1.1  mrg    i386 2.2.13 - has both "cpu MHz" and "bogomips", and it's "cpu MHz" which
    365      1.1  mrg                  is the frequency.
    366      1.1  mrg 
    367      1.1  mrg    alpha 2.2.5 - "cycle frequency [Hz]" seems to be right, "BogoMIPS" is
    368      1.1  mrg                  very slightly different.
    369      1.1  mrg 
    370      1.1  mrg    alpha 2.2.18pre21 - "cycle frequency [Hz]" is 0 on at least one system,
    371      1.1  mrg                  "BogoMIPS" seems near enough.
    372      1.1  mrg 
    373      1.1  mrg    powerpc 2.2.19 - "clock" is the frequency, bogomips is something weird
    374      1.1  mrg   */
    375      1.1  mrg 
    376      1.1  mrg static int
    377      1.1  mrg freq_proc_cpuinfo (int help)
    378      1.1  mrg {
    379      1.1  mrg   FILE    *fp;
    380      1.1  mrg   char    buf[128];
    381      1.1  mrg   double  val;
    382      1.1  mrg   int     ret = 0;
    383      1.1  mrg   int     end;
    384      1.1  mrg 
    385      1.1  mrg   HELP ("linux kernel /proc/cpuinfo file, cpu MHz or bogomips");
    386      1.1  mrg 
    387      1.1  mrg   if ((fp = fopen ("/proc/cpuinfo", "r")) != NULL)
    388      1.1  mrg     {
    389      1.1  mrg       while (fgets (buf, sizeof (buf), fp) != NULL)
    390      1.1  mrg         {
    391      1.1  mrg           if (sscanf (buf, "cycle frequency [Hz]    : %lf", &val) == 1
    392      1.1  mrg               && val != 0.0)
    393      1.1  mrg             {
    394      1.1  mrg               speed_cycletime = 1.0 / val;
    395      1.1  mrg               if (speed_option_verbose)
    396      1.1  mrg                 printf ("Using /proc/cpuinfo \"cycle frequency\" %.2f for cycle time %.3g\n", val, speed_cycletime);
    397      1.1  mrg               ret = 1;
    398      1.1  mrg               break;
    399      1.1  mrg             }
    400      1.1  mrg           if (sscanf (buf, "cpu MHz : %lf\n", &val) == 1)
    401      1.1  mrg             {
    402      1.1  mrg               speed_cycletime = 1e-6 / val;
    403      1.1  mrg               if (speed_option_verbose)
    404      1.1  mrg                 printf ("Using /proc/cpuinfo \"cpu MHz\" %.2f for cycle time %.3g\n", val, speed_cycletime);
    405      1.1  mrg               ret = 1;
    406      1.1  mrg               break;
    407      1.1  mrg             }
    408      1.1  mrg           end = 0;
    409      1.1  mrg           if (sscanf (buf, "clock : %lfMHz\n%n", &val, &end) == 1 && end != 0)
    410      1.1  mrg             {
    411      1.1  mrg               speed_cycletime = 1e-6 / val;
    412      1.1  mrg               if (speed_option_verbose)
    413      1.1  mrg                 printf ("Using /proc/cpuinfo \"clock\" %.2f for cycle time %.3g\n", val, speed_cycletime);
    414      1.1  mrg               ret = 1;
    415      1.1  mrg               break;
    416      1.1  mrg             }
    417      1.1  mrg           if (sscanf (buf, "bogomips : %lf\n", &val) == 1
    418      1.1  mrg               || sscanf (buf, "BogoMIPS : %lf\n", &val) == 1)
    419      1.1  mrg             {
    420      1.1  mrg               speed_cycletime = 1e-6 / val;
    421      1.1  mrg               if (speed_option_verbose)
    422      1.1  mrg                 printf ("Using /proc/cpuinfo \"bogomips\" %.2f for cycle time %.3g\n", val, speed_cycletime);
    423      1.1  mrg               ret = 1;
    424      1.1  mrg               break;
    425      1.1  mrg             }
    426      1.1  mrg         }
    427      1.1  mrg       fclose (fp);
    428      1.1  mrg     }
    429      1.1  mrg   return ret;
    430      1.1  mrg }
    431      1.1  mrg 
    432      1.1  mrg 
    433      1.1  mrg /* /bin/sysinfo for SunOS 4.
    434      1.1  mrg    Prints a line like: cpu0 is a "75 MHz TI,TMS390Z55" CPU */
    435      1.1  mrg static int
    436      1.1  mrg freq_sunos_sysinfo (int help)
    437      1.1  mrg {
    438      1.1  mrg   int     ret = 0;
    439      1.1  mrg #if HAVE_POPEN
    440      1.1  mrg   FILE    *fp;
    441      1.1  mrg   char    buf[128];
    442      1.1  mrg   double  val;
    443      1.1  mrg   int     end;
    444      1.1  mrg 
    445      1.1  mrg   HELP ("SunOS /bin/sysinfo program output, cpu0");
    446      1.1  mrg 
    447      1.1  mrg   /* Error messages are sent to /dev/null in case /bin/sysinfo doesn't
    448      1.1  mrg      exist.  The brackets are necessary for some shells. */
    449      1.1  mrg   if ((fp = popen ("(/bin/sysinfo) 2>/dev/null", "r")) != NULL)
    450      1.1  mrg     {
    451      1.1  mrg       while (fgets (buf, sizeof (buf), fp) != NULL)
    452      1.1  mrg         {
    453      1.1  mrg           end = 0;
    454      1.1  mrg           if (sscanf (buf, " cpu0 is a \"%lf MHz%n", &val, &end) == 1
    455      1.1  mrg               && end != 0)
    456      1.1  mrg             {
    457      1.1  mrg               speed_cycletime = 1e-6 / val;
    458      1.1  mrg               if (speed_option_verbose)
    459      1.1  mrg                 printf ("Using /bin/sysinfo \"cpu0 MHz\" %.2f for cycle time %.3g\n", val, speed_cycletime);
    460      1.1  mrg               ret = 1;
    461      1.1  mrg               break;
    462      1.1  mrg             }
    463      1.1  mrg         }
    464      1.1  mrg       pclose (fp);
    465      1.1  mrg     }
    466      1.1  mrg #endif
    467      1.1  mrg   return ret;
    468      1.1  mrg }
    469      1.1  mrg 
    470      1.1  mrg 
    471      1.1  mrg /* "/etc/hw -r cpu" for SCO OpenUnix 8, printing a line like
    472  1.1.1.2  mrg 	The speed of the CPU is approximately 450MHz
    473      1.1  mrg  */
    474      1.1  mrg static int
    475      1.1  mrg freq_sco_etchw (int help)
    476      1.1  mrg {
    477      1.1  mrg   int     ret = 0;
    478      1.1  mrg #if HAVE_POPEN
    479      1.1  mrg   FILE    *fp;
    480      1.1  mrg   char    buf[128];
    481      1.1  mrg   double  val;
    482      1.1  mrg   int     end;
    483      1.1  mrg 
    484      1.1  mrg   HELP ("SCO /etc/hw program output");
    485      1.1  mrg 
    486      1.1  mrg   /* Error messages are sent to /dev/null in case /etc/hw doesn't exist.
    487      1.1  mrg      The brackets are necessary for some shells. */
    488      1.1  mrg   if ((fp = popen ("(/etc/hw -r cpu) 2>/dev/null", "r")) != NULL)
    489      1.1  mrg     {
    490      1.1  mrg       while (fgets (buf, sizeof (buf), fp) != NULL)
    491      1.1  mrg         {
    492      1.1  mrg           end = 0;
    493  1.1.1.2  mrg           if (sscanf (buf, " The speed of the CPU is approximately %lfMHz%n",
    494      1.1  mrg                       &val, &end) == 1 && end != 0)
    495      1.1  mrg             {
    496      1.1  mrg               speed_cycletime = 1e-6 / val;
    497      1.1  mrg               if (speed_option_verbose)
    498      1.1  mrg                 printf ("Using /etc/hw %.2f MHz, for cycle time %.3g\n",
    499      1.1  mrg                         val, speed_cycletime);
    500      1.1  mrg               ret = 1;
    501      1.1  mrg               break;
    502      1.1  mrg             }
    503      1.1  mrg         }
    504      1.1  mrg       pclose (fp);
    505      1.1  mrg     }
    506      1.1  mrg #endif
    507      1.1  mrg   return ret;
    508      1.1  mrg }
    509      1.1  mrg 
    510      1.1  mrg 
    511      1.1  mrg /* attr_get("/hw/cpunum/0",INFO_LBL_DETAIL_INVENT) ic_cpu_info.cpufq for
    512      1.1  mrg    IRIX 6.5.  Past versions don't have INFO_LBL_DETAIL_INVENT,
    513      1.1  mrg    invent_cpuinfo_t, or /hw/cpunum/0.
    514      1.1  mrg 
    515      1.1  mrg    The same information is available from the "hinv -c processor" command,
    516      1.1  mrg    but it seems better to make a system call where possible. */
    517      1.1  mrg 
    518      1.1  mrg static int
    519      1.1  mrg freq_attr_get_invent (int help)
    520      1.1  mrg {
    521      1.1  mrg   int     ret = 0;
    522      1.1  mrg #if HAVE_ATTR_GET && HAVE_INVENT_H && defined (INFO_LBL_DETAIL_INVENT)
    523      1.1  mrg   invent_cpuinfo_t  inv;
    524      1.1  mrg   int               len, val;
    525      1.1  mrg 
    526      1.1  mrg   HELP ("attr_get(\"/hw/cpunum/0\") ic_cpu_info.cpufq");
    527      1.1  mrg 
    528      1.1  mrg   len = sizeof (inv);
    529      1.1  mrg   if (attr_get ("/hw/cpunum/0", INFO_LBL_DETAIL_INVENT,
    530      1.1  mrg                 (char *) &inv, &len, 0) == 0
    531      1.1  mrg       && len == sizeof (inv)
    532      1.1  mrg       && inv.ic_gen.ig_invclass == INV_PROCESSOR)
    533      1.1  mrg     {
    534      1.1  mrg       val = inv.ic_cpu_info.cpufq;
    535      1.1  mrg       speed_cycletime = 1e-6 / val;
    536      1.1  mrg       if (speed_option_verbose)
    537      1.1  mrg         printf ("Using attr_get(\"/hw/cpunum/0\") ic_cpu_info.cpufq %d MHz for cycle time %.3g\n", val, speed_cycletime);
    538      1.1  mrg       ret = 1;
    539      1.1  mrg     }
    540      1.1  mrg #endif
    541      1.1  mrg   return ret;
    542      1.1  mrg }
    543      1.1  mrg 
    544      1.1  mrg 
    545      1.1  mrg /* FreeBSD on i386 gives a line like the following at bootup, and which can
    546      1.1  mrg    be read back from /var/run/dmesg.boot.
    547      1.1  mrg 
    548      1.1  mrg        CPU: AMD Athlon(tm) Processor (755.29-MHz 686-class CPU)
    549      1.1  mrg        CPU: Pentium 4 (1707.56-MHz 686-class CPU)
    550      1.1  mrg        CPU: i486 DX4 (486-class CPU)
    551      1.1  mrg 
    552      1.1  mrg    This is useful on FreeBSD 4.x, where there's no sysctl machdep.tsc_freq
    553      1.1  mrg    or machdep.i586_freq.
    554      1.1  mrg 
    555      1.1  mrg    It's better to use /var/run/dmesg.boot than to run /sbin/dmesg, since the
    556      1.1  mrg    latter prints the current system message buffer, which is a limited size
    557      1.1  mrg    and can wrap around if the system is up for a long time.  */
    558      1.1  mrg 
    559      1.1  mrg static int
    560      1.1  mrg freq_bsd_dmesg (int help)
    561      1.1  mrg {
    562      1.1  mrg   FILE    *fp;
    563      1.1  mrg   char    buf[256], *p;
    564      1.1  mrg   double  val;
    565      1.1  mrg   int     ret = 0;
    566      1.1  mrg   int     end;
    567      1.1  mrg 
    568      1.1  mrg   HELP ("BSD /var/run/dmesg.boot file");
    569      1.1  mrg 
    570      1.1  mrg   if ((fp = fopen ("/var/run/dmesg.boot", "r")) != NULL)
    571      1.1  mrg     {
    572      1.1  mrg       while (fgets (buf, sizeof (buf), fp) != NULL)
    573      1.1  mrg         {
    574      1.1  mrg           if (memcmp (buf, "CPU:", 4) == 0)
    575      1.1  mrg             {
    576      1.1  mrg               for (p = buf; *p != '\0'; p++)
    577      1.1  mrg                 {
    578      1.1  mrg                   end = 0;
    579      1.1  mrg                   if (sscanf (p, "(%lf-MHz%n", &val, &end) == 1 && end != 0)
    580      1.1  mrg                     {
    581      1.1  mrg                       speed_cycletime = 1e-6 / val;
    582      1.1  mrg                       if (speed_option_verbose)
    583      1.1  mrg                         printf ("Using /var/run/dmesg.boot CPU: %.2f MHz for cycle time %.3g\n", val, speed_cycletime);
    584      1.1  mrg                       ret = 1;
    585      1.1  mrg                       break;
    586      1.1  mrg                     }
    587      1.1  mrg                 }
    588      1.1  mrg             }
    589      1.1  mrg         }
    590      1.1  mrg       fclose (fp);
    591      1.1  mrg     }
    592      1.1  mrg   return ret;
    593      1.1  mrg }
    594      1.1  mrg 
    595      1.1  mrg 
    596      1.1  mrg /* "hinv -c processor" for IRIX.  The following lines have been seen,
    597      1.1  mrg 
    598      1.1  mrg               1 150 MHZ IP20 Processor
    599      1.1  mrg               2 195 MHZ IP27 Processors
    600      1.1  mrg               Processor 0: 500 MHZ IP35
    601      1.1  mrg 
    602      1.1  mrg    This information is available from attr_get() on IRIX 6.5 (see above),
    603      1.1  mrg    but on IRIX 6.2 it's not clear where to look, so fall back on
    604      1.1  mrg    parsing.  */
    605      1.1  mrg 
    606      1.1  mrg static int
    607      1.1  mrg freq_irix_hinv (int help)
    608      1.1  mrg {
    609      1.1  mrg   int     ret = 0;
    610      1.1  mrg #if HAVE_POPEN
    611      1.1  mrg   FILE    *fp;
    612      1.1  mrg   char    buf[128];
    613      1.1  mrg   double  val;
    614      1.1  mrg   int     nproc, end;
    615      1.1  mrg 
    616      1.1  mrg   HELP ("IRIX \"hinv -c processor\" output");
    617      1.1  mrg 
    618      1.1  mrg   /* Error messages are sent to /dev/null in case hinv doesn't exist.  The
    619      1.1  mrg      brackets are necessary for some shells. */
    620      1.1  mrg   if ((fp = popen ("(hinv -c processor) 2>/dev/null", "r")) != NULL)
    621      1.1  mrg     {
    622      1.1  mrg       while (fgets (buf, sizeof (buf), fp) != NULL)
    623      1.1  mrg         {
    624      1.1  mrg           end = 0;
    625      1.1  mrg           if (sscanf (buf, "Processor 0: %lf MHZ%n", &val, &end) == 1
    626      1.1  mrg               && end != 0)
    627      1.1  mrg             {
    628      1.1  mrg             found:
    629      1.1  mrg               speed_cycletime = 1e-6 / val;
    630      1.1  mrg               if (speed_option_verbose)
    631      1.1  mrg                 printf ("Using hinv -c processor \"%.2f MHZ\" for cycle time %.3g\n", val, speed_cycletime);
    632      1.1  mrg               ret = 1;
    633      1.1  mrg               break;
    634      1.1  mrg             }
    635      1.1  mrg           end = 0;
    636      1.1  mrg           if (sscanf (buf, "%d %lf MHZ%n", &nproc, &val, &end) == 2
    637      1.1  mrg               && end != 0)
    638      1.1  mrg             goto found;
    639      1.1  mrg         }
    640      1.1  mrg       pclose (fp);
    641      1.1  mrg     }
    642      1.1  mrg #endif
    643      1.1  mrg   return ret;
    644      1.1  mrg }
    645      1.1  mrg 
    646      1.1  mrg 
    647      1.1  mrg /* processor_info() for Solaris.  "psrinfo" is the command-line interface to
    648      1.1  mrg    this.  "prtconf -vp" gives similar information.
    649      1.1  mrg 
    650      1.1  mrg    Apple Darwin has a processor_info, but in an incompatible style.  It
    651      1.1  mrg    doesn't have <sys/processor.h>, so test for that.  */
    652      1.1  mrg 
    653      1.1  mrg static int
    654      1.1  mrg freq_processor_info (int help)
    655      1.1  mrg {
    656      1.1  mrg #if HAVE_PROCESSOR_INFO && HAVE_SYS_PROCESSOR_H
    657      1.1  mrg   processor_info_t  p;
    658      1.1  mrg   int  i, n, mhz = 0;
    659      1.1  mrg 
    660      1.1  mrg   HELP ("processor_info() pi_clock");
    661      1.1  mrg 
    662      1.1  mrg   n = sysconf (_SC_NPROCESSORS_CONF);
    663      1.1  mrg   for (i = 0; i < n; i++)
    664      1.1  mrg     {
    665      1.1  mrg       if (processor_info (i, &p) != 0)
    666      1.1  mrg         continue;
    667      1.1  mrg       if (p.pi_state != P_ONLINE)
    668      1.1  mrg         continue;
    669      1.1  mrg 
    670      1.1  mrg       if (mhz != 0 && p.pi_clock != mhz)
    671      1.1  mrg         {
    672      1.1  mrg           fprintf (stderr,
    673      1.1  mrg                    "freq_processor_info(): There's more than one CPU and they have different clock speeds\n");
    674      1.1  mrg           return 0;
    675      1.1  mrg         }
    676      1.1  mrg 
    677      1.1  mrg       mhz = p.pi_clock;
    678      1.1  mrg     }
    679      1.1  mrg 
    680      1.1  mrg   speed_cycletime = 1.0e-6 / (double) mhz;
    681      1.1  mrg 
    682      1.1  mrg   if (speed_option_verbose)
    683      1.1  mrg     printf ("Using processor_info() %d mhz for cycle time %.3g\n",
    684      1.1  mrg             mhz, speed_cycletime);
    685      1.1  mrg   return 1;
    686      1.1  mrg 
    687      1.1  mrg #else
    688      1.1  mrg   return 0;
    689      1.1  mrg #endif
    690      1.1  mrg }
    691      1.1  mrg 
    692      1.1  mrg 
    693      1.1  mrg #if HAVE_SPEED_CYCLECOUNTER && HAVE_GETTIMEOFDAY
    694      1.1  mrg static double
    695      1.1  mrg freq_measure_gettimeofday_one (void)
    696      1.1  mrg {
    697      1.1  mrg #define call_gettimeofday(t)   gettimeofday (&(t), NULL)
    698      1.1  mrg #define timeval_tv_sec(t)      ((t).tv_sec)
    699      1.1  mrg #define timeval_tv_usec(t)     ((t).tv_usec)
    700      1.1  mrg   FREQ_MEASURE_ONE ("gettimeofday", struct timeval,
    701      1.1  mrg                     call_gettimeofday, speed_cyclecounter,
    702      1.1  mrg                     timeval_tv_sec, timeval_tv_usec);
    703      1.1  mrg }
    704      1.1  mrg #endif
    705      1.1  mrg 
    706      1.1  mrg #if HAVE_SPEED_CYCLECOUNTER && HAVE_GETRUSAGE
    707      1.1  mrg static double
    708      1.1  mrg freq_measure_getrusage_one (void)
    709      1.1  mrg {
    710      1.1  mrg #define call_getrusage(t)   getrusage (0, &(t))
    711      1.1  mrg #define rusage_tv_sec(t)    ((t).ru_utime.tv_sec)
    712      1.1  mrg #define rusage_tv_usec(t)   ((t).ru_utime.tv_usec)
    713      1.1  mrg   FREQ_MEASURE_ONE ("getrusage", struct rusage,
    714      1.1  mrg                     call_getrusage, speed_cyclecounter,
    715      1.1  mrg                     rusage_tv_sec, rusage_tv_usec);
    716      1.1  mrg }
    717      1.1  mrg #endif
    718      1.1  mrg 
    719      1.1  mrg 
    720      1.1  mrg /* MEASURE_MATCH is how many readings within MEASURE_TOLERANCE of each other
    721      1.1  mrg    are required.  This must be at least 2.  */
    722      1.1  mrg #define MEASURE_MAX_ATTEMPTS   20
    723      1.1  mrg #define MEASURE_TOLERANCE      1.005  /* 0.5% */
    724      1.1  mrg #define MEASURE_MATCH          3
    725      1.1  mrg 
    726      1.1  mrg double
    727      1.1  mrg freq_measure (const char *name, double (*one) (void))
    728      1.1  mrg {
    729      1.1  mrg   double  t[MEASURE_MAX_ATTEMPTS];
    730      1.1  mrg   int     i, j;
    731      1.1  mrg 
    732      1.1  mrg   for (i = 0; i < numberof (t); i++)
    733      1.1  mrg     {
    734      1.1  mrg       t[i] = (*one) ();
    735      1.1  mrg 
    736      1.1  mrg       qsort (t, i+1, sizeof(t[0]), (qsort_function_t) double_cmp_ptr);
    737      1.1  mrg       if (speed_option_verbose >= 3)
    738      1.1  mrg         for (j = 0; j <= i; j++)
    739      1.1  mrg           printf ("   t[%d] is %.6g\n", j, t[j]);
    740      1.1  mrg 
    741      1.1  mrg       for (j = 0; j+MEASURE_MATCH-1 <= i; j++)
    742      1.1  mrg         {
    743      1.1  mrg           if (t[j+MEASURE_MATCH-1] <= t[j] * MEASURE_TOLERANCE)
    744      1.1  mrg             {
    745      1.1  mrg               /* use the average of the range found */
    746      1.1  mrg                 return (t[j+MEASURE_MATCH-1] + t[j]) / 2.0;
    747      1.1  mrg             }
    748      1.1  mrg         }
    749      1.1  mrg     }
    750      1.1  mrg   return -1.0;
    751      1.1  mrg }
    752      1.1  mrg 
    753      1.1  mrg static int
    754      1.1  mrg freq_measure_getrusage (int help)
    755      1.1  mrg {
    756      1.1  mrg #if HAVE_SPEED_CYCLECOUNTER && HAVE_GETRUSAGE
    757      1.1  mrg   double  cycletime;
    758      1.1  mrg 
    759      1.1  mrg   if (! getrusage_microseconds_p ())
    760      1.1  mrg     return 0;
    761      1.1  mrg   if (! cycles_works_p ())
    762      1.1  mrg     return 0;
    763      1.1  mrg 
    764      1.1  mrg   HELP ("cycle counter measured with microsecond getrusage()");
    765      1.1  mrg 
    766      1.1  mrg   cycletime = freq_measure ("getrusage", freq_measure_getrusage_one);
    767      1.1  mrg   if (cycletime == -1.0)
    768      1.1  mrg     return 0;
    769      1.1  mrg 
    770      1.1  mrg   speed_cycletime = cycletime;
    771      1.1  mrg   if (speed_option_verbose)
    772      1.1  mrg     printf ("Using getrusage() measured cycle counter %.4g (%.2f MHz)\n",
    773      1.1  mrg             speed_cycletime, 1e-6/speed_cycletime);
    774      1.1  mrg   return 1;
    775      1.1  mrg 
    776      1.1  mrg #else
    777      1.1  mrg   return 0;
    778      1.1  mrg #endif
    779      1.1  mrg }
    780      1.1  mrg 
    781      1.1  mrg static int
    782      1.1  mrg freq_measure_gettimeofday (int help)
    783      1.1  mrg {
    784      1.1  mrg #if HAVE_SPEED_CYCLECOUNTER && HAVE_GETTIMEOFDAY
    785      1.1  mrg   double  cycletime;
    786      1.1  mrg 
    787      1.1  mrg   if (! gettimeofday_microseconds_p ())
    788      1.1  mrg     return 0;
    789      1.1  mrg   if (! cycles_works_p ())
    790      1.1  mrg     return 0;
    791      1.1  mrg 
    792      1.1  mrg   HELP ("cycle counter measured with microsecond gettimeofday()");
    793      1.1  mrg 
    794      1.1  mrg   cycletime = freq_measure ("gettimeofday", freq_measure_gettimeofday_one);
    795      1.1  mrg   if (cycletime == -1.0)
    796      1.1  mrg     return 0;
    797      1.1  mrg 
    798      1.1  mrg   speed_cycletime = cycletime;
    799      1.1  mrg   if (speed_option_verbose)
    800      1.1  mrg     printf ("Using gettimeofday() measured cycle counter %.4g (%.2f MHz)\n",
    801      1.1  mrg             speed_cycletime, 1e-6/speed_cycletime);
    802      1.1  mrg   return 1;
    803      1.1  mrg #else
    804      1.1  mrg   return 0;
    805      1.1  mrg #endif
    806      1.1  mrg }
    807      1.1  mrg 
    808      1.1  mrg 
    809      1.1  mrg /* Each function returns 1 if it succeeds in setting speed_cycletime, or 0
    810      1.1  mrg    if not.
    811      1.1  mrg 
    812      1.1  mrg    In general system call tests are first since they're fast, then file
    813      1.1  mrg    tests, then tests running programs.  Necessary exceptions to this rule
    814      1.1  mrg    are noted.  The measuring is last since it's time consuming, and rather
    815      1.1  mrg    wasteful of cpu.  */
    816      1.1  mrg 
    817      1.1  mrg static int
    818      1.1  mrg freq_all (int help)
    819      1.1  mrg {
    820      1.1  mrg   return
    821      1.1  mrg     /* This should be first, so an environment variable can override
    822      1.1  mrg        anything the system gives. */
    823      1.1  mrg     freq_environment (help)
    824      1.1  mrg 
    825      1.1  mrg     || freq_attr_get_invent (help)
    826      1.1  mrg     || freq_getsysinfo (help)
    827      1.1  mrg     || freq_pstat_getprocessor (help)
    828      1.1  mrg     || freq_sysctl_hw_model (help)
    829      1.1  mrg     || freq_sysctl_hw_cpufrequency (help)
    830      1.1  mrg     || freq_sysctlbyname_i586_freq (help)
    831      1.1  mrg     || freq_sysctlbyname_tsc_freq (help)
    832      1.1  mrg 
    833      1.1  mrg     /* SCO openunix 8 puts a dummy pi_clock==16 in processor_info, so be
    834      1.1  mrg        sure to check /etc/hw before that function. */
    835      1.1  mrg     || freq_sco_etchw (help)
    836      1.1  mrg 
    837      1.1  mrg     || freq_processor_info (help)
    838      1.1  mrg     || freq_proc_cpuinfo (help)
    839      1.1  mrg     || freq_bsd_dmesg (help)
    840      1.1  mrg     || freq_irix_hinv (help)
    841      1.1  mrg     || freq_sunos_sysinfo (help)
    842      1.1  mrg     || freq_measure_getrusage (help)
    843      1.1  mrg     || freq_measure_gettimeofday (help);
    844      1.1  mrg }
    845      1.1  mrg 
    846      1.1  mrg 
    847      1.1  mrg void
    848      1.1  mrg speed_cycletime_init (void)
    849      1.1  mrg {
    850      1.1  mrg   static int  attempted = 0;
    851      1.1  mrg 
    852      1.1  mrg   if (attempted)
    853      1.1  mrg     return;
    854      1.1  mrg   attempted = 1;
    855      1.1  mrg 
    856      1.1  mrg   if (freq_all (0))
    857      1.1  mrg     return;
    858      1.1  mrg 
    859      1.1  mrg   if (speed_option_verbose)
    860      1.1  mrg     printf ("CPU frequency couldn't be determined\n");
    861      1.1  mrg }
    862      1.1  mrg 
    863      1.1  mrg 
    864      1.1  mrg void
    865      1.1  mrg speed_cycletime_fail (const char *str)
    866      1.1  mrg {
    867      1.1  mrg   fprintf (stderr, "Measuring with: %s\n", speed_time_string);
    868      1.1  mrg   fprintf (stderr, "%s,\n", str);
    869      1.1  mrg   fprintf (stderr, "but none of the following are available,\n");
    870      1.1  mrg   freq_all (1);
    871      1.1  mrg   abort ();
    872      1.1  mrg }
    873      1.1  mrg 
    874      1.1  mrg /* speed_time_init leaves speed_cycletime set to either 0.0 or 1.0 when the
    875      1.1  mrg    CPU frequency is unknown.  0.0 is when the time base is in seconds, so
    876      1.1  mrg    that's no good if cycles are wanted.  1.0 is when the time base is in
    877      1.1  mrg    cycles, which conversely is no good if seconds are wanted.  */
    878      1.1  mrg void
    879      1.1  mrg speed_cycletime_need_cycles (void)
    880      1.1  mrg {
    881      1.1  mrg   speed_time_init ();
    882      1.1  mrg   if (speed_cycletime == 0.0)
    883      1.1  mrg     speed_cycletime_fail
    884      1.1  mrg       ("Need to know CPU frequency to give times in cycles");
    885      1.1  mrg }
    886      1.1  mrg void
    887      1.1  mrg speed_cycletime_need_seconds (void)
    888      1.1  mrg {
    889      1.1  mrg   speed_time_init ();
    890      1.1  mrg   if (speed_cycletime == 1.0)
    891      1.1  mrg     speed_cycletime_fail
    892      1.1  mrg       ("Need to know CPU frequency to convert cycles to seconds");
    893      1.1  mrg }
    894