]>
Commit | Line | Data |
---|---|---|
fd67aa11 | 1 | /* Copyright (C) 2021-2024 Free Software Foundation, Inc. |
bb368aad VM |
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 | */ | |
0a30596c | 162 | #ifdef CLOCK_MONOTONIC_RAW |
bb368aad | 163 | int r = clock_gettime (CLOCK_MONOTONIC_RAW, &tp); |
0a30596c NC |
164 | #else |
165 | int r = clock_gettime (CLOCK_MONOTONIC, &tp); | |
166 | #endif | |
bb368aad VM |
167 | if (r == 0) |
168 | rc = ((hrtime_t) tp.tv_sec) * 1000000000 + (hrtime_t) tp.tv_nsec; | |
169 | return rc; | |
170 | } |