(root)/
binutils-2.41/
gprofng/
testsuite/
gprofng.display/
mttest/
gethrtime.c
       1  /* Copyright (C) 2021-2023 Free Software Foundation, Inc.
       2     Contributed by Oracle.
       3  
       4     This file is part of GNU Binutils.
       5  
       6     This program is free software; you can redistribute it and/or modify
       7     it under the terms of the GNU General Public License as published by
       8     the Free Software Foundation; either version 3, or (at your option)
       9     any later version.
      10  
      11     This program is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14     GNU General Public License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with this program; if not, write to the Free Software
      18     Foundation, 51 Franklin Street - Fifth Floor, Boston,
      19     MA 02110-1301, USA.  */
      20  
      21  #include <time.h>
      22  #include <unistd.h>
      23  #include <string.h>
      24  #include <stdio.h>
      25  #include <stdlib.h>
      26  #include <sys/resource.h>
      27  #include <sys/time.h>
      28  #include <sys/times.h>
      29  #include <limits.h>
      30  
      31  #if defined(sparc) || defined(__sparcv9)
      32  #define SPARC       1
      33  #elif defined(__aarch64__)
      34  #define Aarch64     1
      35  #else
      36  #define Intel       1
      37  #endif
      38  
      39  /* typedef and function prototypes for hi-resolution timers */
      40  typedef long long hrtime_t;
      41  #if defined(__cplusplus)
      42  extern "C"
      43  {
      44  #endif
      45    hrtime_t gethrtime ();
      46    hrtime_t gethrvtime ();
      47    hrtime_t gethrustime ();
      48    hrtime_t gethrpxtime ();
      49    int get_clock_rate ();
      50    int get_ncpus ();
      51  
      52    /* prototype underscore-appended wrappers for Fortran usage */
      53    hrtime_t gethrtime_ ();
      54    hrtime_t gethrustime_ ();
      55    hrtime_t gethrpxtime_ ();
      56    hrtime_t gethrvtime_ ();
      57    int get_clock_rate_ ();
      58  #if defined(__cplusplus)
      59  }
      60  #endif
      61  
      62  /* =============================================================== */
      63  /*
      64   * Below this are the get_clock_rate() and get_ncpus() for all OSs and architectures
      65   */
      66  /* prototypes */
      67  
      68  /* implementation */
      69  static int clock_rate = 0;
      70  static int ncpus = 0;
      71  static char msgbuf[1024];
      72  
      73  int
      74  get_clock_rate (void)
      75  {
      76    /* Linux version -- read /proc/cpuinfo
      77     *	Note the parsing is different on intel-Linux and sparc-Linux
      78     */
      79    FILE *fp = fopen ("/proc/cpuinfo", "r");
      80    if (fp != NULL)
      81      {
      82        char temp[1024];
      83        while (fgets (temp, sizeof (temp), fp) != NULL)
      84          {
      85  #if defined(SPARC)
      86            /* cpu count for SPARC linux -- read from /proc/cpuinfo */
      87            if (strncmp (temp, "ncpus active", 12) == 0)
      88              {
      89                char *val = strchr (temp, ':');
      90                ncpus = val ? atol (val + 1) : 0;
      91              }
      92  #endif
      93  
      94            if (clock_rate == 0)
      95              {
      96                /* pick the first line that gives a CPU clock rate */
      97  #if defined(SPARC)
      98                long long clk;
      99                if (strncmp (temp, "Cpu0ClkTck", 10) == 0)
     100                  {
     101                    char *val = strchr (temp, ':');
     102                    clk = val ? strtoll (val + 1, NULL, 16) : 0;
     103                    clock_rate = (int) (clk / 1000000);
     104                  }
     105  #elif defined(Intel)
     106                if (strncmp (temp, "cpu MHz", 7) == 0)
     107                  {
     108                    char *val = strchr (temp, ':');
     109                    clock_rate = val ? atoi (val + 1) : 0;
     110                  }
     111  #endif
     112              }
     113  
     114            /* did we get a clock rate? */
     115            if (clock_rate != 0)
     116              {
     117  #if defined(SPARC)
     118                /* since we got a cpu count, we can break from the look */
     119                break;
     120  #endif
     121              }
     122  #if defined(Intel)
     123            /* On intel-Linux, count cpus based on "cpu MHz" lines */
     124            if (strncmp (temp, "cpu MHz", 7) == 0)
     125              ncpus++;
     126  #endif
     127          }
     128        fclose (fp);
     129      }
     130  
     131    if (clock_rate != 0)
     132      sprintf (msgbuf, "Clock rate = %d MHz (from reading /proc/cpuinfo) %d CPUs\n", clock_rate, ncpus);
     133  
     134    /* did we get a clock rate? */
     135    if (clock_rate == 0)
     136      {
     137        clock_rate = 1000;
     138        sprintf (msgbuf, "Clock rate = %d MHz (set by default) %d CPUs\n",
     139                 clock_rate, ncpus);
     140      }
     141    return clock_rate;
     142  }
     143  
     144  int
     145  get_ncpus (void)
     146  {
     147    if (clock_rate == 0)
     148      (void) get_clock_rate ();
     149    return ncpus;
     150  }
     151  
     152  
     153  /* gethrpxtime -- per-process user+system CPU time from POSIX times() */
     154  /*  does not include the child user and system CPU time */
     155  hrtime_t
     156  gethrpxtime (void)
     157  {
     158    hrtime_t rc = 0;
     159    static int initted = 0;
     160    static hrtime_t ns_per_tick;
     161    if (!initted)
     162      {
     163        static long ticks_per_sec;
     164        ticks_per_sec = sysconf (_SC_CLK_TCK);
     165        ns_per_tick = 1000000000 / ticks_per_sec;
     166        initted = 1;
     167      }
     168    struct tms mytms = {0};
     169  
     170    clock_t curtick = times (&mytms);
     171    if (curtick == 0) return rc;
     172    rc = (mytms.tms_utime + mytms.tms_stime) * ns_per_tick;
     173    return rc;
     174  }
     175  
     176  /* gethrustime -- per-process user+system CPU time from getrusage() */
     177  hrtime_t
     178  gethrustime (void)
     179  {
     180    struct rusage usage;
     181    if (0 == getrusage (RUSAGE_SELF, &usage))
     182      {
     183        hrtime_t rc = usage.ru_utime.tv_sec /* seconds */
     184                + usage.ru_stime.tv_sec;
     185        rc = usage.ru_utime.tv_usec /* microseconds */
     186                + usage.ru_stime.tv_usec + 1000000 * rc;
     187        rc *= 1000; /* nanoseconds */
     188        return rc;
     189      }
     190    else
     191      return 0;
     192  }
     193  
     194  /*
     195   * Below this are the Linux versions of gethrvtime and gethrtime
     196   */
     197  hrtime_t
     198  gethrtcputime (void)
     199  {
     200    struct timespec tp;
     201    hrtime_t rc = 0;
     202    int r = clock_gettime (CLOCK_THREAD_CPUTIME_ID, &tp);
     203    if (r == 0)
     204      rc = ((hrtime_t) tp.tv_sec) * 1000000000 + (hrtime_t) tp.tv_nsec;
     205    return rc;
     206  }
     207  
     208  /* generic gethrvtime -- uses gethrtcputime */
     209  hrtime_t
     210  gethrvtime ()
     211  {
     212    return gethrtcputime ();
     213  }
     214  
     215  /*
     216   *  CLOCK_MONOTONIC
     217   *  Clock that cannot be set and represents monotonic time since some
     218   *           unspecified starting point.
     219   */
     220  hrtime_t
     221  gethrtime (void)
     222  {
     223    struct timespec tp;
     224    hrtime_t rc = 0;
     225  #ifdef CLOCK_MONOTONIC_RAW
     226    int r = clock_gettime (CLOCK_MONOTONIC_RAW, &tp);
     227  #else
     228    int r = clock_gettime (CLOCK_MONOTONIC, &tp);
     229  #endif
     230  
     231    if (r == 0)
     232      rc = ((hrtime_t) tp.tv_sec) * 1000000000 + (hrtime_t) tp.tv_nsec;
     233    return rc;
     234  }
     235  
     236  /*
     237   * define underscore-appended wrappers for Fortran usage
     238   */
     239  hrtime_t
     240  gethrtime_ ()
     241  {
     242    return gethrtime ();
     243  }
     244  
     245  hrtime_t
     246  gethrustime_ ()
     247  {
     248    return gethrustime ();
     249  }
     250  
     251  hrtime_t
     252  gethrpxtime_ ()
     253  {
     254    return gethrpxtime ();
     255  }
     256  
     257  hrtime_t
     258  gethrvtime_ ()
     259  {
     260    return gethrvtime ();
     261  }
     262  
     263  int
     264  get_clock_rate_ ()
     265  {
     266    return get_clock_rate ();
     267  }
     268  
     269  void
     270  init_micro_acct () { }