diff --git a/devicemodel/Makefile b/devicemodel/Makefile index 1b0b27384..823265e27 100644 --- a/devicemodel/Makefile +++ b/devicemodel/Makefile @@ -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 diff --git a/devicemodel/core/iothread.c b/devicemodel/core/iothread.c new file mode 100644 index 000000000..0f56ea60d --- /dev/null +++ b/devicemodel/core/iothread.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2022 Intel Corporation. + * + * SPDX-License-Identifier: BSD-3-Clause +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/devicemodel/core/main.c b/devicemodel/core/main.c index 924a6b5d6..f2acb0b15 100644 --- a/devicemodel/core/main.c +++ b/devicemodel/core/main.c @@ -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); diff --git a/devicemodel/include/iothread.h b/devicemodel/include/iothread.h new file mode 100644 index 000000000..6a3cc7167 --- /dev/null +++ b/devicemodel/include/iothread.h @@ -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