2006-01-18 17:42:42 -08:00
/*
2015-11-02 16:16:37 +00:00
* Copyright ( C ) 2015 Anton Ivanov ( aivanov @ { brocade . com , kot - begemot . co . uk } )
* Copyright ( C ) 2015 Thomas Meyer ( thomas @ m3y3r . de )
* Copyright ( C ) 2012 - 2014 Cisco Systems
2007-10-16 01:26:54 -07:00
* Copyright ( C ) 2000 - 2007 Jeff Dike ( jdike { addtoit , linux . intel } . com )
2006-01-18 17:42:42 -08:00
* Licensed under the GPL
*/
2007-10-16 01:26:54 -07:00
# include <stddef.h>
# include <errno.h>
# include <signal.h>
2006-01-18 17:42:42 -08:00
# include <time.h>
2005-04-16 15:20:36 -07:00
# include <sys/time.h>
2012-10-08 03:27:32 +01:00
# include <kern_util.h>
# include <os.h>
2015-11-02 16:16:37 +00:00
# include <string.h>
# include <timer-internal.h>
2006-01-18 17:42:42 -08:00
2015-11-02 16:16:37 +00:00
static timer_t event_high_res_timer = 0 ;
2006-09-25 23:33:05 -07:00
2015-11-02 16:16:37 +00:00
static inline long long timeval_to_ns ( const struct timeval * tv )
{
return ( ( long long ) tv - > tv_sec * UM_NSEC_PER_SEC ) +
tv - > tv_usec * UM_NSEC_PER_USEC ;
2006-01-18 17:42:42 -08:00
}
2015-11-02 16:16:37 +00:00
static inline long long timespec_to_ns ( const struct timespec * ts )
2007-10-16 01:27:25 -07:00
{
2019-05-06 14:39:38 +02:00
return ( ( long long ) ts - > tv_sec * UM_NSEC_PER_SEC ) + ts - > tv_nsec ;
2015-11-02 16:16:37 +00:00
}
2007-10-16 01:27:25 -07:00
2019-05-06 14:39:38 +02:00
long long os_persistent_clock_emulation ( void )
{
2015-11-02 16:16:37 +00:00
struct timespec realtime_tp ;
2007-10-16 01:27:25 -07:00
2015-11-02 16:16:37 +00:00
clock_gettime ( CLOCK_REALTIME , & realtime_tp ) ;
return timespec_to_ns ( & realtime_tp ) ;
2007-10-16 01:27:25 -07:00
}
2007-10-16 01:27:27 -07:00
/**
2015-11-02 16:16:37 +00:00
* os_timer_create ( ) - create an new posix ( interval ) timer
2007-10-16 01:27:27 -07:00
*/
2019-05-06 14:39:38 +02:00
int os_timer_create ( void )
{
timer_t * t = & event_high_res_timer ;
2015-11-02 16:16:37 +00:00
2019-05-06 14:39:38 +02:00
if ( timer_create ( CLOCK_MONOTONIC , NULL , t ) = = - 1 )
2015-11-02 16:16:37 +00:00
return - 1 ;
2019-05-06 14:39:38 +02:00
2015-11-02 16:16:37 +00:00
return 0 ;
2007-10-16 01:27:27 -07:00
}
2019-05-27 10:34:26 +02:00
int os_timer_set_interval ( unsigned long long nsecs )
2006-01-18 17:42:42 -08:00
{
2015-11-02 16:16:37 +00:00
struct itimerspec its ;
2007-10-16 01:27:22 -07:00
2019-05-27 10:34:26 +02:00
its . it_value . tv_sec = nsecs / UM_NSEC_PER_SEC ;
its . it_value . tv_nsec = nsecs % UM_NSEC_PER_SEC ;
2008-05-12 14:02:00 -07:00
2019-05-27 10:34:26 +02:00
its . it_interval . tv_sec = nsecs / UM_NSEC_PER_SEC ;
its . it_interval . tv_nsec = nsecs % UM_NSEC_PER_SEC ;
2005-04-16 15:20:36 -07:00
2019-05-06 14:39:38 +02:00
if ( timer_settime ( event_high_res_timer , 0 , & its , NULL ) = = - 1 )
2015-11-02 16:16:37 +00:00
return - errno ;
2005-04-16 15:20:36 -07:00
2007-12-01 12:16:29 -08:00
return 0 ;
2007-11-28 16:21:51 -08:00
}
2008-05-12 14:02:00 -07:00
2019-05-27 10:34:26 +02:00
int os_timer_one_shot ( unsigned long long nsecs )
2015-11-02 16:16:37 +00:00
{
2019-05-06 14:39:38 +02:00
struct itimerspec its = {
2019-05-27 10:34:26 +02:00
. it_value . tv_sec = nsecs / UM_NSEC_PER_SEC ,
. it_value . tv_nsec = nsecs % UM_NSEC_PER_SEC ,
2008-06-05 22:46:10 -07:00
2019-05-06 14:39:38 +02:00
. it_interval . tv_sec = 0 ,
. it_interval . tv_nsec = 0 , // we cheat here
} ;
2008-05-12 14:02:00 -07:00
2015-11-02 16:16:37 +00:00
timer_settime ( event_high_res_timer , 0 , & its , NULL ) ;
return 0 ;
2008-05-12 14:02:00 -07:00
}
2015-11-02 16:16:37 +00:00
/**
* os_timer_disable ( ) - disable the posix ( interval ) timer
*/
2019-05-06 14:39:38 +02:00
void os_timer_disable ( void )
2008-05-12 14:02:00 -07:00
{
2015-11-02 16:16:37 +00:00
struct itimerspec its ;
2008-05-12 14:02:00 -07:00
2015-11-02 16:16:37 +00:00
memset ( & its , 0 , sizeof ( struct itimerspec ) ) ;
2019-05-06 14:39:38 +02:00
timer_settime ( event_high_res_timer , 0 , & its , NULL ) ;
2015-11-02 16:16:37 +00:00
}
2007-11-28 16:21:51 -08:00
2015-11-02 16:16:37 +00:00
long long os_nsecs ( void )
{
struct timespec ts ;
2007-11-28 16:21:51 -08:00
2015-11-02 16:16:37 +00:00
clock_gettime ( CLOCK_MONOTONIC , & ts ) ;
return timespec_to_ns ( & ts ) ;
2007-11-28 16:21:51 -08:00
}
2015-11-02 16:16:37 +00:00
/**
* os_idle_sleep ( ) - sleep for a given time of nsecs
* @ nsecs : nanoseconds to sleep
*/
void os_idle_sleep ( unsigned long long nsecs )
2006-01-18 17:42:42 -08:00
{
2019-05-06 14:39:38 +02:00
struct timespec ts = {
. tv_sec = nsecs / UM_NSEC_PER_SEC ,
. tv_nsec = nsecs % UM_NSEC_PER_SEC
} ;
2006-01-18 17:42:42 -08:00
2015-11-02 16:16:37 +00:00
/*
* Relay the signal if clock_nanosleep is interrupted .
*/
2019-05-06 14:39:38 +02:00
if ( clock_nanosleep ( CLOCK_MONOTONIC , 0 , & ts , NULL ) )
2008-05-12 14:02:00 -07:00
deliver_alarm ( ) ;
2006-01-18 17:42:42 -08:00
}