Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 56.4% 106 / 0 / 188
Functions: 66.7% 18 / 1 / 28
Branches: 45.0% 36 / 0 / 80

OMCompiler/SimulationRuntime/c/util/rtclock.c
Line Branch Exec Source
1 /*
2 * This file belongs to the OpenModelica Run-Time System
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC), c/o Linköpings
5 * universitet, Department of Computer and Information Science, SE-58183 Linköping, Sweden. All rights
6 * reserved.
7 *
8 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF THE BSD NEW LICENSE OR THE
9 * AGPL VERSION 3 LICENSE OR THE OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. ANY
10 * USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S
11 * ACCEPTANCE OF THE BSD NEW LICENSE OR THE OSMC PUBLIC LICENSE OR THE AGPL
12 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
13 *
14 * The OpenModelica software and the OSMC (Open Source Modelica Consortium) Public License
15 * (OSMC-PL) are obtained from OSMC, either from the above address, from the URLs:
16 * http://www.openmodelica.org or https://github.com/OpenModelica/ or
17 * http://www.ida.liu.se/projects/OpenModelica, and in the OpenModelica distribution. GNU
18 * AGPL version 3 is obtained from: https://www.gnu.org/licenses/licenses.html#GPL. The BSD NEW
19 * License is obtained from: http://www.opensource.org/licenses/BSD-3-Clause.
20 *
21 * This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY
23 * SET FORTH IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF
24 * OSMC-PL.
25 *
26 */
27
28 #include "rtclock.h"
29 #include <assert.h>
30 #include <stdlib.h>
31 #include <limits.h>
32 #include <string.h>
33 #include "omc_msvc.h"
34 #include "../gc/omc_gc.h"
35 #include <errno.h>
36 #include "omc_error.h"
37 #ifndef NSEC_PER_SEC
38 #define NSEC_PER_SEC 1000000000L
39 #endif
40
41 /* If min_time is set, subtract this amount from measured times to avoid
42 * including the time of measuring in reported statistics */
43 static double min_time = 0;
44 static uint32_t default_rt_clock_ncall[NUM_RT_CLOCKS] = { 0 };
45 static uint32_t default_rt_clock_ncall_min[NUM_RT_CLOCKS] = { 0 };
46 static uint32_t default_rt_clock_ncall_max[NUM_RT_CLOCKS] = { 0 };
47 static uint32_t default_rt_clock_ncall_total[NUM_RT_CLOCKS] = { 0 };
48 static uint32_t *rt_clock_ncall = default_rt_clock_ncall;
49 static uint32_t *rt_clock_ncall_min = default_rt_clock_ncall_min;
50 static uint32_t *rt_clock_ncall_max = default_rt_clock_ncall_max;
51 static uint32_t *rt_clock_ncall_total = default_rt_clock_ncall_total;
52
53 static rtclock_t default_total_tp[NUM_RT_CLOCKS];
54 static rtclock_t default_max_tp[NUM_RT_CLOCKS];
55 static rtclock_t default_acc_tp[NUM_RT_CLOCKS];
56 static rtclock_t default_tick_tp[NUM_RT_CLOCKS];
57
58 static rtclock_t *total_tp = default_total_tp;
59 static rtclock_t *max_tp = default_max_tp;
60 static rtclock_t *acc_tp = default_acc_tp;
61 static rtclock_t *tick_tp = default_tick_tp;
62
63 static int rtclock_compare(rtclock_t, rtclock_t);
64
65 static rtclock_t max_rtclock(rtclock_t t1, rtclock_t t2) {
66
2/2
✓ Branch 0 taken 36108 times.
✓ Branch 1 taken 47 times.
36155 if (rtclock_compare(t1, t2) < 0)
67 return t2;
68 36108 return t1;
69 }
70
71 static double rtclock_value(rtclock_t);
72
73 static double rtclock_compensated_value(rtclock_t tp) {
74 double d = rtclock_value(tp);
75
3/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2949 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 14622 times.
17573 if (d < min_time) {
76 2 min_time = d;
77 }
78 ✗ return d - min_time;
79 }
80
81 2030 void rt_add_ncall(int ix, int n) {
82 2030 rt_clock_ncall[ix] += n;
83 2030 }
84
85 33777 uint32_t rt_ncall(int ix) {
86 33777 return rt_clock_ncall[ix];
87 }
88
89 1 uint32_t* rt_ncall_arr(int ix) {
90 1 return rt_clock_ncall+ix;
91 }
92
93 5 uint32_t rt_ncall_min(int ix) {
94 5 return rt_clock_ncall_min[ix];
95 }
96
97 5 uint32_t rt_ncall_max(int ix) {
98 5 return rt_clock_ncall_max[ix];
99 }
100
101 5 uint32_t rt_ncall_total(int ix) {
102 5 return rt_clock_ncall_total[ix];
103 }
104
105 36155 void rt_update_min_max_ncall(int ix) {
106 36155 unsigned long nmin = rt_clock_ncall_min[ix];
107 36155 unsigned long nmax = rt_clock_ncall_max[ix];
108 36155 unsigned long n = rt_clock_ncall[ix];
109
2/2
✓ Branch 0 taken 12459 times.
✓ Branch 1 taken 23696 times.
36155 if (n == 0) {
110 return;
111 }
112
2/2
✓ Branch 0 taken 12455 times.
✓ Branch 1 taken 4 times.
12459 rt_clock_ncall_min[ix] = nmin && nmin < n ? nmin : n;
113 12459 rt_clock_ncall_max[ix] = nmax > n ? nmax : n;
114 }
115
116 ✗ void rt_clear_total_ncall(int ix) {
117 ✗ rt_clock_ncall[ix] = 0;
118 ✗ rt_clock_ncall_total[ix] = 0;
119 ✗ rt_clock_ncall_min[ix] = UINT32_MAX;
120 ✗ rt_clock_ncall_max[ix] = 0;
121 ✗ }
122
123 2543 double rt_accumulated(int ix) {
124 2543 double d = rtclock_value(acc_tp[ix]);
125
2/2
✓ Branch 0 taken 1543 times.
✓ Branch 1 taken 1000 times.
2543 if (d == 0) {
126 return d;
127 }
128
2/4
✓ Branch 0 taken 1543 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1543 times.
1543 if (d > 0 && d < min_time * rt_clock_ncall[ix]) {
129 ✗ min_time = d / rt_clock_ncall[ix];
130 }
131 1543 return d - min_time * rt_clock_ncall[ix];
132 }
133
134 5 double rt_max_accumulated(int ix) {
135 5 double d = rtclock_value(max_tp[ix]);
136
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (d == 0) {
137 return d;
138 }
139
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (d > 0 && d < min_time) {
140 ✗ min_time = d;
141 }
142 5 return d - min_time;
143 }
144
145 5 double rt_total(int ix) {
146 5 double d = rtclock_value(total_tp[ix]);
147
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (d == 0) {
148 return d;
149 }
150 5 d = d - min_time * rt_clock_ncall_total[ix];
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(d >= 0);
152 return d;
153 }
154
155 #if defined(__MINGW32__) || defined(_MSC_VER)
156
157 static enum omc_rt_clock_t selectedClock = OMC_CLOCK_REALTIME;
158
159 #if !defined(_MSC_VER)
160 static long long RDTSC(void) {
161 register long long TSC __asm__("eax");
162 __asm__ volatile (".byte 15, 49" : : : "eax", "edx");
163 return TSC;
164 // unsigned int hi, lo;
165 // asm volatile("rdtscp" : "=a"(lo), "=d"(hi));
166 // return (unsigned long long)lo | ((unsigned long long)hi << 32);
167 }
168 #else
169 static long RDTSC() {
170 // unsigned int ui;
171 // return __rdtscp(&ui);
172 return __rdtsc();
173 }
174 #endif
175
176 int rt_set_clock(enum omc_rt_clock_t newClock) {
177 if (newClock != OMC_CLOCK_REALTIME && newClock != OMC_CPU_CYCLES) {
178 return 1;
179 }
180
181 selectedClock = newClock;
182 return 0;
183 }
184
185 enum omc_rt_clock_t rt_get_clock(void) {
186 return selectedClock;
187 }
188
189 static rtclock_t performance_frequency;
190
191 void rt_tick(int ix) {
192 if(selectedClock == OMC_CLOCK_REALTIME) {
193 rt_ext_tp_tick_realtime(&tick_tp[ix]);
194 } else {
195 rtclock_t time;
196 time.QuadPart = RDTSC();
197 tick_tp[ix] = time;
198 }
199 rt_clock_ncall[ix]++;
200 }
201
202 double rt_tock(int ix) {
203 rtclock_t diff_tp;
204 rtclock_t tock_tp;
205 if(selectedClock == OMC_CLOCK_REALTIME) {
206 QueryPerformanceCounter(&tock_tp);
207 } else {
208 tock_tp.QuadPart = RDTSC();
209 }
210 #if defined(__MINGW32__) // error: ISO C forbids casts to union type [-Wpedantic]
211 #pragma GCC diagnostic push
212 #pragma GCC diagnostic ignored "-Wpedantic"
213 #endif
214 diff_tp = (rtclock_t)(tock_tp.QuadPart - tick_tp[ix].QuadPart);
215 #if defined(__MINGW32__)
216 #pragma GCC diagnostic pop
217 #endif
218 return rtclock_compensated_value(diff_tp);
219 }
220
221 void rt_clear(int ix) {
222 total_tp[ix].QuadPart += acc_tp[ix].QuadPart;
223 rt_clock_ncall_total[ix] += rt_clock_ncall[ix];
224 max_tp[ix] = max_rtclock(max_tp[ix], acc_tp[ix]);
225 rt_update_min_max_ncall(ix);
226 acc_tp[ix].QuadPart = 0;
227 rt_clock_ncall[ix] = 0;
228 }
229
230 void rt_clear_total(int ix) {
231 total_tp[ix].QuadPart = 0;
232 acc_tp[ix].QuadPart = 0;
233 rt_clear_total_ncall(ix);
234 }
235
236 double rt_accumulate(int ix) {
237 rtclock_t diff_tp;
238 rtclock_t tock_tp;
239 if(selectedClock == OMC_CLOCK_REALTIME) {
240 QueryPerformanceCounter(&tock_tp);
241 } else {
242 tock_tp.QuadPart = RDTSC();
243 }
244 #if defined(__MINGW32__) // error: ISO C forbids casts to union type [-Wpedantic]
245 #pragma GCC diagnostic push
246 #pragma GCC diagnostic ignored "-Wpedantic"
247 #endif
248 diff_tp = (rtclock_t)(tock_tp.QuadPart - tick_tp[ix].QuadPart);
249 #if defined(__MINGW32__)
250 #pragma GCC diagnostic pop
251 #endif
252 acc_tp[ix].QuadPart += diff_tp.QuadPart;
253 return rtclock_compensated_value(diff_tp);
254 }
255
256 int rtclock_compare(rtclock_t t1, rtclock_t t2) {
257 return t1.QuadPart - t2.QuadPart;
258 }
259
260 double rtclock_value(rtclock_t tp) {
261 if(selectedClock == OMC_CLOCK_REALTIME) {
262 double d1, d2;
263 d1 = (double) tp.QuadPart;
264 d2 = (double) performance_frequency.QuadPart;
265 return d1 / d2;
266 } else {
267 return (double) tp.QuadPart;
268 }
269 }
270
271 void rt_ext_tp_tick(rtclock_t* tick_tp) {
272 if(selectedClock == OMC_CLOCK_REALTIME) {
273 rt_ext_tp_tick_realtime(tick_tp);
274 } else {
275 rtclock_t time;
276 time.QuadPart = RDTSC();
277 *tick_tp = time;
278 }
279 }
280
281 void rt_ext_tp_tick_realtime(rtclock_t* tick_tp) {
282 static int init = 0;
283 if (!init) {
284 init = 1;
285 QueryPerformanceFrequency(&performance_frequency);
286 }
287 QueryPerformanceCounter(tick_tp);
288 }
289
290 double rt_ext_tp_tock_realtime(rtclock_t* tick_tp) {
291 rtclock_t diff_tp;
292 rtclock_t tock_tp;
293 QueryPerformanceCounter(&tock_tp);
294 #if defined(__MINGW32__) // error: ISO C forbids casts to union type [-Wpedantic]
295 #pragma GCC diagnostic push
296 #pragma GCC diagnostic ignored "-Wpedantic"
297 #endif
298 diff_tp = (rtclock_t)(tock_tp.QuadPart - tick_tp->QuadPart);
299 #if defined(__MINGW32__)
300 #pragma GCC diagnostic pop
301 #endif
302 return rtclock_compensated_value(diff_tp);
303 }
304
305 double rt_ext_tp_tock(rtclock_t* tick_tp) {
306 if(selectedClock == OMC_CLOCK_REALTIME) {
307 return rt_ext_tp_tock_realtime(tick_tp);
308 } else {
309 rtclock_t diff_tp;
310 rtclock_t tock_tp;
311 tock_tp.QuadPart = RDTSC();
312 #if defined(__MINGW32__) // error: ISO C forbids casts to union type [-Wpedantic]
313 #pragma GCC diagnostic push
314 #pragma GCC diagnostic ignored "-Wpedantic"
315 #endif
316 diff_tp = (rtclock_t)(tock_tp.QuadPart - tick_tp->QuadPart);
317 #if defined(__MINGW32__)
318 #pragma GCC diagnostic pop
319 #endif
320 return rtclock_compensated_value(diff_tp);
321 }
322 }
323
324 int64_t rt_ext_tp_sync_nanosec(rtclock_t* tick_tp, uint64_t nsec)
325 {
326 int64_t res = rt_ext_tp_tock_realtime(tick_tp)*1e9 - nsec;
327 double d=0;
328 if (res > 0) {
329 return res;
330 }
331 do {
332 d = nsec*1e-9 - rt_ext_tp_tock_realtime(tick_tp);
333 if (d < 0) {
334 break;
335 } if (d >= 2e-3) {
336 Sleep((int)(d*1e3));
337 } else {
338 Sleep(0);
339 }
340 } while (1);
341 return res;
342 }
343
344 #elif defined(__APPLE_CC__)
345
346 int rt_set_clock(enum omc_rt_clock_t newClock) {
347 return newClock != OMC_CLOCK_REALTIME;
348 }
349
350 void rt_tick(int ix) {
351 tick_tp[ix] = mach_absolute_time();
352 rt_clock_ncall[ix]++;
353 }
354
355 double rt_tock(int ix) {
356 rtclock_t tock_tp = mach_absolute_time();
357 rtclock_t diff_tp = tock_tp - tick_tp[ix];
358 return rtclock_compensated_value(diff_tp);
359 }
360
361 void rt_clear(int ix)
362 {
363 total_tp[ix] += acc_tp[ix];
364 rt_clock_ncall_total[ix] += rt_clock_ncall[ix];
365 max_tp[ix] = max_rtclock(max_tp[ix],acc_tp[ix]);
366 rt_update_min_max_ncall(ix);
367 acc_tp[ix] = 0;
368 rt_clock_ncall[ix] = 0;
369 }
370
371 void rt_clear_total(int ix)
372 {
373 total_tp[ix] = 0;
374 rt_clock_ncall_total[ix] = 0;
375 acc_tp[ix] = 0;
376 rt_clock_ncall[ix] = 0;
377 }
378
379 double rt_accumulate(int ix) {
380 rtclock_t tock_tp = mach_absolute_time();
381 rtclock_t diff_tp = tock_tp - tick_tp[ix];
382 acc_tp[ix] += diff_tp;
383 return rtclock_compensated_value(diff_tp);
384 }
385
386 double rtclock_value(rtclock_t tp) {
387 static mach_timebase_info_data_t info = {0,0};
388 if(info.denom == 0)
389 mach_timebase_info(&info);
390 uint64_t elapsednano = tp * (info.numer / info.denom);
391 return elapsednano * 1e-9;
392 }
393
394 int rtclock_compare(rtclock_t t1, rtclock_t t2) {
395 return t1 - t2;
396 }
397
398 void rt_ext_tp_tick(rtclock_t* tick_tp) {
399 *tick_tp = mach_absolute_time();
400 }
401
402 double rt_ext_tp_tock(rtclock_t* tick_tp) {
403 rtclock_t tock_tp = mach_absolute_time();
404 rtclock_t diff_tp = tock_tp - *tick_tp;
405 return rtclock_compensated_value(diff_tp);
406 }
407
408 void rt_ext_tp_tick_realtime(rtclock_t* tick_tp) {
409 *tick_tp = mach_absolute_time();
410 }
411
412 double rt_ext_tp_tock_realtime(rtclock_t* tick_tp) {
413 rtclock_t tock_tp = mach_absolute_time();
414 rtclock_t diff_tp = tock_tp - *tick_tp;
415 return rtclock_compensated_value(diff_tp);
416 }
417
418 int64_t rt_ext_tp_sync_nanosec(rtclock_t* tick_tp, uint64_t nsec)
419 {
420 int64_t res = 0;
421 throwStreamPrint(NULL, "%s not implemented for OSX", __func__);
422 return res;
423 }
424
425 #else
426
427 /* CLOCK_MONOTONIC_RAW: since Linux 2.6.28 */
428 #ifdef CLOCK_MONOTONIC_RAW
429 #define OMC_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
430 #else
431 #define OMC_CLOCK_MONOTONIC CLOCK_MONOTONIC
432 #endif
433 static clockid_t omc_clock = OMC_CLOCK_MONOTONIC;
434
435 1 int rt_set_clock(enum omc_rt_clock_t newClock) {
436 #if defined(__linux__) || defined(__FreeBSD__)
437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 omc_clock = newClock == OMC_CLOCK_REALTIME ? OMC_CLOCK_MONOTONIC : CLOCK_PROCESS_CPUTIME_ID;
438 #else
439 omc_clock = OMC_CLOCK_MONOTONIC;
440 #endif
441 1 return 0;
442 }
443
444 ✗ enum omc_rt_clock_t rt_get_clock(void) {
445 ✗ return omc_clock==OMC_CLOCK_MONOTONIC ? OMC_CLOCK_REALTIME : OMC_CLOCK_CPUTIME;
446 }
447
448 #if defined(__i386__)
449 static inline unsigned long long RDTSC(void)
450 {
451 unsigned long long int x;
452 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
453 return x;
454 }
455 #elif defined(__x86_64__)
456 static inline unsigned long long RDTSC(void)
457 {
458 unsigned hi, lo;
459 ✗ __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
460 ✗ return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
461 }
462 #else
463 #include <stdio.h>
464
465 static inline unsigned long long RDTSC(void)
466 {
467 fprintf(stderr, "No CPU clock implemented on this processor architecture\n");
468 abort();
469 }
470 #endif
471
472 29899 void rt_tick(int ix) {
473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29899 times.
29899 if(omc_clock == OMC_CPU_CYCLES) {
474 ✗ tick_tp[ix].cycles = RDTSC();
475 } else {
476 29899 clock_gettime(omc_clock, &tick_tp[ix].time);
477 }
478 29899 rt_clock_ncall[ix]++;
479 29899 }
480
481 14624 double rt_tock(int ix) {
482 rtclock_t diff_tp;
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14624 times.
14624 if(omc_clock == OMC_CPU_CYCLES) {
484 unsigned long long cycles = RDTSC();
485 ✗ diff_tp = (rtclock_t){ .cycles = cycles - tick_tp[ix].cycles };
486 } else {
487 14624 struct timespec tock_tp = {0,0};
488 14624 clock_gettime(omc_clock, &tock_tp);
489 14624 diff_tp = (rtclock_t){
490 14624 tock_tp.tv_sec - tick_tp[ix].time.tv_sec,
491 14624 tock_tp.tv_nsec - tick_tp[ix].time.tv_nsec
492 };
493 }
494 14624 return rtclock_compensated_value(diff_tp);
495 }
496
497 36155 void rt_clear(int ix)
498 {
499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36155 times.
36155 if(omc_clock == OMC_CPU_CYCLES) {
500 ✗ total_tp[ix].cycles += acc_tp[ix].cycles;
501 ✗ rt_clock_ncall_total[ix] += rt_clock_ncall[ix];
502 ✗ max_tp[ix] = max_rtclock(max_tp[ix],acc_tp[ix]);
503 ✗ rt_update_min_max_ncall(ix);
504
505 ✗ acc_tp[ix].cycles = 0;
506 ✗ rt_clock_ncall[ix] = 0;
507 } else {
508 36155 total_tp[ix].time.tv_sec += acc_tp[ix].time.tv_sec;
509 36155 total_tp[ix].time.tv_nsec += acc_tp[ix].time.tv_nsec;
510 36155 rt_clock_ncall_total[ix] += rt_clock_ncall[ix];
511 72310 max_tp[ix] = max_rtclock(max_tp[ix],acc_tp[ix]);
512 36155 rt_update_min_max_ncall(ix);
513
514 36155 acc_tp[ix].time.tv_sec = 0;
515 36155 acc_tp[ix].time.tv_nsec = 0;
516 36155 rt_clock_ncall[ix] = 0;
517 }
518 36155 }
519
520 ✗ void rt_clear_total(int ix)
521 {
522 ✗ if(omc_clock == OMC_CPU_CYCLES) {
523 ✗ total_tp[ix].cycles = 0;
524 ✗ rt_clock_ncall_total[ix] = 0;
525
526 ✗ acc_tp[ix].cycles = 0;
527 ✗ rt_clock_ncall[ix] = 0;
528 } else {
529 ✗ total_tp[ix].time.tv_sec = 0;
530 ✗ total_tp[ix].time.tv_nsec = 0;
531 ✗ rt_clock_ncall_total[ix] = 0;
532
533 ✗ acc_tp[ix].time.tv_sec = 0;
534 ✗ acc_tp[ix].time.tv_nsec = 0;
535 ✗ rt_clock_ncall[ix] = 0;
536 }
537 ✗ }
538
539 static inline struct timespec timeSpecAdd(struct timespec t1, struct timespec t2)
540 {
541 struct timespec res;
542 ✗ res.tv_sec = t1.tv_sec + t2.tv_sec;
543 ✗ res.tv_nsec = t1.tv_nsec + t2.tv_nsec;
544 ✗ if (res.tv_nsec >= 1000000000L) {
545 ✗ res.tv_sec++;
546 ✗ res.tv_nsec -= 1000000000L;
547 }
548 return res;
549 }
550
551 static inline struct timespec timeSpecSub(struct timespec t1, struct timespec t2)
552 {
553 struct timespec res;
554 ✗ res.tv_sec = t2.tv_sec - t1.tv_sec;
555 ✗ res.tv_nsec = t2.tv_nsec - t1.tv_nsec;
556 ✗ if (res.tv_nsec < 0) {
557 ✗ res.tv_sec--;
558 ✗ res.tv_nsec += 1000000000L;
559 }
560 return res;
561 }
562
563 static inline int timeSpecCmp(struct timespec t1, struct timespec t2)
564 {
565 if (t2.tv_sec > t1.tv_sec) {
566 return 1;
567 } else if (t2.tv_sec < t1.tv_sec) {
568 return -1;
569 }
570 if (t2.tv_nsec > t1.tv_nsec) {
571 return 1;
572 } else if (t2.tv_nsec < t1.tv_nsec) {
573 return -1;
574 }
575 return 0;
576 }
577
578 2949 double rt_accumulate(int ix) {
579 rtclock_t diff_tp;
580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2949 times.
2949 if(omc_clock == OMC_CPU_CYCLES) {
581 unsigned long long cycles = RDTSC();
582 ✗ diff_tp = (rtclock_t){ .cycles = cycles - tick_tp[ix].cycles };
583 ✗ acc_tp[ix].cycles += diff_tp.cycles;
584 } else {
585 2949 struct timespec tock_tp = {0,0};
586 2949 clock_gettime(omc_clock, &tock_tp);
587 2949 diff_tp = (rtclock_t){
588 2949 tock_tp.tv_sec - tick_tp[ix].time.tv_sec,
589 2949 tock_tp.tv_nsec - tick_tp[ix].time.tv_nsec
590 };
591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2949 times.
2949 if(diff_tp.time.tv_nsec < 0) {
592 ✗ diff_tp.time.tv_sec--;
593 ✗ diff_tp.time.tv_nsec += 1e9;
594 }
595 2949 acc_tp[ix].time.tv_sec += diff_tp.time.tv_sec;
596 2949 acc_tp[ix].time.tv_nsec += diff_tp.time.tv_nsec;
597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2949 times.
2949 if(acc_tp[ix].time.tv_nsec >= 1e9) {
598 ✗ acc_tp[ix].time.tv_sec++;
599 ✗ acc_tp[ix].time.tv_nsec -= 1e9;
600 }
601 }
602 2949 return rtclock_compensated_value(diff_tp);
603 }
604
605 static double rtclock_value(rtclock_t tp) {
606 double d;
607
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 2949 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14624 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2543 times.
20126 if(omc_clock == OMC_CPU_CYCLES) {
608 ✗ d = tp.cycles;
609 } else {
610 20126 d = tp.time.tv_sec + tp.time.tv_nsec*1e-9;
611 }
612 return d;
613 }
614
615 int rtclock_compare(rtclock_t t1, rtclock_t t2)
616 {
617 if(omc_clock == OMC_CPU_CYCLES) {
618 ✗ return t1.cycles - t2.cycles;
619 } else {
620
1/2
✓ Branch 0 taken 36155 times.
✗ Branch 1 not taken.
36155 if(t1.time.tv_sec == t2.time.tv_sec) {
621 36155 return t1.time.tv_nsec - t2.time.tv_nsec;
622 }
623 ✗ return t1.time.tv_sec - t2.time.tv_sec;
624 }
625 }
626
627 ✗ void rt_ext_tp_tick(rtclock_t* tick_tp) {
628 ✗ if(omc_clock == OMC_CPU_CYCLES) {
629 ✗ tick_tp->cycles = RDTSC();
630 } else {
631 ✗ clock_gettime(omc_clock, &tick_tp->time);
632 }
633 ✗ }
634
635 ✗ void rt_ext_tp_tick_realtime(rtclock_t* tick_tp) {
636 ✗ clock_gettime(CLOCK_MONOTONIC, &tick_tp->time);
637 ✗ }
638
639 ✗ static inline double rt_ext_tp_tock_common(clockid_t clk_id, rtclock_t* tick_tp) {
640 rtclock_t diff_tp;
641 ✗ struct timespec tock_tp = {0,0};
642 ✗ clock_gettime(clk_id, &tock_tp);
643 diff_tp = (rtclock_t){
644 ✗ tock_tp.tv_sec - tick_tp->time.tv_sec,
645 ✗ tock_tp.tv_nsec - tick_tp->time.tv_nsec
646 };
647 ✗ return rtclock_compensated_value(diff_tp);
648 }
649
650 ✗ double rt_ext_tp_tock_realtime(rtclock_t* tick_tp) {
651 ✗ return rt_ext_tp_tock_common(CLOCK_MONOTONIC, tick_tp);
652 }
653
654 ✗ double rt_ext_tp_tock(rtclock_t* tick_tp) {
655 ✗ if(omc_clock == OMC_CPU_CYCLES) {
656 unsigned long long cycles = RDTSC();
657 ✗ return rtclock_compensated_value((rtclock_t){ .cycles = cycles - tick_tp->cycles });
658 } else {
659 ✗ return rt_ext_tp_tock_common(omc_clock, tick_tp);
660 }
661 }
662
663 ✗ int64_t rt_ext_tp_sync_nanosec(rtclock_t* tick_tp, uint64_t nsec)
664 {
665 int64_t res=0;
666 int res_sleep=0;
667 ✗ struct timespec remain = {.tv_sec=nsec/NSEC_PER_SEC, .tv_nsec= nsec%NSEC_PER_SEC};
668 ✗ struct timespec sleepTime = timeSpecAdd(tick_tp->time, remain);
669 struct timespec curTime;
670 struct timespec late;
671 ✗ clock_gettime(CLOCK_MONOTONIC, &curTime);
672 late = timeSpecSub(sleepTime, curTime);
673 ✗ res = late.tv_sec*NSEC_PER_SEC + late.tv_nsec;
674 ✗ if (res > 0) {
675 return res;
676 }
677 do {
678 ✗ res_sleep = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &sleepTime, NULL);
679 ✗ if (res_sleep != 0 && res != EINTR) {
680 ✗ throwStreamPrint(NULL, "rt_ext_tp_sync_nanosec: %s\n", strerror(res));
681 }
682 } while (res_sleep==EINTR);
683 return res;
684 }
685
686 #endif
687
688 8 static OMC_INLINE void alloc_and_copy(void **ptr, size_t n, size_t sz)
689 {
690 8 void *newmemory = omc_alloc_interface.malloc(n*sz);
691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 assert(newmemory != 0);
692 8 memcpy(newmemory,*ptr,NUM_RT_CLOCKS*sz);
693 8 *ptr = newmemory;
694 8 }
695
696 2 void rt_init(int numTimers) {
697
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 if (numTimers < NUM_RT_CLOCKS) {
698 return; /* We already have more than we need statically allocated */
699 }
700 1 alloc_and_copy((void**)&acc_tp,numTimers,sizeof(rtclock_t));
701 1 alloc_and_copy((void**)&max_tp,numTimers,sizeof(rtclock_t));
702 1 alloc_and_copy((void**)&total_tp,numTimers,sizeof(rtclock_t));
703 1 alloc_and_copy((void**)&tick_tp,numTimers,sizeof(rtclock_t));
704 1 alloc_and_copy((void**)&rt_clock_ncall,numTimers,sizeof(uint32_t));
705 1 alloc_and_copy((void**)&rt_clock_ncall_total,numTimers,sizeof(uint32_t));
706 1 alloc_and_copy((void**)&rt_clock_ncall_min,numTimers,sizeof(uint32_t));
707 1 alloc_and_copy((void**)&rt_clock_ncall_max,numTimers,sizeof(uint32_t));
708 /* This memset-command is not working properly, especially on windows.
709 * It's writing into the rt_clock_ncall_total-array and thus the values are wrong.
710 * However, the profiling-functionality seems to work without it. */
711 //memset(rt_clock_ncall_min + NUM_RT_CLOCKS*sizeof(uint32_t), 0xFF, (numTimers-NUM_RT_CLOCKS) * sizeof(uint32_t));
712 }
713
714 1 void rt_measure_overhead(int ix)
715 {
716 int i;
717 1 min_time = 0;
718 1 rt_tick(ix);
719 1 min_time = rt_tock(ix);
720
2/2
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 1 time.
301 for (i=0; i<300; i++) {
721 300 rt_tick(ix);
722 300 rt_tock(ix);
723 }
724 1 }
725