18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk}) 48c2ecf20Sopenharmony_ci * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de) 58c2ecf20Sopenharmony_ci * Copyright (C) 2012-2014 Cisco Systems 68c2ecf20Sopenharmony_ci * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com) 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <stddef.h> 108c2ecf20Sopenharmony_ci#include <errno.h> 118c2ecf20Sopenharmony_ci#include <signal.h> 128c2ecf20Sopenharmony_ci#include <time.h> 138c2ecf20Sopenharmony_ci#include <sys/time.h> 148c2ecf20Sopenharmony_ci#include <kern_util.h> 158c2ecf20Sopenharmony_ci#include <os.h> 168c2ecf20Sopenharmony_ci#include <string.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistatic timer_t event_high_res_timer = 0; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic inline long long timeval_to_ns(const struct timeval *tv) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) + 238c2ecf20Sopenharmony_ci tv->tv_usec * UM_NSEC_PER_USEC; 248c2ecf20Sopenharmony_ci} 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic inline long long timespec_to_ns(const struct timespec *ts) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec; 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cilong long os_persistent_clock_emulation(void) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci struct timespec realtime_tp; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci clock_gettime(CLOCK_REALTIME, &realtime_tp); 368c2ecf20Sopenharmony_ci return timespec_to_ns(&realtime_tp); 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/** 408c2ecf20Sopenharmony_ci * os_timer_create() - create an new posix (interval) timer 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_ciint os_timer_create(void) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci timer_t *t = &event_high_res_timer; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci if (timer_create(CLOCK_MONOTONIC, NULL, t) == -1) 478c2ecf20Sopenharmony_ci return -1; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci return 0; 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciint os_timer_set_interval(unsigned long long nsecs) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci struct itimerspec its; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci its.it_value.tv_sec = nsecs / UM_NSEC_PER_SEC; 578c2ecf20Sopenharmony_ci its.it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci its.it_interval.tv_sec = nsecs / UM_NSEC_PER_SEC; 608c2ecf20Sopenharmony_ci its.it_interval.tv_nsec = nsecs % UM_NSEC_PER_SEC; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if (timer_settime(event_high_res_timer, 0, &its, NULL) == -1) 638c2ecf20Sopenharmony_ci return -errno; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci return 0; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ciint os_timer_one_shot(unsigned long long nsecs) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci struct itimerspec its = { 718c2ecf20Sopenharmony_ci .it_value.tv_sec = nsecs / UM_NSEC_PER_SEC, 728c2ecf20Sopenharmony_ci .it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC, 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci .it_interval.tv_sec = 0, 758c2ecf20Sopenharmony_ci .it_interval.tv_nsec = 0, // we cheat here 768c2ecf20Sopenharmony_ci }; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci timer_settime(event_high_res_timer, 0, &its, NULL); 798c2ecf20Sopenharmony_ci return 0; 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/** 838c2ecf20Sopenharmony_ci * os_timer_disable() - disable the posix (interval) timer 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_civoid os_timer_disable(void) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci struct itimerspec its; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci memset(&its, 0, sizeof(struct itimerspec)); 908c2ecf20Sopenharmony_ci timer_settime(event_high_res_timer, 0, &its, NULL); 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cilong long os_nsecs(void) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci struct timespec ts; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC,&ts); 988c2ecf20Sopenharmony_ci return timespec_to_ns(&ts); 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/** 1028c2ecf20Sopenharmony_ci * os_idle_sleep() - sleep for a given time of nsecs 1038c2ecf20Sopenharmony_ci * @nsecs: nanoseconds to sleep 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_civoid os_idle_sleep(unsigned long long nsecs) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci struct timespec ts = { 1088c2ecf20Sopenharmony_ci .tv_sec = nsecs / UM_NSEC_PER_SEC, 1098c2ecf20Sopenharmony_ci .tv_nsec = nsecs % UM_NSEC_PER_SEC 1108c2ecf20Sopenharmony_ci }; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci /* 1138c2ecf20Sopenharmony_ci * Relay the signal if clock_nanosleep is interrupted. 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci if (clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL)) 1168c2ecf20Sopenharmony_ci deliver_alarm(); 1178c2ecf20Sopenharmony_ci} 118