Alex Dewar | 97870c3 | 2019-08-25 10:49:18 +0100 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
Gennady Sharapov | cff65c4 | 2006-01-18 17:42:42 -0800 | [diff] [blame] | 2 | /* |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 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 |
Jeff Dike | 4c9e138 | 2007-10-16 01:26:54 -0700 | [diff] [blame] | 6 | * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com) |
Gennady Sharapov | cff65c4 | 2006-01-18 17:42:42 -0800 | [diff] [blame] | 7 | */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8 | |
Jeff Dike | 4c9e138 | 2007-10-16 01:26:54 -0700 | [diff] [blame] | 9 | #include <stddef.h> |
Johannes Berg | 49da38a | 2020-12-02 20:58:04 +0100 | [diff] [blame] | 10 | #include <unistd.h> |
Jeff Dike | 4c9e138 | 2007-10-16 01:26:54 -0700 | [diff] [blame] | 11 | #include <errno.h> |
| 12 | #include <signal.h> |
Gennady Sharapov | cff65c4 | 2006-01-18 17:42:42 -0800 | [diff] [blame] | 13 | #include <time.h> |
| 14 | #include <sys/time.h> |
Al Viro | 37185b3 | 2012-10-08 03:27:32 +0100 | [diff] [blame] | 15 | #include <kern_util.h> |
| 16 | #include <os.h> |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 17 | #include <string.h> |
Gennady Sharapov | cff65c4 | 2006-01-18 17:42:42 -0800 | [diff] [blame] | 18 | |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 19 | static timer_t event_high_res_timer = 0; |
Gennady Sharapov | cff65c4 | 2006-01-18 17:42:42 -0800 | [diff] [blame] | 20 | |
Jeff Dike | 5f73461 | 2007-10-16 01:27:27 -0700 | [diff] [blame] | 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 | |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 27 | static inline long long timespec_to_ns(const struct timespec *ts) |
Gennady Sharapov | cff65c4 | 2006-01-18 17:42:42 -0800 | [diff] [blame] | 28 | { |
Johannes Berg | 56fc187 | 2019-05-06 14:39:38 +0200 | [diff] [blame] | 29 | return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec; |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 30 | } |
Jeff Dike | 4c9e138 | 2007-10-16 01:26:54 -0700 | [diff] [blame] | 31 | |
Johannes Berg | 56fc187 | 2019-05-06 14:39:38 +0200 | [diff] [blame] | 32 | long long os_persistent_clock_emulation(void) |
| 33 | { |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 34 | struct timespec realtime_tp; |
Gennady Sharapov | cff65c4 | 2006-01-18 17:42:42 -0800 | [diff] [blame] | 35 | |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 36 | clock_gettime(CLOCK_REALTIME, &realtime_tp); |
| 37 | return timespec_to_ns(&realtime_tp); |
| 38 | } |
Jeff Dike | fe2cc53 | 2008-05-12 14:02:00 -0700 | [diff] [blame] | 39 | |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 40 | /** |
| 41 | * os_timer_create() - create an new posix (interval) timer |
| 42 | */ |
Johannes Berg | 56fc187 | 2019-05-06 14:39:38 +0200 | [diff] [blame] | 43 | int os_timer_create(void) |
| 44 | { |
| 45 | timer_t *t = &event_high_res_timer; |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 46 | |
Johannes Berg | 56fc187 | 2019-05-06 14:39:38 +0200 | [diff] [blame] | 47 | if (timer_create(CLOCK_MONOTONIC, NULL, t) == -1) |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 48 | return -1; |
Johannes Berg | 56fc187 | 2019-05-06 14:39:38 +0200 | [diff] [blame] | 49 | |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 50 | return 0; |
| 51 | } |
| 52 | |
Johannes Berg | c7c6f3b | 2019-05-27 10:34:26 +0200 | [diff] [blame] | 53 | int os_timer_set_interval(unsigned long long nsecs) |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 54 | { |
| 55 | struct itimerspec its; |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 56 | |
Johannes Berg | c7c6f3b | 2019-05-27 10:34:26 +0200 | [diff] [blame] | 57 | its.it_value.tv_sec = nsecs / UM_NSEC_PER_SEC; |
| 58 | its.it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC; |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 59 | |
Johannes Berg | c7c6f3b | 2019-05-27 10:34:26 +0200 | [diff] [blame] | 60 | its.it_interval.tv_sec = nsecs / UM_NSEC_PER_SEC; |
| 61 | its.it_interval.tv_nsec = nsecs % UM_NSEC_PER_SEC; |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 62 | |
Johannes Berg | 56fc187 | 2019-05-06 14:39:38 +0200 | [diff] [blame] | 63 | if (timer_settime(event_high_res_timer, 0, &its, NULL) == -1) |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 64 | return -errno; |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 65 | |
| 66 | return 0; |
| 67 | } |
| 68 | |
Johannes Berg | c7c6f3b | 2019-05-27 10:34:26 +0200 | [diff] [blame] | 69 | int os_timer_one_shot(unsigned long long nsecs) |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 70 | { |
Johannes Berg | 56fc187 | 2019-05-06 14:39:38 +0200 | [diff] [blame] | 71 | struct itimerspec its = { |
Johannes Berg | c7c6f3b | 2019-05-27 10:34:26 +0200 | [diff] [blame] | 72 | .it_value.tv_sec = nsecs / UM_NSEC_PER_SEC, |
| 73 | .it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC, |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 74 | |
Johannes Berg | 56fc187 | 2019-05-06 14:39:38 +0200 | [diff] [blame] | 75 | .it_interval.tv_sec = 0, |
| 76 | .it_interval.tv_nsec = 0, // we cheat here |
| 77 | }; |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +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 |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 85 | */ |
Johannes Berg | 56fc187 | 2019-05-06 14:39:38 +0200 | [diff] [blame] | 86 | void os_timer_disable(void) |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 87 | { |
| 88 | struct itimerspec its; |
| 89 | |
| 90 | memset(&its, 0, sizeof(struct itimerspec)); |
Johannes Berg | 56fc187 | 2019-05-06 14:39:38 +0200 | [diff] [blame] | 91 | timer_settime(event_high_res_timer, 0, &its, NULL); |
Gennady Sharapov | cff65c4 | 2006-01-18 17:42:42 -0800 | [diff] [blame] | 92 | } |
| 93 | |
Jeff Dike | 5f73461 | 2007-10-16 01:27:27 -0700 | [diff] [blame] | 94 | long long os_nsecs(void) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 95 | { |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 96 | struct timespec ts; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 97 | |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 98 | clock_gettime(CLOCK_MONOTONIC,&ts); |
| 99 | return timespec_to_ns(&ts); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 100 | } |
| 101 | |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 102 | /** |
Johannes Berg | 49da38a | 2020-12-02 20:58:04 +0100 | [diff] [blame] | 103 | * os_idle_sleep() - sleep until interrupted |
Anton Ivanov | 2eb5f31 | 2015-11-02 16:16:37 +0000 | [diff] [blame] | 104 | */ |
Johannes Berg | 49da38a | 2020-12-02 20:58:04 +0100 | [diff] [blame] | 105 | void os_idle_sleep(void) |
Jeff Dike | b160fb6 | 2007-10-16 01:27:26 -0700 | [diff] [blame] | 106 | { |
Johannes Berg | 49da38a | 2020-12-02 20:58:04 +0100 | [diff] [blame] | 107 | pause(); |
Gennady Sharapov | cff65c4 | 2006-01-18 17:42:42 -0800 | [diff] [blame] | 108 | } |