don't print SYSTEM stacktrace on exceptions as it's not scheduled any more.
[minix.git] / lib / libsys / tsc_util.c
blobdfb1218e065e2ce2faf23133210629e2618395d4
2 #include <stdio.h>
3 #include <time.h>
4 #include <sys/times.h>
5 #include <sys/types.h>
6 #include <minix/u64.h>
7 #include <minix/config.h>
8 #include <minix/const.h>
10 #include "sysutil.h"
12 #define CALIBRATE_TICKS(h) ((h)/5)
13 #define MICROHZ 1000000 /* number of micros per second */
14 #define MICROSPERTICK(h) (MICROHZ/(h)) /* number of micros per HZ tick */
16 #define CALIBRATE \
17 if(!calibrated) { \
18 int r; \
19 if((r=tsc_calibrate()) != OK) \
20 panic("calibrate failed: %d", r); \
23 static u32_t calib_tsc, Hz = 0;
24 static int calibrated = 0;
26 int
27 tsc_calibrate(void)
29 u64_t start, end, diff;
30 struct tms tms;
31 unsigned long t = 0;
33 /* Get HZ. */
34 Hz = sys_hz();
36 /* Wait for clock to tick. */
37 while(!t || (t == times(&tms)))
38 t = times(&tms);
40 t++;
42 /* Wait for clock to tick CALIBRATE_TICKS times, and time
43 * this using the TSC.
45 read_tsc_64(&start);
46 while(times(&tms) < t+CALIBRATE_TICKS(Hz)) ;
47 read_tsc_64(&end);
49 diff = sub64(end, start);
50 if(ex64hi(diff) != 0)
51 panic("tsc_calibrate: CALIBRATE_TICKS too high for TSC frequency");
52 calib_tsc = ex64lo(diff);
53 #if 0
54 printf("tsc_calibrate: "
55 "%lu cycles/%d ticks of %d Hz; %lu cycles/s\n",
56 calib_tsc, CALIBRATE_TICKS(Hz), Hz,
57 div64u(mul64u(calib_tsc, Hz), CALIBRATE_TICKS(Hz)));
58 #endif
59 calibrated = 1;
61 return OK;
64 int
65 micro_delay(u32_t micros)
67 u64_t now, end;
69 /* Start of delay. */
70 read_tsc_64(&now);
72 CALIBRATE;
74 /* We have to know when to end the delay. */
75 end = add64u(now, div64u(mul64u(calib_tsc,
76 micros * Hz / CALIBRATE_TICKS(Hz)), MICROHZ));
78 /* If we have to wait for at least one HZ tick, use the regular
79 * tickdelay first. Round downwards on purpose, so the average
80 * half-tick we wait short (depending on where in the current tick
81 * we call tickdelay). We can correct for both overhead of tickdelay
82 * itself and the short wait in the busywait later.
84 if(micros >= MICROSPERTICK(Hz))
85 tickdelay(micros*Hz/MICROHZ);
87 /* Wait (the rest) of the delay time using busywait. */
88 while(cmp64(now, end) < 0)
89 read_tsc_64(&now);
91 return OK;
94 u32_t tsc_64_to_micros(u64_t tsc)
96 return tsc_to_micros(ex64lo(tsc), ex64hi(tsc));
99 u32_t tsc_to_micros(u32_t low, u32_t high)
101 u32_t micros;
103 if(high) {
104 return 0;
106 CALIBRATE;
108 micros = (div64u(mul64u(low, MICROHZ * CALIBRATE_TICKS(Hz)),
109 calib_tsc)/Hz);
111 return micros;