1 /* 2 * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk}) 3 * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de) 4 * Copyright (C) 2012-2014 Cisco Systems 5 * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com) 6 * Licensed under the GPL 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 { 29 return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec; 30 } 31 32 long 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 */ 43 int 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 53 int 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 69 int 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 */ 86 void 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 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 { 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 } 119