1// SPDX-License-Identifier: GPL-2.0 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) 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 18static timer_t event_high_res_timer = 0; 19 20static 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 26static inline long long timespec_to_ns(const struct timespec *ts) 27{ 28 return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec; 29} 30 31long long os_persistent_clock_emulation(void) 32{ 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 */ 42int os_timer_create(void) 43{ 44 timer_t *t = &event_high_res_timer; 45 46 if (timer_create(CLOCK_MONOTONIC, NULL, t) == -1) 47 return -1; 48 49 return 0; 50} 51 52int os_timer_set_interval(unsigned long long nsecs) 53{ 54 struct itimerspec its; 55 56 its.it_value.tv_sec = nsecs / UM_NSEC_PER_SEC; 57 its.it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC; 58 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) 63 return -errno; 64 65 return 0; 66} 67 68int os_timer_one_shot(unsigned long long nsecs) 69{ 70 struct itimerspec its = { 71 .it_value.tv_sec = nsecs / UM_NSEC_PER_SEC, 72 .it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC, 73 74 .it_interval.tv_sec = 0, 75 .it_interval.tv_nsec = 0, // we cheat here 76 }; 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 84 */ 85void os_timer_disable(void) 86{ 87 struct itimerspec its; 88 89 memset(&its, 0, sizeof(struct itimerspec)); 90 timer_settime(event_high_res_timer, 0, &its, NULL); 91} 92 93long 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 */ 105void os_idle_sleep(unsigned long long nsecs) 106{ 107 struct timespec ts = { 108 .tv_sec = nsecs / UM_NSEC_PER_SEC, 109 .tv_nsec = nsecs % UM_NSEC_PER_SEC 110 }; 111 112 /* 113 * Relay the signal if clock_nanosleep is interrupted. 114 */ 115 if (clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL)) 116 deliver_alarm(); 117} 118