dm: provide timer callback handlers the number of expirations

It is possible for multiple timeouts to occur in one mevent epoll
iteration. Providing the number of timer expirations to the timer
callback handlers can be useful. E.g., this could improve emulation of
timing-sensitive hardware components.

Tracked-On: #2319
Signed-off-by: Peter Fang <peter.fang@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
Peter Fang 2019-01-10 19:03:30 -08:00 committed by wenlingz
parent 0f7535fdbe
commit 3fe4c3f2a8
5 changed files with 24 additions and 14 deletions

View File

@ -6,6 +6,8 @@
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <sys/timerfd.h>
#include "vmmapi.h"
@ -28,8 +30,9 @@ timer_handler(int fd __attribute__((unused)),
void *arg)
{
struct acrn_timer *timer = arg;
uint64_t buf;
int32_t size;
uint64_t nexp;
ssize_t size;
void (*cb)(void *, uint64_t);
if (timer == NULL) {
return;
@ -39,19 +42,25 @@ timer_handler(int fd __attribute__((unused)),
* Here is a temporary solution, the processing could be moved to
* mevent.c once EVF_TIMER is supported.
*/
size = read(timer->fd, &buf, sizeof(buf));
if (size < 1) {
fprintf(stderr, "acrn_timer read timerfd error!");
size = read(timer->fd, &nexp, sizeof(nexp));
if (size < 0) {
if (errno != EAGAIN) {
perror("acrn_timer read timerfd error");
}
return;
}
if (timer->callback != NULL) {
(*timer->callback)(timer->callback_param);
assert(size > 0 && nexp > 0);
if ((cb = timer->callback) != NULL) {
(*cb)(timer->callback_param, nexp);
}
}
int32_t
acrn_timer_init(struct acrn_timer *timer, void (*cb)(void *), void *param)
acrn_timer_init(struct acrn_timer *timer, void (*cb)(void *, uint64_t),
void *param)
{
if ((timer == NULL) || (cb == NULL)) {
return -1;

View File

@ -66,7 +66,7 @@ virtio_start_timer(struct acrn_timer *timer, time_t sec, time_t nsec)
}
static void
virtio_poll_timer(void *arg)
virtio_poll_timer(void *arg, uint64_t nexp)
{
struct virtio_base *base;
struct virtio_ops *vops;

View File

@ -110,7 +110,7 @@ static void start_wdt_timer(void);
* action to guest OS
*/
static void
wdt_expired_handler(void *arg)
wdt_expired_handler(void *arg, uint64_t nexp)
{
struct pci_vdev *dev = (struct pci_vdev *)arg;

View File

@ -660,7 +660,7 @@ vrtc_time_update(struct vrtc *vrtc, time_t newtime, time_t newbase)
}
static void
vrtc_periodic_timer(void *arg)
vrtc_periodic_timer(void *arg, uint64_t nexp)
{
struct vrtc *vrtc = arg;
@ -673,13 +673,14 @@ vrtc_periodic_timer(void *arg)
}
static void
vrtc_update_timer(void *arg)
vrtc_update_timer(void *arg, uint64_t nexp)
{
struct vrtc *vrtc = arg;
time_t basetime;
time_t curtime;
pthread_mutex_lock(&vrtc->mtx);
if (aintr_enabled(vrtc) || uintr_enabled(vrtc)) {
curtime = vrtc_curtime(vrtc, &basetime);
vrtc_time_update(vrtc, curtime, basetime);

View File

@ -10,12 +10,12 @@ struct acrn_timer {
int32_t fd;
int32_t clockid;
struct mevent *mevp;
void (*callback)(void *);
void (*callback)(void *, uint64_t);
void *callback_param;
};
int32_t
acrn_timer_init(struct acrn_timer *timer, void (*cb)(void *), void *param);
acrn_timer_init(struct acrn_timer *timer, void (*cb)(void *, uint64_t), void *param);
void
acrn_timer_deinit(struct acrn_timer *timer);
int32_t