Commit | Line | Data |
---|---|---|
97870c34 | 1 | // SPDX-License-Identifier: GPL-2.0 |
cff65c4f | 2 | /* |
2eb5f31b AI |
3 | * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk}) |
4 | * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de) | |
5 | * Copyright (C) 2012-2014 Cisco Systems | |
4c9e1385 | 6 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com) |
cff65c4f GS |
7 | */ |
8 | ||
4c9e1385 | 9 | #include <stddef.h> |
49da38a3 | 10 | #include <unistd.h> |
4c9e1385 JD |
11 | #include <errno.h> |
12 | #include <signal.h> | |
cff65c4f | 13 | #include <time.h> |
1da177e4 | 14 | #include <sys/time.h> |
37185b33 AV |
15 | #include <kern_util.h> |
16 | #include <os.h> | |
2eb5f31b | 17 | #include <string.h> |
cff65c4f | 18 | |
2eb5f31b | 19 | static timer_t event_high_res_timer = 0; |
537ae946 | 20 | |
2eb5f31b | 21 | static inline long long timespec_to_ns(const struct timespec *ts) |
d2753a6d | 22 | { |
56fc1870 | 23 | return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec; |
2eb5f31b | 24 | } |
d2753a6d | 25 | |
56fc1870 JB |
26 | long long os_persistent_clock_emulation(void) |
27 | { | |
2eb5f31b | 28 | struct timespec realtime_tp; |
d2753a6d | 29 | |
2eb5f31b AI |
30 | clock_gettime(CLOCK_REALTIME, &realtime_tp); |
31 | return timespec_to_ns(&realtime_tp); | |
d2753a6d JD |
32 | } |
33 | ||
5f734614 | 34 | /** |
2eb5f31b | 35 | * os_timer_create() - create an new posix (interval) timer |
5f734614 | 36 | */ |
56fc1870 JB |
37 | int os_timer_create(void) |
38 | { | |
39 | timer_t *t = &event_high_res_timer; | |
2eb5f31b | 40 | |
56fc1870 | 41 | if (timer_create(CLOCK_MONOTONIC, NULL, t) == -1) |
2eb5f31b | 42 | return -1; |
56fc1870 | 43 | |
2eb5f31b | 44 | return 0; |
5f734614 JD |
45 | } |
46 | ||
c7c6f3b9 | 47 | int os_timer_set_interval(unsigned long long nsecs) |
cff65c4f | 48 | { |
2eb5f31b | 49 | struct itimerspec its; |
181bde80 | 50 | |
c7c6f3b9 JB |
51 | its.it_value.tv_sec = nsecs / UM_NSEC_PER_SEC; |
52 | its.it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC; | |
fe2cc53e | 53 | |
c7c6f3b9 JB |
54 | its.it_interval.tv_sec = nsecs / UM_NSEC_PER_SEC; |
55 | its.it_interval.tv_nsec = nsecs % UM_NSEC_PER_SEC; | |
1da177e4 | 56 | |
56fc1870 | 57 | if (timer_settime(event_high_res_timer, 0, &its, NULL) == -1) |
2eb5f31b | 58 | return -errno; |
1da177e4 | 59 | |
0a765329 | 60 | return 0; |
364e3a3d | 61 | } |
fe2cc53e | 62 | |
c7c6f3b9 | 63 | int os_timer_one_shot(unsigned long long nsecs) |
2eb5f31b | 64 | { |
56fc1870 | 65 | struct itimerspec its = { |
c7c6f3b9 JB |
66 | .it_value.tv_sec = nsecs / UM_NSEC_PER_SEC, |
67 | .it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC, | |
06e1e4ff | 68 | |
56fc1870 JB |
69 | .it_interval.tv_sec = 0, |
70 | .it_interval.tv_nsec = 0, // we cheat here | |
71 | }; | |
fe2cc53e | 72 | |
2eb5f31b AI |
73 | timer_settime(event_high_res_timer, 0, &its, NULL); |
74 | return 0; | |
fe2cc53e JD |
75 | } |
76 | ||
2eb5f31b AI |
77 | /** |
78 | * os_timer_disable() - disable the posix (interval) timer | |
2eb5f31b | 79 | */ |
56fc1870 | 80 | void os_timer_disable(void) |
fe2cc53e | 81 | { |
2eb5f31b | 82 | struct itimerspec its; |
fe2cc53e | 83 | |
2eb5f31b | 84 | memset(&its, 0, sizeof(struct itimerspec)); |
56fc1870 | 85 | timer_settime(event_high_res_timer, 0, &its, NULL); |
2eb5f31b | 86 | } |
364e3a3d | 87 | |
2eb5f31b AI |
88 | long long os_nsecs(void) |
89 | { | |
90 | struct timespec ts; | |
364e3a3d | 91 | |
2eb5f31b AI |
92 | clock_gettime(CLOCK_MONOTONIC,&ts); |
93 | return timespec_to_ns(&ts); | |
364e3a3d | 94 | } |
364e3a3d | 95 | |
2eb5f31b | 96 | /** |
49da38a3 | 97 | * os_idle_sleep() - sleep until interrupted |
2eb5f31b | 98 | */ |
49da38a3 | 99 | void os_idle_sleep(void) |
cff65c4f | 100 | { |
9868c208 JB |
101 | struct itimerspec its; |
102 | sigset_t set, old; | |
103 | ||
104 | /* block SIGALRM while we analyze the timer state */ | |
105 | sigemptyset(&set); | |
106 | sigaddset(&set, SIGALRM); | |
107 | sigprocmask(SIG_BLOCK, &set, &old); | |
108 | ||
109 | /* check the timer, and if it'll fire then wait for it */ | |
110 | timer_gettime(event_high_res_timer, &its); | |
111 | if (its.it_value.tv_sec || its.it_value.tv_nsec) | |
112 | sigsuspend(&old); | |
113 | /* either way, restore the signal mask */ | |
114 | sigprocmask(SIG_UNBLOCK, &set, NULL); | |
cff65c4f | 115 | } |