From 9af35baf5a7b660cf10d89ddcde83f327ebcf7e0 Mon Sep 17 00:00:00 2001 From: "yuhong.tao@intel.com" Date: Wed, 30 May 2018 02:44:13 +0800 Subject: [PATCH] DM:monitor: add monitor_register_vm_ops() monitor_vm_ops and its helpers is added to allow DM to register operations , so thant vm manager could trigger the power state changes of VM. Reviewed-by: Geoffroy Van Cutsem Reviewed-by: Kevin Tian Reviewed-by: Yan, Like Reviewed-by: Wang, Yu signed-off-by: Yan Like Signed-off-by: Tao Yuhong --- devicemodel/core/monitor.c | 179 ++++++++++++++++++++++++++++++++++ devicemodel/include/monitor.h | 15 +++ 2 files changed, 194 insertions(+) diff --git a/devicemodel/core/monitor.c b/devicemodel/core/monitor.c index 7a683d994..d933c31da 100644 --- a/devicemodel/core/monitor.c +++ b/devicemodel/core/monitor.c @@ -65,8 +65,171 @@ static int check_dir(const char *path) return -1; } +struct vm_ops { + char name[16]; + void *arg; + struct monitor_vm_ops *ops; + LIST_ENTRY(vm_ops) list; +}; + +static unsigned wakeup_reason = 0; + +unsigned get_wakeup_reason(void) +{ + return wakeup_reason; +} + +int set_wakeup_timer(time_t t) +{ + int acrnd_fd; + struct req_acrnd_timer req; + struct ack_acrnd_timer ack; + int ret; + + acrnd_fd = mngr_open_un("acrnd", MNGR_CLIENT); + if (acrnd_fd < 0) { + return -1; + } + + req.msg.magic = MNGR_MSG_MAGIC; + req.msg.msgid = ACRND_TIMER; + req.msg.timestamp = time(NULL); + req.msg.len = sizeof(req); + + req.t = t; + strncpy(req.name, vmname, sizeof(req.name)); + + ret = mngr_send_msg(acrnd_fd, &req.msg, &ack.msg, sizeof(ack), 2); + mngr_close(acrnd_fd); + if (ret != sizeof(ack)) { + fprintf(stderr, "%s %d\r\n", __FUNCTION__, __LINE__); + return -1; + } + + return ack.err; +} + +static LIST_HEAD(vm_ops_list, vm_ops) vm_ops_head; +static pthread_mutex_t vm_ops_mtx = PTHREAD_MUTEX_INITIALIZER; + +int monitor_register_vm_ops(struct monitor_vm_ops *mops, void *arg, + const char *name) +{ + struct vm_ops *ops; + + if (!mops) { + fprintf(stderr, "%s %d\r\n", __FUNCTION__, __LINE__); + return -1; + } + + ops = calloc(1, sizeof(*ops)); + if (!ops) { + perror("Alloc ops"); + return -1; + } + + if (name) + strncpy(ops->name, name, sizeof(ops->name) - 1); + + ops->ops = mops; + ops->arg = arg; + + pthread_mutex_lock(&vm_ops_mtx); + LIST_INSERT_HEAD(&vm_ops_head, ops, list); + pthread_mutex_unlock(&vm_ops_mtx); + + return 0; +} + static int monitor_fd = -1; +/* handlers */ +#define ACK_TIMEOUT 1 + +#define DEFINE_HANDLER(name, type, func) \ +static void name(struct mngr_msg *msg, int client_fd, void *param) \ +{ \ + struct req_##type *req = (void*)msg; \ + struct ack_##type ack; \ + struct vm_ops *ops; \ + \ + int ret = 0; \ + int count = 0; \ + \ + memcpy(&ack.msg, &req->msg, sizeof(req->msg)); \ + ack.msg.len = sizeof(ack); \ + \ + LIST_FOREACH(ops, &vm_ops_head, list) { \ + if (ops->ops->func) { \ + ret += ops->ops->func(ops->arg); \ + count++; \ + } \ + } \ + \ + if (!count) { \ + ack.err = -1; \ + fprintf(stderr, "No handler for id:%u\r\n", req->msg.msgid); \ + } else \ + ack.err = ret; \ + \ + mngr_send_msg(client_fd, &ack.msg, NULL, 0, ACK_TIMEOUT); \ +} + +DEFINE_HANDLER(handle_stop, dm_stop, stop); +DEFINE_HANDLER(handle_suspend, dm_suspend, suspend); +DEFINE_HANDLER(handle_pause, dm_pause, pause); +DEFINE_HANDLER(handle_continue, dm_continue, unpause); + +static void handle_resume(struct mngr_msg *msg, int client_fd, void *param) +{ + struct req_dm_resume *req = (void *)msg; + struct ack_dm_resume ack; + struct vm_ops *ops; + int ret = 0; + int count = 0; + + memcpy(&ack.msg, &req->msg, sizeof(req->msg)); + ack.msg.len = sizeof(ack); + + LIST_FOREACH(ops, &vm_ops_head, list) { + if (ops->ops->resume) { + ret += ops->ops->resume(ops->arg); + count++; + } + } + + if (!count) { + ack.err = -1; + fprintf(stderr, "No handler for id:%u\r\n", req->msg.msgid); + } else + ack.err = ret; + + wakeup_reason = req->reason; + + mngr_send_msg(client_fd, &ack.msg, NULL, 0, ACK_TIMEOUT); +} + +static void handle_query(struct mngr_msg *msg, int client_fd, void *param) +{ + struct req_dm_query *req = (void *)msg; + struct ack_dm_query ack; + struct vm_ops *ops; + + memcpy(&ack.msg, &req->msg, sizeof(req->msg)); + ack.msg.len = sizeof(ack); + + ack.state = -1; + + LIST_FOREACH(ops, &vm_ops_head, list) { + if (ops->ops->query) { + ack.state = ops->ops->query(ops->arg); + break; + } + } + + mngr_send_msg(client_fd, &ack.msg, NULL, 0, ACK_TIMEOUT); +} + int monitor_init(struct vmctx *ctx) { int ret; @@ -92,8 +255,24 @@ int monitor_init(struct vmctx *ctx) goto server_err; } + ret = 0; + ret += mngr_add_handler(monitor_fd, DM_STOP, handle_stop, NULL); + ret += mngr_add_handler(monitor_fd, DM_SUSPEND, handle_suspend, NULL); + ret += mngr_add_handler(monitor_fd, DM_RESUME, handle_resume, NULL); + ret += mngr_add_handler(monitor_fd, DM_PAUSE, handle_pause, NULL); + ret += mngr_add_handler(monitor_fd, DM_CONTINUE, handle_continue, NULL); + ret += mngr_add_handler(monitor_fd, DM_QUERY, handle_query, NULL); + + if (ret) { + fprintf(stderr, "%s %d\r\n", __FUNCTION__, __LINE__); + goto handlers_err; + } + return 0; + handlers_err: + mngr_close(monitor_fd); + monitor_fd = -1; server_err: dir_err: return -1; diff --git a/devicemodel/include/monitor.h b/devicemodel/include/monitor.h index fde1994d0..ec49c4587 100644 --- a/devicemodel/include/monitor.h +++ b/devicemodel/include/monitor.h @@ -43,4 +43,19 @@ int monitor_init(struct vmctx *ctx); void monitor_close(void); +struct monitor_vm_ops { + int (*stop) (void *arg); + int (*resume) (void *arg); + int (*suspend) (void *arg); + int (*pause) (void *arg); + int (*unpause) (void *arg); + int (*query) (void *arg); +}; + +int monitor_register_vm_ops(struct monitor_vm_ops *ops, void *arg, + const char *name); + +/* helper functions for vm_ops callback developer */ +unsigned get_wakeup_reason(void); +int set_wakeup_timer(time_t t); #endif