diff options
Diffstat (limited to 'gprofng/src/gethrtime.c')
-rw-r--r-- | gprofng/src/gethrtime.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/gprofng/src/gethrtime.c b/gprofng/src/gethrtime.c new file mode 100644 index 00000000000..9e17f1eaa11 --- /dev/null +++ b/gprofng/src/gethrtime.c @@ -0,0 +1,170 @@ +/* Copyright (C) 2021 Free Software Foundation, Inc. + Contributed by Oracle. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "config.h" +#include <time.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/resource.h> + +#include "gp-defs.h" +#include "gp-time.h" + +/* =============================================================== */ +/* + * Below this are the get_clock_rate() and get_ncpus() for all architectures + */ + +static int clock_rate = 0; +static int ncpus = 0; +static char msgbuf[1024]; + +int +get_clock_rate (void) +{ + /* Linux version -- read /proc/cpuinfo + * Note the parsing is different on intel-Linux and sparc-Linux + */ + FILE *fp = fopen ("/proc/cpuinfo", "r"); + if (fp != NULL) + { + + char temp[1024]; + while (fgets (temp, sizeof (temp), fp) != NULL) + { +#if ARCH(SPARC) + /* cpu count for SPARC linux -- read from /proc/cpuinfo */ + if (strncmp (temp, "ncpus active", 12) == 0) + { + char *val = strchr (temp, ':'); + ncpus = val ? atol (val + 1) : 0; + } +#endif /* ARCH(SPARC) */ + + if (clock_rate == 0) + { + /* pick the first line that gives a CPU clock rate */ +#if ARCH(SPARC) + long long clk; + if (strncmp (temp, "Cpu0ClkTck", 10) == 0) + { + char *val = strchr (temp, ':'); + clk = val ? strtoll (val + 1, NULL, 16) : 0; + clock_rate = (int) (clk / 1000000); + } +#else + if (strncmp (temp, "cpu MHz", 7) == 0) + { + char *val = strchr (temp, ':'); + clock_rate = val ? atoi (val + 1) : 0; + } +#endif /* ARCH() */ + } + + /* did we get a clock rate? */ + if (clock_rate != 0) + { +#if ARCH(SPARC) + /* since we got a cpu count, we can break from the look */ + break; +#endif /* ARCH(SPARC) */ + } +#if ARCH(Intel) + /* On intel-Linux, count cpus based on "cpu MHz" lines */ + if (strncmp (temp, "cpu MHz", 7) == 0) + ncpus++; +#endif /* ARCH(Intel) */ + } + fclose (fp); + } + + if (clock_rate != 0) + sprintf (msgbuf, + "Clock rate = %d MHz (from reading /proc/cpuinfo) %d CPUs\n", + clock_rate, ncpus); + + /* did we get a clock rate? */ + if (clock_rate == 0) + { + clock_rate = 1000; + sprintf (msgbuf, "Clock rate = %d MHz (set by default) %d CPUs\n", + clock_rate, ncpus); + } + return clock_rate; +} + +int +get_ncpus (void) +{ + if (clock_rate == 0) + get_clock_rate (); + return ncpus; +} + +/* gethrvtime -- generic solution, getting user time from + * clock_gettime(CLOCK_THREAD_CPUTIME_ID,..), and reformatting. + * need -lrt to compile.*/ +hrtime_t +gethrvtime () +{ + struct timespec tp; + hrtime_t rc = 0; + int r = clock_gettime (CLOCK_THREAD_CPUTIME_ID, &tp); + if (r == 0) + rc = ((hrtime_t) tp.tv_sec) * 1000000000 + (hrtime_t) tp.tv_nsec; + return rc; +} + +/* + * CLOCK_MONOTONIC + * Clock that cannot be set and represents monotonic time since some + * unspecified starting point. + */ +hrtime_t +gethrtime (void) +{ + struct timespec tp; + hrtime_t rc = 0; + + /* + * For er_kernel on Linux, we want to match how DTrace gets its timestamps. + * This is CLOCK_MONOTONIC_RAW. It might be changing to CLOCK_MONOTONIC. + * For now, we change to "RAW" and can change back if DTrace changes. + * + * The two can be different. Check the clock_gettime() man page. + * CLOCK_MONOTONIC_RAW is Linux-specific and introduced in 2.6.28. + * It is impervious to NTP or adjtime adjustments. + * + * We must match the timer used in perfan/libcollector/src/gethrtime.c. + * + * There is no issue on Solaris, where gethrtime() is provided by the kernel + * and used by DTrace. + */ +#ifdef CLOCK_MONOTONIC_RAW + int r = clock_gettime (CLOCK_MONOTONIC_RAW, &tp); +#else + int r = clock_gettime (CLOCK_MONOTONIC, &tp); +#endif + if (r == 0) + rc = ((hrtime_t) tp.tv_sec) * 1000000000 + (hrtime_t) tp.tv_nsec; + return rc; +} |