(root)/
binutils-2.41/
gprofng/
src/
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 "config.h"
      22  #include <time.h>
      23  #include <unistd.h>
      24  #include <string.h>
      25  #include <stdio.h>
      26  #include <stdlib.h>
      27  #include <sys/resource.h>
      28  
      29  #include "gp-defs.h"
      30  #include "gp-time.h"
      31  
      32  /* =============================================================== */
      33  /*
      34   * Below this are the get_clock_rate() and get_ncpus() for all architectures
      35   */
      36  
      37  static int clock_rate = 0;
      38  static int ncpus = 0;
      39  static char msgbuf[1024];
      40  
      41  int
      42  get_clock_rate (void)
      43  {
      44    /* Linux version -- read /proc/cpuinfo
      45     *	Note the parsing is different on intel-Linux and sparc-Linux
      46     */
      47    FILE *fp = fopen ("/proc/cpuinfo", "r");
      48    if (fp != NULL)
      49      {
      50  
      51        char temp[1024];
      52        while (fgets (temp, sizeof (temp), fp) != NULL)
      53  	{
      54  #if ARCH(SPARC)
      55  	  /* cpu count for SPARC linux -- read from /proc/cpuinfo */
      56  	  if (strncmp (temp, "ncpus active", 12) == 0)
      57  	    {
      58  	      char *val = strchr (temp, ':');
      59  	      ncpus = val ? atol (val + 1) : 0;
      60  	    }
      61  #endif /* ARCH(SPARC) */
      62  
      63  	  if (clock_rate == 0)
      64  	    {
      65  	      /* pick the first line that gives a CPU clock rate */
      66  #if ARCH(SPARC)
      67  	      long long clk;
      68  	      if (strncmp (temp, "Cpu0ClkTck", 10) == 0)
      69  		{
      70  		  char *val = strchr (temp, ':');
      71  		  clk = val ? strtoll (val + 1, NULL, 16) : 0;
      72  		  clock_rate = (int) (clk / 1000000);
      73  		}
      74  #else
      75  	      if (strncmp (temp, "cpu MHz", 7) == 0)
      76  		{
      77  		  char *val = strchr (temp, ':');
      78  		  clock_rate = val ? atoi (val + 1) : 0;
      79  		}
      80  #endif /* ARCH() */
      81  	    }
      82  
      83  	  /* did we get a clock rate? */
      84  	  if (clock_rate != 0)
      85  	    {
      86  #if ARCH(SPARC)
      87  	      /* since we got a cpu count, we can break from the look */
      88  	      break;
      89  #endif /* ARCH(SPARC) */
      90  	    }
      91  #if ARCH(Intel)
      92  	  /* On intel-Linux, count cpus based on "cpu MHz" lines */
      93  	  if (strncmp (temp, "cpu MHz", 7) == 0)
      94  	    ncpus++;
      95  #endif /* ARCH(Intel) */
      96  	}
      97        fclose (fp);
      98      }
      99  
     100    if (clock_rate != 0)
     101      sprintf (msgbuf,
     102  	     "Clock rate = %d MHz (from reading /proc/cpuinfo) %d CPUs\n",
     103  	     clock_rate, ncpus);
     104  
     105    /* did we get a clock rate? */
     106    if (clock_rate == 0)
     107      {
     108        clock_rate = 1000;
     109        sprintf (msgbuf, "Clock rate = %d MHz (set by default) %d CPUs\n",
     110  	       clock_rate, ncpus);
     111      }
     112    return clock_rate;
     113  }
     114  
     115  int
     116  get_ncpus (void)
     117  {
     118    if (clock_rate == 0)
     119      get_clock_rate ();
     120    return ncpus;
     121  }
     122  
     123  /* gethrvtime -- generic solution, getting user time from
     124   * clock_gettime(CLOCK_THREAD_CPUTIME_ID,..), and reformatting.
     125   * need -lrt to compile.*/
     126  hrtime_t
     127  gethrvtime ()
     128  {
     129    struct timespec tp;
     130    hrtime_t rc = 0;
     131    int r = clock_gettime (CLOCK_THREAD_CPUTIME_ID, &tp);
     132    if (r == 0)
     133      rc = ((hrtime_t) tp.tv_sec) * 1000000000 + (hrtime_t) tp.tv_nsec;
     134    return rc;
     135  }
     136  
     137  /*
     138   *  CLOCK_MONOTONIC
     139   *  Clock that cannot be set and represents monotonic time since some
     140   *           unspecified starting point.
     141   */
     142  hrtime_t
     143  gethrtime (void)
     144  {
     145    struct timespec tp;
     146    hrtime_t rc = 0;
     147  
     148    /*
     149     * For er_kernel on Linux, we want to match how DTrace gets its timestamps.
     150     * This is CLOCK_MONOTONIC_RAW.  It might be changing to CLOCK_MONOTONIC.
     151     * For now, we change to "RAW" and can change back if DTrace changes.
     152     *
     153     * The two can be different.  Check the clock_gettime() man page.
     154     * CLOCK_MONOTONIC_RAW is Linux-specific and introduced in 2.6.28.
     155     * It is impervious to NTP or adjtime adjustments.
     156     *
     157     * We must match the timer used in perfan/libcollector/src/gethrtime.c.
     158     *
     159     * There is no issue on Solaris, where gethrtime() is provided by the kernel
     160     * and used by DTrace.
     161     */
     162  #ifdef CLOCK_MONOTONIC_RAW
     163    int r = clock_gettime (CLOCK_MONOTONIC_RAW, &tp);
     164  #else
     165    int r = clock_gettime (CLOCK_MONOTONIC, &tp);
     166  #endif
     167    if (r == 0)
     168      rc = ((hrtime_t) tp.tv_sec) * 1000000000 + (hrtime_t) tp.tv_nsec;
     169    return rc;
     170  }