linux/arch/um/os-Linux/time.c
<<
>>
Prefs
   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}
 119