]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gprofng/testsuite/gprofng.display/synprog/stopwatch.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gprofng / testsuite / gprofng.display / synprog / stopwatch.c
1 /* Copyright (C) 2021-2024 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 <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29
30 #include "stopwatch.h"
31
32 static char *prhrdelta (hrtime_t);
33 static char *prhrvdelta (hrtime_t);
34 void init_micro_acct ();
35
36 /* stopwatch routines */
37 void
38 stpwtch_calibrate ()
39 {
40 struct timeval ttime;
41 char buf[1024];
42
43 (void) gettimeofday (&ttime, NULL);
44 time_t secs = (time_t) ttime.tv_sec;
45 sprintf (buf, "%s Stopwatch calibration", prtime (&secs));
46 wlog (buf, NULL);
47
48 init_micro_acct ();
49 stopwatch_t *inner = stpwtch_alloc ("inner", 0);
50 stopwatch_t *outer = stpwtch_alloc ("outer", 0);
51 for (int i = 0; i < 1000; i++)
52 {
53 stpwtch_start (outer);
54 stpwtch_start (inner);
55 stpwtch_stop (inner);
56 stpwtch_stop (outer);
57 }
58 stpwtch_print (inner);
59 stpwtch_print (outer);
60 free ((void *) inner);
61 free ((void *) outer);
62 }
63
64 stopwatch_t *
65 stpwtch_alloc (char *name, int histo)
66 {
67 stopwatch_t *w = (stopwatch_t *) malloc (sizeof (stopwatch_t));
68 if (w == NULL)
69 {
70 fprintf (stderr, "stpwtch_alloc(%s, %d): malloc failed\n", name, histo);
71 return NULL;
72 }
73 w->sum = 0.;
74 w->sumsq = 0.;
75 w->count = 0;
76 w->min = 0;
77 w->last = 0;
78 w->name = strdup (name);
79 stpwtch_start (w);
80 w->begin = w->start;
81
82 return w;
83 }
84
85 void
86 stpwtch_start (stopwatch_t *w)
87 {
88 w->start = gethrtime ();
89 }
90
91 void
92 stpwtch_stop (stopwatch_t *w)
93 {
94 if (w->start == 0) /* if never started, ignore the call */
95 return;
96
97 /* get stopping high-res time */
98 w->tempus = gethrtime ();
99
100 /* bump count of stops */
101 w->count++;
102
103 /* compute the delta for this call */
104 w->delta = w->tempus - w->start;
105
106 /* add in this one */
107 w->last = (double) (w->delta);
108 w->sum = w->sum + w->last;
109 w->sumsq = w->sumsq + w->last * w->last;
110
111 if (w->max == 0)
112 w->max = w->last;
113 else if (w->max < w->last)
114 w->max = w->last;
115 if (w->min == 0)
116 w->min = w->last;
117 else if (w->min > w->last)
118 w->min = w->last;
119
120 /* show stopwatch stopped */
121 w->start = 0;
122 }
123
124 void
125 stpwtch_print (stopwatch_t *w)
126 {
127 char cvdbuf[1024];
128
129 /* get stopping high-res time */
130 w->tempus = gethrtime ();
131 double duration = (double) (w->tempus - w->begin);
132
133 if (w->count == 0)
134 sprintf (cvdbuf, " 0. s. ( 0. %% of %12.6f s.) -- %s\n",
135 (duration / 1000000000.), w->name);
136 else if (w->count == 1)
137 sprintf (cvdbuf, " %12.6f s. (%4.1f %%%% of %.6f s.) -- %s\n",
138 w->sum / 1000000000., (100. * w->sum) / duration,
139 duration / 1000000000., w->name);
140 else
141 sprintf (cvdbuf,
142 " %12.6f s. (%4.1f %%%% of %.6f s.) -- %s\n\tN = %d,"
143 " avg = %.3f us., min = %.3f, max = %.3f\n",
144 w->sum / 1000000000., (100. * w->sum) / duration,
145 duration / 1000000000., w->name, w->count,
146 w->sum / 1000. / ((double) (w->count > 0 ? w->count : 1)),
147 ((double) w->min / 1000.), ((double) w->max / 1000.));
148 fprintf (stderr, cvdbuf);
149 }
150
151 /* hrtime routines */
152 int
153 whrlog (hrtime_t delta, char *event, char *string)
154 {
155 char buf[1024];
156 if (string == NULL)
157 sprintf (buf, " %s secs. in %s\n", prhrdelta (delta), event);
158 else
159 sprintf (buf, " %s secs. in %s\n\t%s\n", prhrdelta (delta), event, string);
160 int bytes = fprintf (stderr, "%s", buf);
161 return bytes;
162 }
163
164 /* hrtime routines */
165 int
166 whrvlog (hrtime_t delta, hrtime_t vdelta, char *event, char *string)
167 {
168 char buf[1024];
169 if (string == NULL)
170 sprintf (buf, " %s wall-secs., %s CPU-secs., in %s\n",
171 prhrdelta (delta), prhrvdelta (vdelta), event);
172 else
173 sprintf (buf, " %s wall-secs., %s CPU-secs., in %s\n\t%s\n",
174 prhrdelta (delta), prhrvdelta (vdelta), event, string);
175 int bytes = fprintf (stderr, "%s", buf);
176 return bytes;
177 }
178
179 /* prhrdelta (hrtime_t delta)
180 * returns a pointer to a static string in the form:
181 * sec.micros
182 * 1.123456
183 * 0123456789
184 *
185 * prhrvdelta is the same, but uses a different static buffer
186 */
187 static char *
188 prhrdelta (hrtime_t delta)
189 {
190 static char cvdbuf[26];
191
192 /* convert to seconds */
193 double tempus = ((double) delta) / (double) 1000000000.;
194 sprintf (cvdbuf, "%10.6f", tempus);
195 return cvdbuf;
196 }
197
198 static char *
199 prhrvdelta (hrtime_t delta)
200 {
201 static char cvdbuf[26];
202
203 /* convert to seconds */
204 double tempus = ((double) delta) / (double) 1000000000.;
205 sprintf (cvdbuf, "%10.6f", tempus);
206 return cvdbuf;
207 }
208
209 /* time of day routines */
210
211 /* starting time - first timestamp; initialized on first call */
212 static struct timeval starttime = {0, 0};
213 static struct timeval ttime; /* last-recorded timestamp */
214 static struct timeval deltatime; /* delta of last-rec'd timestamp */
215
216 static void
217 snaptod ()
218 {
219 (void) gettimeofday (&ttime, NULL);
220 if (starttime.tv_sec == 0)
221 starttime = ttime;
222
223 deltatime.tv_sec = ttime.tv_sec - starttime.tv_sec;
224 deltatime.tv_usec = ttime.tv_usec - starttime.tv_usec;
225 while (deltatime.tv_usec < 0)
226 {
227 deltatime.tv_sec--;
228 deltatime.tv_usec += 1000000;
229 }
230 }
231
232 int
233 wlog (char *event, char *string)
234 {
235 char buf[1024];
236
237 snaptod ();
238 if (string == NULL)
239 sprintf (buf, "%s ===== (%d) %s\n", prdelta (deltatime),
240 (int) getpid (), event);
241 else
242 sprintf (buf, "%s ===== (%d) %s\n\t%s\n", prdelta (deltatime),
243 (int) getpid (), event, string);
244 int bytes = fprintf (stderr, "%s", buf);
245 return bytes;
246 }
247
248 /* prtime (ttime)
249 * returns a pointer to a static string in the form:
250 * Thu 01 Jan 90 00:00:00\0
251 * 01234567890122345678901234
252 *
253 * ttime is a pointer to a UNIX time in seconds since epoch
254 * library routine localtime() is used
255 */
256 char *
257 prtime (time_t *ttime)
258 {
259 static char *days[] = {
260 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
261 };
262 static char *months[] = {
263 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
264 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
265 };
266 static char cvbuf[26];
267
268 /* get the date and time */
269 struct tm *tp = localtime (ttime);
270
271 /* convert to string */
272 sprintf (cvbuf, "%3s %02d %s %02d %02d:%02d:%02d", days[tp->tm_wday],
273 tp->tm_mday, months[tp->tm_mon], tp->tm_year % 100,
274 tp->tm_hour, tp->tm_min, tp->tm_sec);
275 return cvbuf;
276 }
277
278 char *
279 prdelta (struct timeval tempus)
280 {
281 static char cvdbuf[26];
282 while (tempus.tv_usec < 0)
283 {
284 tempus.tv_sec--;
285 tempus.tv_usec += 1000000;
286 }
287 long seconds = tempus.tv_sec % 60;
288 long minutes = tempus.tv_sec / 60;
289 long hours = minutes / 60;
290 minutes = minutes % 60;
291 sprintf (cvdbuf, "%02ld:%02ld:%02ld.%03ld ",
292 hours, minutes, seconds, (long) tempus.tv_usec / 1000);
293 return cvdbuf;
294 }