David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 2 | /* |
| 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 |
| 6 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com) |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 7 | */ |
| 8 | |
| 9 | #include <stddef.h> |
| 10 | #include <errno.h> |
| 11 | #include <signal.h> |
| 12 | #include <time.h> |
| 13 | #include <sys/time.h> |
| 14 | #include <kern_util.h> |
| 15 | #include <os.h> |
| 16 | #include <string.h> |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 17 | |
| 18 | static timer_t event_high_res_timer = 0; |
| 19 | |
| 20 | static inline long long timeval_to_ns(const struct timeval *tv) |
| 21 | { |
| 22 | return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) + |
| 23 | tv->tv_usec * UM_NSEC_PER_USEC; |
| 24 | } |
| 25 | |
| 26 | static inline long long timespec_to_ns(const struct timespec *ts) |
| 27 | { |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 28 | return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 29 | } |
| 30 | |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 31 | long long os_persistent_clock_emulation(void) |
| 32 | { |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 33 | struct timespec realtime_tp; |
| 34 | |
| 35 | clock_gettime(CLOCK_REALTIME, &realtime_tp); |
| 36 | return timespec_to_ns(&realtime_tp); |
| 37 | } |
| 38 | |
| 39 | /** |
| 40 | * os_timer_create() - create an new posix (interval) timer |
| 41 | */ |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 42 | int os_timer_create(void) |
| 43 | { |
| 44 | timer_t *t = &event_high_res_timer; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 45 | |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 46 | if (timer_create(CLOCK_MONOTONIC, NULL, t) == -1) |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 47 | return -1; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 48 | |
| 49 | return 0; |
| 50 | } |
| 51 | |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 52 | int os_timer_set_interval(unsigned long long nsecs) |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 53 | { |
| 54 | struct itimerspec its; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 55 | |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 56 | its.it_value.tv_sec = nsecs / UM_NSEC_PER_SEC; |
| 57 | its.it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 58 | |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 59 | its.it_interval.tv_sec = nsecs / UM_NSEC_PER_SEC; |
| 60 | its.it_interval.tv_nsec = nsecs % UM_NSEC_PER_SEC; |
| 61 | |
| 62 | if (timer_settime(event_high_res_timer, 0, &its, NULL) == -1) |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 63 | return -errno; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 64 | |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 65 | return 0; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 66 | } |
| 67 | |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 68 | int os_timer_one_shot(unsigned long long nsecs) |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 69 | { |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 70 | struct itimerspec its = { |
| 71 | .it_value.tv_sec = nsecs / UM_NSEC_PER_SEC, |
| 72 | .it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC, |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 73 | |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 74 | .it_interval.tv_sec = 0, |
| 75 | .it_interval.tv_nsec = 0, // we cheat here |
| 76 | }; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 77 | |
| 78 | timer_settime(event_high_res_timer, 0, &its, NULL); |
| 79 | return 0; |
| 80 | } |
| 81 | |
| 82 | /** |
| 83 | * os_timer_disable() - disable the posix (interval) timer |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 84 | */ |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 85 | void os_timer_disable(void) |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 86 | { |
| 87 | struct itimerspec its; |
| 88 | |
| 89 | memset(&its, 0, sizeof(struct itimerspec)); |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 90 | timer_settime(event_high_res_timer, 0, &its, NULL); |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 91 | } |
| 92 | |
| 93 | long long os_nsecs(void) |
| 94 | { |
| 95 | struct timespec ts; |
| 96 | |
| 97 | clock_gettime(CLOCK_MONOTONIC,&ts); |
| 98 | return timespec_to_ns(&ts); |
| 99 | } |
| 100 | |
| 101 | /** |
| 102 | * os_idle_sleep() - sleep for a given time of nsecs |
| 103 | * @nsecs: nanoseconds to sleep |
| 104 | */ |
| 105 | void os_idle_sleep(unsigned long long nsecs) |
| 106 | { |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 107 | struct timespec ts = { |
| 108 | .tv_sec = nsecs / UM_NSEC_PER_SEC, |
| 109 | .tv_nsec = nsecs % UM_NSEC_PER_SEC |
| 110 | }; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 111 | |
| 112 | /* |
| 113 | * Relay the signal if clock_nanosleep is interrupted. |
| 114 | */ |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 115 | if (clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL)) |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 116 | deliver_alarm(); |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 117 | } |