Skip to content

Commit 6ffa1aa

Browse files
jsun26intelwenlingz
authored andcommitted
DM: add acrn_timer api for timer emulation
We will use timerfd and epoll mechanism to emulate kinds of timers like PIT/RTC/WDT/PMTIMER/... in device model under Linux. The api is unified in this patch. Compare with sigevent mechanism, timerfd has a advantage that it could avoid race condition on resource accessing in the async sigev thread. change log: v1 -> v2: add NULL pointer check for function parameter; v2 -> v3: rename file name of vtimer.* to timer.*; rename structure name of vtimer to acrn_timer; add read() in timer handler to consume I/O event; v3 -> v4: replace bool clock_realtime with int clockid; close acrn_timer->fd properly; Tracked-On: #1489 Signed-off-by: Victor Sun <victor.sun@intel.com> Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com> Acked-by: Yin Fengwei <fengwei.yin@intel.com>
1 parent d9df6e9 commit 6ffa1aa

File tree

3 files changed

+149
-0
lines changed

3 files changed

+149
-0
lines changed

devicemodel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ SRCS += core/mptbl.c
122122
SRCS += core/main.c
123123
SRCS += core/hugetlb.c
124124
SRCS += core/vrpmb.c
125+
SRCS += core/timer.c
125126

126127
# arch
127128
SRCS += arch/x86/pm.c

devicemodel/core/timer.c

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright (C) <2018> Intel Corporation
3+
* SPDX-License-Identifier: BSD-3-Clause
4+
*/
5+
6+
#include <stdio.h>
7+
#include <stdbool.h>
8+
#include <unistd.h>
9+
#include <sys/timerfd.h>
10+
11+
#include "vmmapi.h"
12+
#include "mevent.h"
13+
#include "timer.h"
14+
15+
/* We can use timerfd and epoll mechanism to emulate kinds of timers like
16+
* PIT/RTC/WDT/PMTIMER/... in device model under Linux.
17+
* Compare with sigevent mechanism, timerfd has a advantage that it could
18+
* avoid race condition on resource accessing in the async sigev thread.
19+
*
20+
* Please note timerfd and epoll are all Linux specific. If the code need to be
21+
* ported to other OS, we can modify the api with POSIX timers and sigevent
22+
* mechanism.
23+
*/
24+
25+
static void
26+
timer_handler(int fd __attribute__((unused)),
27+
enum ev_type t __attribute__((unused)),
28+
void *arg)
29+
{
30+
struct acrn_timer *timer = arg;
31+
uint64_t buf;
32+
int32_t size;
33+
34+
if (timer == NULL) {
35+
return;
36+
}
37+
38+
/* Consume I/O event for default EPOLLLT type.
39+
* Here is a temporary solution, the processing could be moved to
40+
* mevent.c once EVF_TIMER is supported.
41+
*/
42+
size = read(timer->fd, &buf, sizeof(buf));
43+
if (size < 1) {
44+
fprintf(stderr, "acrn_timer read timerfd error!");
45+
return;
46+
}
47+
48+
if (timer->callback != NULL) {
49+
(*timer->callback)(timer->callback_param);
50+
}
51+
}
52+
53+
int32_t
54+
acrn_timer_init(struct acrn_timer *timer, void (*cb)(void *), void *param)
55+
{
56+
if ((timer == NULL) || (cb == NULL)) {
57+
return -1;
58+
}
59+
60+
timer->fd = -1;
61+
if ((timer->clockid == CLOCK_REALTIME) ||
62+
(timer->clockid == CLOCK_MONOTONIC)) {
63+
timer->fd = timerfd_create(timer->clockid,
64+
TFD_NONBLOCK | TFD_CLOEXEC);
65+
} else {
66+
perror("acrn_timer clockid is not supported.\n");
67+
}
68+
69+
if (timer->fd <= 0) {
70+
perror("acrn_timer create failed.\n");
71+
return -1;
72+
}
73+
74+
timer->mevp = mevent_add(timer->fd, EVF_READ, timer_handler, timer);
75+
if (timer->mevp == NULL) {
76+
close(timer->fd);
77+
perror("acrn_timer mevent add failed.\n");
78+
return -1;
79+
}
80+
81+
timer->callback = cb;
82+
timer->callback_param = param;
83+
84+
return 0;
85+
}
86+
87+
void
88+
acrn_timer_deinit(struct acrn_timer *timer)
89+
{
90+
if (timer == NULL) {
91+
return;
92+
}
93+
94+
if (timer->mevp != NULL) {
95+
mevent_delete_close(timer->mevp);
96+
timer->mevp = NULL;
97+
}
98+
99+
timer->fd = -1;
100+
timer->callback = NULL;
101+
timer->callback_param = NULL;
102+
}
103+
104+
int32_t
105+
acrn_timer_settime(struct acrn_timer *timer, struct itimerspec *new_value)
106+
{
107+
if (timer == NULL) {
108+
return -1;
109+
}
110+
111+
return timerfd_settime(timer->fd, 0, new_value, NULL);
112+
}
113+
114+
int32_t
115+
acrn_timer_gettime(struct acrn_timer *timer, struct itimerspec *cur_value)
116+
{
117+
if (timer == NULL) {
118+
return -1;
119+
}
120+
121+
return timerfd_gettime(timer->fd, cur_value);
122+
}

devicemodel/include/timer.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (C) <2018> Intel Corporation
3+
* SPDX-License-Identifier: BSD-3-Clause
4+
*/
5+
6+
#ifndef _TIMER_H_
7+
#define _TIMER_H_
8+
9+
struct acrn_timer {
10+
int32_t fd;
11+
int32_t clockid;
12+
struct mevent *mevp;
13+
void (*callback)(void *);
14+
void *callback_param;
15+
};
16+
17+
int32_t
18+
acrn_timer_init(struct acrn_timer *timer, void (*cb)(void *), void *param);
19+
void
20+
acrn_timer_deinit(struct acrn_timer *timer);
21+
int32_t
22+
acrn_timer_settime(struct acrn_timer *timer, struct itimerspec *new_value);
23+
int32_t
24+
acrn_timer_gettime(struct acrn_timer *timer, struct itimerspec *cur_value);
25+
26+
#endif /* _VTIMER_ */

0 commit comments

Comments
 (0)