Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v5.5-rc2 118 lines 2.6 kB view raw
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#include <timer-internal.h> 18 19static timer_t event_high_res_timer = 0; 20 21static 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 27static inline long long timespec_to_ns(const struct timespec *ts) 28{ 29 return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec; 30} 31 32long long os_persistent_clock_emulation(void) 33{ 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 */ 43int os_timer_create(void) 44{ 45 timer_t *t = &event_high_res_timer; 46 47 if (timer_create(CLOCK_MONOTONIC, NULL, t) == -1) 48 return -1; 49 50 return 0; 51} 52 53int os_timer_set_interval(unsigned long long nsecs) 54{ 55 struct itimerspec its; 56 57 its.it_value.tv_sec = nsecs / UM_NSEC_PER_SEC; 58 its.it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC; 59 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) 64 return -errno; 65 66 return 0; 67} 68 69int os_timer_one_shot(unsigned long long nsecs) 70{ 71 struct itimerspec its = { 72 .it_value.tv_sec = nsecs / UM_NSEC_PER_SEC, 73 .it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC, 74 75 .it_interval.tv_sec = 0, 76 .it_interval.tv_nsec = 0, // we cheat here 77 }; 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 85 */ 86void os_timer_disable(void) 87{ 88 struct itimerspec its; 89 90 memset(&its, 0, sizeof(struct itimerspec)); 91 timer_settime(event_high_res_timer, 0, &its, NULL); 92} 93 94long 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 */ 106void os_idle_sleep(unsigned long long nsecs) 107{ 108 struct timespec ts = { 109 .tv_sec = nsecs / UM_NSEC_PER_SEC, 110 .tv_nsec = nsecs % UM_NSEC_PER_SEC 111 }; 112 113 /* 114 * Relay the signal if clock_nanosleep is interrupted. 115 */ 116 if (clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL)) 117 deliver_alarm(); 118}