dm: support iothread

Supply a decidate thread, which can moniter a set of fds with epoll,
when the data is ready, call the corresponding callback.

This iothread will be created automatically with the first successful
call to iothread_add,  and will be destroyed in iothread_deinit if it
was created.

Note, currenlty only support one iothread.

Tracked-On: #7940
Signed-off-by: Conghui <conghui.chen@intel.com>
Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
Conghui 2022-07-15 18:42:08 +08:00 committed by acrnsi-robot
parent 670ccf21f8
commit 4fd0a1900a
4 changed files with 188 additions and 0 deletions

View File

@ -170,6 +170,7 @@ SRCS += core/sw_load_vsbl.c
SRCS += core/sw_load_ovmf.c
SRCS += core/sw_load_elf.c
SRCS += core/mevent.c
SRCS += core/iothread.c
SRCS += core/pm.c
SRCS += core/pm_vuart.c
SRCS += core/console.c

158
devicemodel/core/iothread.c Normal file
View File

@ -0,0 +1,158 @@
/*
* Copyright (C) 2022 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/queue.h>
#include <pthread.h>
#include <signal.h>
#include "iothread.h"
#include "log.h"
#include "mevent.h"
#define MEVENT_MAX 64
struct iothread_ctx {
pthread_t tid;
int epfd;
bool started;
pthread_mutex_t mtx;
};
static struct iothread_ctx ioctx;
static void *
io_thread(void *arg)
{
struct epoll_event eventlist[MEVENT_MAX];
struct iothread_mevent *aevp;
int i, n;
while(ioctx.started) {
n = epoll_wait(ioctx.epfd, eventlist, MEVENT_MAX, -1);
if (n < 0) {
if (errno == EINTR)
pr_info("%s: exit from epoll_wait\n", __func__);
else
pr_err("%s: return from epoll wait with errno %d\r\n", __func__, errno);
break;
}
for (i = 0; i < n; i++) {
aevp = eventlist[i].data.ptr;
if (aevp && aevp->run)
(*aevp->run)(aevp->arg);
}
}
return NULL;
}
static int
iothread_start(void)
{
pthread_mutex_lock(&ioctx.mtx);
if (ioctx.started) {
pthread_mutex_unlock(&ioctx.mtx);
return 0;
}
if (pthread_create(&ioctx.tid, NULL, io_thread, NULL) != 0) {
pthread_mutex_unlock(&ioctx.mtx);
pr_err("%s", "iothread create failed\r\n");
return -1;
}
ioctx.started = true;
pthread_setname_np(ioctx.tid, "iothread");
pthread_mutex_unlock(&ioctx.mtx);
pr_info("iothread started\n");
return 0;
}
int
iothread_add(int fd, struct iothread_mevent *aevt)
{
struct epoll_event ee;
int ret;
/* Create a epoll instance before the first fd is added.*/
ee.events = EPOLLIN;
ee.data.ptr = aevt;
ret = epoll_ctl(ioctx.epfd, EPOLL_CTL_ADD, fd, &ee);
if (ret < 0) {
pr_err("%s: failed to add fd, error is %d\n",
__func__, errno);
return ret;
}
/* Start the iothread after the first fd is added.*/
ret = iothread_start();
if (ret < 0) {
pr_err("%s: failed to start iothread thread\n",
__func__);
}
return ret;
}
int
iothread_del(int fd)
{
int ret = 0;
if (ioctx.epfd) {
ret = epoll_ctl(ioctx.epfd, EPOLL_CTL_DEL, fd, NULL);
if (ret < 0)
pr_err("%s: failed to delete fd from epoll fd, error is %d\n",
__func__, errno);
}
return ret;
}
void
iothread_deinit(void)
{
void *jval;
if (ioctx.tid > 0) {
pthread_mutex_lock(&ioctx.mtx);
ioctx.started = false;
pthread_mutex_unlock(&ioctx.mtx);
pthread_kill(ioctx.tid, SIGCONT);
pthread_join(ioctx.tid, &jval);
}
if (ioctx.epfd > 0) {
close(ioctx.epfd);
ioctx.epfd = -1;
}
pthread_mutex_destroy(&ioctx.mtx);
pr_info("iothread stop\n");
}
int
iothread_init(void)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&ioctx.mtx, &attr);
pthread_mutexattr_destroy(&attr);
ioctx.tid = -1;
ioctx.started = false;
ioctx.epfd = epoll_create1(0);
if (ioctx.epfd < 0) {
pr_err("%s: failed to create epoll fd, error is %d\r\n",
__func__, errno);
return -1;
}
return 0;
}

View File

@ -70,6 +70,7 @@
#include "vssram.h"
#include "cmd_monitor.h"
#include "vdisplay.h"
#include "iothread.h"
#define VM_MAXCPU 16 /* maximum virtual cpus */
@ -1105,6 +1106,12 @@ main(int argc, char *argv[])
goto mevent_fail;
}
error = iothread_init();
if (error) {
pr_err("Unable to initialize iothread (%d)\n", errno);
goto iothread_fail;
}
pr_notice("vm_init_vdevs\n");
if (vm_init_vdevs(ctx) < 0) {
pr_err("Unable to init vdev (%d)\n", errno);
@ -1167,6 +1174,7 @@ main(int argc, char *argv[])
vm_deinit_vdevs(ctx);
mevent_deinit();
iothread_deinit();
vm_unsetup_memory(ctx);
vm_destroy(ctx);
_ctx = 0;
@ -1181,6 +1189,8 @@ vm_fail:
clean_vssram_configs();
dev_fail:
iothread_deinit();
iothread_fail:
mevent_deinit();
mevent_fail:
vm_unsetup_memory(ctx);

View File

@ -0,0 +1,19 @@
/* Copyright (C) 2022 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef _iothread_CTX_H_
#define _iothread_CTX_H_
struct iothread_mevent {
void (*run)(void *);
void *arg;
};
int iothread_add(int fd, struct iothread_mevent *aevt);
int iothread_del(int fd);
int iothread_init(void);
void iothread_deinit(void);
#endif