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