time.c (2577B)
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 <unistd.h> 11#include <errno.h> 12#include <signal.h> 13#include <time.h> 14#include <sys/time.h> 15#include <kern_util.h> 16#include <os.h> 17#include <string.h> 18 19static timer_t event_high_res_timer = 0; 20 21static inline long long timespec_to_ns(const struct timespec *ts) 22{ 23 return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec; 24} 25 26long long os_persistent_clock_emulation(void) 27{ 28 struct timespec realtime_tp; 29 30 clock_gettime(CLOCK_REALTIME, &realtime_tp); 31 return timespec_to_ns(&realtime_tp); 32} 33 34/** 35 * os_timer_create() - create an new posix (interval) timer 36 */ 37int os_timer_create(void) 38{ 39 timer_t *t = &event_high_res_timer; 40 41 if (timer_create(CLOCK_MONOTONIC, NULL, t) == -1) 42 return -1; 43 44 return 0; 45} 46 47int os_timer_set_interval(unsigned long long nsecs) 48{ 49 struct itimerspec its; 50 51 its.it_value.tv_sec = nsecs / UM_NSEC_PER_SEC; 52 its.it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC; 53 54 its.it_interval.tv_sec = nsecs / UM_NSEC_PER_SEC; 55 its.it_interval.tv_nsec = nsecs % UM_NSEC_PER_SEC; 56 57 if (timer_settime(event_high_res_timer, 0, &its, NULL) == -1) 58 return -errno; 59 60 return 0; 61} 62 63int os_timer_one_shot(unsigned long long nsecs) 64{ 65 struct itimerspec its = { 66 .it_value.tv_sec = nsecs / UM_NSEC_PER_SEC, 67 .it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC, 68 69 .it_interval.tv_sec = 0, 70 .it_interval.tv_nsec = 0, // we cheat here 71 }; 72 73 timer_settime(event_high_res_timer, 0, &its, NULL); 74 return 0; 75} 76 77/** 78 * os_timer_disable() - disable the posix (interval) timer 79 */ 80void os_timer_disable(void) 81{ 82 struct itimerspec its; 83 84 memset(&its, 0, sizeof(struct itimerspec)); 85 timer_settime(event_high_res_timer, 0, &its, NULL); 86} 87 88long long os_nsecs(void) 89{ 90 struct timespec ts; 91 92 clock_gettime(CLOCK_MONOTONIC,&ts); 93 return timespec_to_ns(&ts); 94} 95 96/** 97 * os_idle_sleep() - sleep until interrupted 98 */ 99void os_idle_sleep(void) 100{ 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); 115}