Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/um/os-Linux/time.c
26442 views
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 ([email protected])
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 <unistd.h>
11
#include <errno.h>
12
#include <signal.h>
13
#include <time.h>
14
#include <sys/time.h>
15
#include <kern_util.h>
16
#include <os.h>
17
#include <string.h>
18
19
static timer_t event_high_res_timer = 0;
20
21
static inline long long timespec_to_ns(const struct timespec *ts)
22
{
23
return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec;
24
}
25
26
long long os_persistent_clock_emulation(void)
27
{
28
struct timespec realtime_tp;
29
30
clock_gettime(CLOCK_REALTIME, &realtime_tp);
31
return timespec_to_ns(&realtime_tp);
32
}
33
34
/**
35
* os_timer_create() - create an new posix (interval) timer
36
*/
37
int os_timer_create(void)
38
{
39
timer_t *t = &event_high_res_timer;
40
41
if (timer_create(CLOCK_MONOTONIC, NULL, t) == -1)
42
return -1;
43
44
return 0;
45
}
46
47
int os_timer_set_interval(unsigned long long nsecs)
48
{
49
struct itimerspec its;
50
51
its.it_value.tv_sec = nsecs / UM_NSEC_PER_SEC;
52
its.it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC;
53
54
its.it_interval.tv_sec = nsecs / UM_NSEC_PER_SEC;
55
its.it_interval.tv_nsec = nsecs % UM_NSEC_PER_SEC;
56
57
if (timer_settime(event_high_res_timer, 0, &its, NULL) == -1)
58
return -errno;
59
60
return 0;
61
}
62
63
int os_timer_one_shot(unsigned long long nsecs)
64
{
65
struct itimerspec its = {
66
.it_value.tv_sec = nsecs / UM_NSEC_PER_SEC,
67
.it_value.tv_nsec = nsecs % UM_NSEC_PER_SEC,
68
69
.it_interval.tv_sec = 0,
70
.it_interval.tv_nsec = 0, // we cheat here
71
};
72
73
timer_settime(event_high_res_timer, 0, &its, NULL);
74
return 0;
75
}
76
77
/**
78
* os_timer_disable() - disable the posix (interval) timer
79
*/
80
void os_timer_disable(void)
81
{
82
struct itimerspec its;
83
84
memset(&its, 0, sizeof(struct itimerspec));
85
timer_settime(event_high_res_timer, 0, &its, NULL);
86
}
87
88
long long os_nsecs(void)
89
{
90
struct timespec ts;
91
92
clock_gettime(CLOCK_MONOTONIC,&ts);
93
return timespec_to_ns(&ts);
94
}
95
96
/**
97
* os_idle_sleep() - sleep until interrupted
98
*/
99
void os_idle_sleep(void)
100
{
101
struct itimerspec its;
102
sigset_t set, old;
103
104
/* block SIGALRM while we analyze the timer state */
105
sigemptyset(&set);
106
sigaddset(&set, SIGALRM);
107
sigprocmask(SIG_BLOCK, &set, &old);
108
109
/* check the timer, and if it'll fire then wait for it */
110
timer_gettime(event_high_res_timer, &its);
111
if (its.it_value.tv_sec || its.it_value.tv_nsec)
112
sigsuspend(&old);
113
/* either way, restore the signal mask */
114
sigprocmask(SIG_UNBLOCK, &set, NULL);
115
}
116
117