1 /* public domain, no copyright claimed */
2
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <assert.h>
6 #include <time.h>
7 #include <math.h>
8 #include <unistd.h>
9
10 #include <stdint.h>
11 #include <stdbool.h>
12
13 #ifdef __OpenBSD__
14 #include <sys/types.h>
15 #include <sys/sysctl.h>
16 #endif
17
18 #include "../platform_types.h"
19
arcan_timemillis()20 long long int arcan_timemillis()
21 {
22 struct timespec tp;
23 clock_gettime(CLOCK_MONOTONIC, &tp);
24 return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000);
25 }
26
arcan_timemicros()27 long long int arcan_timemicros()
28 {
29 struct timespec tp;
30 clock_gettime(CLOCK_MONOTONIC, &tp);
31 return (tp.tv_sec * 1000000) + (tp.tv_nsec / 1000);
32 }
33
platform_hardware_clockcfg()34 struct platform_timing platform_hardware_clockcfg()
35 {
36 #ifdef __OpenBSD__
37 int mib[2] = {CTL_KERN, KERN_CLOCKRATE};
38 struct clockinfo cinf;
39 size_t len = sizeof(struct clockinfo);
40 if (sysctl(mib, 2, &cinf, &len, NULL, 0) != -1){
41 return (struct platform_timing){
42 .cost_us = cinf.tick,
43 .tickless = false
44 };
45 }
46 else {
47 return (struct platform_timing){
48 .cost_us = 10 * 1000,
49 .tickless = false
50 };
51 }
52 #else
53 return (struct platform_timing){
54 .cost_us = 0,
55 .tickless = true
56 };
57 #endif
58 }
59
arcan_timesleep(unsigned long val)60 void arcan_timesleep(unsigned long val)
61 {
62 struct timespec req, rem;
63 req.tv_sec = floor(val / 1000);
64 val -= req.tv_sec * 1000;
65 req.tv_nsec = val * 1000000;
66
67 while( nanosleep(&req, &rem) == -1 ){
68 assert(errno != EINVAL);
69 if (errno == EFAULT)
70 break;
71
72 /* sweeping EINTR introduces an error rate that can grow large,
73 * check if the remaining time is less than a threshold */
74 if (errno == EINTR) {
75 req = rem;
76 if (rem.tv_sec * 1000 + (1 + req.tv_nsec) / 1000000 < 4)
77 break;
78 }
79 }
80 }
81