mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-21 13:08:42 +00:00
DM: mevent_add/del refine for Linux
Unlike kqueue/kevent of BSD, the epoll of Linux could be add/del by using different API on the fly. This patch drops the notify used by mevent_add/del and call epoll_ctl to add/delete target fd. Only keeps global_head to track mevent added and makes the code logic in mevent_dispatch() a littel bit simpler. Another thing is related with epoll_ctl. If the target fd is regular fd which doesn't support epoll, epoll_ctl will return -1. When DM is start by systemd, the STDIO is not mapped to terminal, epoll_ctl on STDIO could return -1. Which block UOS boot. We only call mevent_add after confirm STDIO is mapped to terminal. Signed-off-by: Yin Fengwei <fengwei.yin@intel.com> Reviewed-by: Zhao Yakui <yakui.zhao@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
parent
7ed912a088
commit
ecf619cb95
170
core/mevent.c
170
core/mevent.c
@ -75,13 +75,7 @@ struct mevent {
|
|||||||
LIST_ENTRY(mevent) me_list;
|
LIST_ENTRY(mevent) me_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ctl_event {
|
static LIST_HEAD(listhead, mevent) global_head;
|
||||||
int op;
|
|
||||||
int fd;
|
|
||||||
struct epoll_event ee;
|
|
||||||
};
|
|
||||||
|
|
||||||
static LIST_HEAD(listhead, mevent) global_head, change_head;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mevent_qlock(void)
|
mevent_qlock(void)
|
||||||
@ -141,80 +135,25 @@ mevent_kq_filter(struct mevent *mevp)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
mevent_kq_flags(struct mevent *mevp)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
switch (mevp->me_state) {
|
|
||||||
case MEV_ADD:
|
|
||||||
ret = EPOLL_CTL_ADD; /* implicitly enabled */
|
|
||||||
break;
|
|
||||||
case MEV_DEL_PENDING:
|
|
||||||
ret = EPOLL_CTL_DEL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
mevent_build(int mfd, struct ctl_event *kev)
|
|
||||||
{
|
|
||||||
struct mevent *mevp, *tmpp;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
mevent_qlock();
|
|
||||||
|
|
||||||
list_foreach_safe(mevp, &change_head, me_list, tmpp) {
|
|
||||||
if (mevp->me_closefd) {
|
|
||||||
/*
|
|
||||||
* A close of the file descriptor will remove the
|
|
||||||
* event
|
|
||||||
*/
|
|
||||||
close(mevp->me_fd);
|
|
||||||
} else {
|
|
||||||
kev[i].fd = mevp->me_fd;
|
|
||||||
kev[i].ee.events = mevent_kq_filter(mevp);
|
|
||||||
kev[i].op = mevent_kq_flags(mevp);
|
|
||||||
kev[i].ee.data.ptr = mevp;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
mevp->me_cq = 0;
|
|
||||||
LIST_REMOVE(mevp, me_list);
|
|
||||||
|
|
||||||
if (mevp->me_state == MEV_DEL_PENDING)
|
|
||||||
free(mevp);
|
|
||||||
else
|
|
||||||
LIST_INSERT_HEAD(&global_head, mevp, me_list);
|
|
||||||
|
|
||||||
assert(i < MEVENT_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
mevent_qunlock();
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mevent_destroy()
|
mevent_destroy()
|
||||||
{
|
{
|
||||||
struct mevent *mevp, *tmpp;
|
struct mevent *mevp, *tmpp;
|
||||||
|
struct epoll_event ee;
|
||||||
|
|
||||||
mevent_qlock();
|
mevent_qlock();
|
||||||
|
|
||||||
list_foreach_safe(mevp, &global_head, me_list, tmpp) {
|
list_foreach_safe(mevp, &global_head, me_list, tmpp) {
|
||||||
|
LIST_REMOVE(mevp, me_list);
|
||||||
|
ee.events = mevent_kq_filter(mevp);
|
||||||
|
ee.data.ptr = mevp;
|
||||||
|
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, mevp->me_fd, &ee);
|
||||||
|
|
||||||
if ((mevp->me_type == EVF_READ ||
|
if ((mevp->me_type == EVF_READ ||
|
||||||
mevp->me_type == EVF_WRITE)
|
mevp->me_type == EVF_WRITE)
|
||||||
&& mevp->me_fd != STDIN_FILENO)
|
&& mevp->me_fd != STDIN_FILENO)
|
||||||
close(mevp->me_fd);
|
close(mevp->me_fd);
|
||||||
LIST_REMOVE(mevp, me_list);
|
|
||||||
free(mevp);
|
free(mevp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,6 +178,8 @@ struct mevent *
|
|||||||
mevent_add(int tfd, enum ev_type type,
|
mevent_add(int tfd, enum ev_type type,
|
||||||
void (*func)(int, enum ev_type, void *), void *param)
|
void (*func)(int, enum ev_type, void *), void *param)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
struct epoll_event ee;
|
||||||
struct mevent *lp, *mevp;
|
struct mevent *lp, *mevp;
|
||||||
|
|
||||||
if (tfd < 0 || func == NULL)
|
if (tfd < 0 || func == NULL)
|
||||||
@ -247,44 +188,41 @@ mevent_add(int tfd, enum ev_type type,
|
|||||||
if (type == EVF_TIMER)
|
if (type == EVF_TIMER)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
mevp = NULL;
|
|
||||||
|
|
||||||
mevent_qlock();
|
mevent_qlock();
|
||||||
|
/* Verify that the fd/type tuple is not present in the list */
|
||||||
/*
|
|
||||||
* Verify that the fd/type tuple is not present in any list
|
|
||||||
*/
|
|
||||||
LIST_FOREACH(lp, &global_head, me_list) {
|
LIST_FOREACH(lp, &global_head, me_list) {
|
||||||
if (lp->me_fd == tfd && lp->me_type == type)
|
if (lp->me_fd == tfd && lp->me_type == type) {
|
||||||
goto exit;
|
mevent_qunlock();
|
||||||
}
|
return lp;
|
||||||
|
}
|
||||||
LIST_FOREACH(lp, &change_head, me_list) {
|
|
||||||
if (lp->me_fd == tfd && lp->me_type == type)
|
|
||||||
goto exit;
|
|
||||||
}
|
}
|
||||||
|
mevent_qunlock();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate an entry, populate it, and add it to the change list.
|
* Allocate an entry, populate it, and add it to the list.
|
||||||
*/
|
*/
|
||||||
mevp = calloc(1, sizeof(struct mevent));
|
mevp = calloc(1, sizeof(struct mevent));
|
||||||
if (mevp == NULL)
|
if (mevp == NULL)
|
||||||
goto exit;
|
return NULL;
|
||||||
|
|
||||||
mevp->me_fd = tfd;
|
mevp->me_fd = tfd;
|
||||||
mevp->me_type = type;
|
mevp->me_type = type;
|
||||||
mevp->me_func = func;
|
mevp->me_func = func;
|
||||||
mevp->me_param = param;
|
mevp->me_param = param;
|
||||||
|
|
||||||
LIST_INSERT_HEAD(&change_head, mevp, me_list);
|
ee.events = mevent_kq_filter(mevp);
|
||||||
mevp->me_cq = 1;
|
ee.data.ptr = mevp;
|
||||||
mevp->me_state = MEV_ADD;
|
ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mevp->me_fd, &ee);
|
||||||
mevent_notify();
|
if (ret == 0) {
|
||||||
|
mevent_qlock();
|
||||||
|
LIST_INSERT_HEAD(&global_head, mevp, me_list);
|
||||||
|
mevent_qunlock();
|
||||||
|
|
||||||
exit:
|
return mevp;
|
||||||
mevent_qunlock();
|
} else {
|
||||||
|
free(mevp);
|
||||||
return mevp;
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -302,25 +240,20 @@ mevent_disable(struct mevent *evp)
|
|||||||
static int
|
static int
|
||||||
mevent_delete_event(struct mevent *evp, int closefd)
|
mevent_delete_event(struct mevent *evp, int closefd)
|
||||||
{
|
{
|
||||||
|
struct epoll_event ee;
|
||||||
|
|
||||||
mevent_qlock();
|
mevent_qlock();
|
||||||
|
LIST_REMOVE(evp, me_list);
|
||||||
/*
|
|
||||||
* Place the entry onto the changed list if not already there, and
|
|
||||||
* mark as to be deleted.
|
|
||||||
*/
|
|
||||||
if (evp->me_cq == 0) {
|
|
||||||
evp->me_cq = 1;
|
|
||||||
LIST_REMOVE(evp, me_list);
|
|
||||||
LIST_INSERT_HEAD(&change_head, evp, me_list);
|
|
||||||
mevent_notify();
|
|
||||||
}
|
|
||||||
evp->me_state = MEV_DEL_PENDING;
|
|
||||||
|
|
||||||
if (closefd)
|
|
||||||
evp->me_closefd = 1;
|
|
||||||
|
|
||||||
mevent_qunlock();
|
mevent_qunlock();
|
||||||
|
|
||||||
|
ee.events = mevent_kq_filter(evp);
|
||||||
|
ee.data.ptr = evp;
|
||||||
|
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, evp->me_fd, &ee);
|
||||||
|
|
||||||
|
if (closefd)
|
||||||
|
close(evp->me_fd);
|
||||||
|
|
||||||
|
free(evp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,11 +297,9 @@ mevent_deinit(void)
|
|||||||
void
|
void
|
||||||
mevent_dispatch(void)
|
mevent_dispatch(void)
|
||||||
{
|
{
|
||||||
struct ctl_event clist[MEVENT_MAX];
|
|
||||||
struct epoll_event eventlist[MEVENT_MAX];
|
struct epoll_event eventlist[MEVENT_MAX];
|
||||||
|
|
||||||
struct mevent *pipev;
|
struct mevent *pipev;
|
||||||
int numev;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mevent_tid = pthread_self();
|
mevent_tid = pthread_self();
|
||||||
@ -392,24 +323,6 @@ mevent_dispatch(void)
|
|||||||
assert(pipev != NULL);
|
assert(pipev != NULL);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/*
|
|
||||||
* Build changelist if required.
|
|
||||||
* XXX the changelist can be put into the blocking call
|
|
||||||
* to eliminate the extra syscall. Currently better for
|
|
||||||
* debug.
|
|
||||||
*/
|
|
||||||
int i;
|
|
||||||
struct epoll_event *e;
|
|
||||||
|
|
||||||
numev = mevent_build(epoll_fd, clist);
|
|
||||||
|
|
||||||
for (i = 0; i < numev; i++) {
|
|
||||||
e = &clist[i].ee;
|
|
||||||
ret = epoll_ctl(epoll_fd, clist[i].op, clist[i].fd, e);
|
|
||||||
if (ret == -1)
|
|
||||||
perror("Error return from epoll_ctl");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Block awaiting events
|
* Block awaiting events
|
||||||
*/
|
*/
|
||||||
@ -425,5 +338,4 @@ mevent_dispatch(void)
|
|||||||
if (vm_get_suspend_mode() != VM_SUSPEND_NONE)
|
if (vm_get_suspend_mode() != VM_SUSPEND_NONE)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mevent_build(epoll_fd, clist);
|
|
||||||
}
|
}
|
||||||
|
@ -691,12 +691,14 @@ virtio_console_add_backend(struct virtio_console *console,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (virtio_console_backend_can_read(be_type)) {
|
if (virtio_console_backend_can_read(be_type)) {
|
||||||
be->evp = mevent_add(fd, EVF_READ,
|
if (isatty(fd)) {
|
||||||
virtio_console_backend_read, be);
|
be->evp = mevent_add(fd, EVF_READ,
|
||||||
if (be->evp == NULL) {
|
virtio_console_backend_read, be);
|
||||||
WPRINTF(("vtcon: mevent_add failed\n"));
|
if (be->evp == NULL) {
|
||||||
error = -1;
|
WPRINTF(("vtcon: mevent_add failed\n"));
|
||||||
goto out;
|
error = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,8 +267,11 @@ static void
|
|||||||
uart_opentty(struct uart_vdev *uart)
|
uart_opentty(struct uart_vdev *uart)
|
||||||
{
|
{
|
||||||
ttyopen(&uart->tty);
|
ttyopen(&uart->tty);
|
||||||
uart->mev = mevent_add(uart->tty.fd, EVF_READ, uart_drain, uart);
|
if (isatty(uart->tty.fd)) {
|
||||||
assert(uart->mev != NULL);
|
uart->mev = mevent_add(uart->tty.fd, EVF_READ,
|
||||||
|
uart_drain, uart);
|
||||||
|
assert(uart->mev != NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
|
Loading…
Reference in New Issue
Block a user