1*108fc825SYoshihiro YUNOMAE /* 2*108fc825SYoshihiro YUNOMAE * Controller of read/write threads for virtio-trace 3*108fc825SYoshihiro YUNOMAE * 4*108fc825SYoshihiro YUNOMAE * Copyright (C) 2012 Hitachi, Ltd. 5*108fc825SYoshihiro YUNOMAE * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com> 6*108fc825SYoshihiro YUNOMAE * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> 7*108fc825SYoshihiro YUNOMAE * 8*108fc825SYoshihiro YUNOMAE * Licensed under GPL version 2 only. 9*108fc825SYoshihiro YUNOMAE * 10*108fc825SYoshihiro YUNOMAE */ 11*108fc825SYoshihiro YUNOMAE 12*108fc825SYoshihiro YUNOMAE #define _GNU_SOURCE 13*108fc825SYoshihiro YUNOMAE #include <fcntl.h> 14*108fc825SYoshihiro YUNOMAE #include <poll.h> 15*108fc825SYoshihiro YUNOMAE #include <signal.h> 16*108fc825SYoshihiro YUNOMAE #include <stdio.h> 17*108fc825SYoshihiro YUNOMAE #include <stdlib.h> 18*108fc825SYoshihiro YUNOMAE #include <unistd.h> 19*108fc825SYoshihiro YUNOMAE #include "trace-agent.h" 20*108fc825SYoshihiro YUNOMAE 21*108fc825SYoshihiro YUNOMAE #define HOST_MSG_SIZE 256 22*108fc825SYoshihiro YUNOMAE #define EVENT_WAIT_MSEC 100 23*108fc825SYoshihiro YUNOMAE 24*108fc825SYoshihiro YUNOMAE static volatile sig_atomic_t global_signal_val; 25*108fc825SYoshihiro YUNOMAE bool global_sig_receive; /* default false */ 26*108fc825SYoshihiro YUNOMAE bool global_run_operation; /* default false*/ 27*108fc825SYoshihiro YUNOMAE 28*108fc825SYoshihiro YUNOMAE /* Handle SIGTERM/SIGINT/SIGQUIT to exit */ 29*108fc825SYoshihiro YUNOMAE static void signal_handler(int sig) 30*108fc825SYoshihiro YUNOMAE { 31*108fc825SYoshihiro YUNOMAE global_signal_val = sig; 32*108fc825SYoshihiro YUNOMAE } 33*108fc825SYoshihiro YUNOMAE 34*108fc825SYoshihiro YUNOMAE int rw_ctl_init(const char *ctl_path) 35*108fc825SYoshihiro YUNOMAE { 36*108fc825SYoshihiro YUNOMAE int ctl_fd; 37*108fc825SYoshihiro YUNOMAE 38*108fc825SYoshihiro YUNOMAE ctl_fd = open(ctl_path, O_RDONLY); 39*108fc825SYoshihiro YUNOMAE if (ctl_fd == -1) { 40*108fc825SYoshihiro YUNOMAE pr_err("Cannot open ctl_fd\n"); 41*108fc825SYoshihiro YUNOMAE goto error; 42*108fc825SYoshihiro YUNOMAE } 43*108fc825SYoshihiro YUNOMAE 44*108fc825SYoshihiro YUNOMAE return ctl_fd; 45*108fc825SYoshihiro YUNOMAE 46*108fc825SYoshihiro YUNOMAE error: 47*108fc825SYoshihiro YUNOMAE exit(EXIT_FAILURE); 48*108fc825SYoshihiro YUNOMAE } 49*108fc825SYoshihiro YUNOMAE 50*108fc825SYoshihiro YUNOMAE static int wait_order(int ctl_fd) 51*108fc825SYoshihiro YUNOMAE { 52*108fc825SYoshihiro YUNOMAE struct pollfd poll_fd; 53*108fc825SYoshihiro YUNOMAE int ret = 0; 54*108fc825SYoshihiro YUNOMAE 55*108fc825SYoshihiro YUNOMAE while (!global_sig_receive) { 56*108fc825SYoshihiro YUNOMAE poll_fd.fd = ctl_fd; 57*108fc825SYoshihiro YUNOMAE poll_fd.events = POLLIN; 58*108fc825SYoshihiro YUNOMAE 59*108fc825SYoshihiro YUNOMAE ret = poll(&poll_fd, 1, EVENT_WAIT_MSEC); 60*108fc825SYoshihiro YUNOMAE 61*108fc825SYoshihiro YUNOMAE if (global_signal_val) { 62*108fc825SYoshihiro YUNOMAE global_sig_receive = true; 63*108fc825SYoshihiro YUNOMAE pr_info("Receive interrupt %d\n", global_signal_val); 64*108fc825SYoshihiro YUNOMAE 65*108fc825SYoshihiro YUNOMAE /* Wakes rw-threads when they are sleeping */ 66*108fc825SYoshihiro YUNOMAE if (!global_run_operation) 67*108fc825SYoshihiro YUNOMAE pthread_cond_broadcast(&cond_wakeup); 68*108fc825SYoshihiro YUNOMAE 69*108fc825SYoshihiro YUNOMAE ret = -1; 70*108fc825SYoshihiro YUNOMAE break; 71*108fc825SYoshihiro YUNOMAE } 72*108fc825SYoshihiro YUNOMAE 73*108fc825SYoshihiro YUNOMAE if (ret < 0) { 74*108fc825SYoshihiro YUNOMAE pr_err("Polling error\n"); 75*108fc825SYoshihiro YUNOMAE goto error; 76*108fc825SYoshihiro YUNOMAE } 77*108fc825SYoshihiro YUNOMAE 78*108fc825SYoshihiro YUNOMAE if (ret) 79*108fc825SYoshihiro YUNOMAE break; 80*108fc825SYoshihiro YUNOMAE }; 81*108fc825SYoshihiro YUNOMAE 82*108fc825SYoshihiro YUNOMAE return ret; 83*108fc825SYoshihiro YUNOMAE 84*108fc825SYoshihiro YUNOMAE error: 85*108fc825SYoshihiro YUNOMAE exit(EXIT_FAILURE); 86*108fc825SYoshihiro YUNOMAE } 87*108fc825SYoshihiro YUNOMAE 88*108fc825SYoshihiro YUNOMAE /* 89*108fc825SYoshihiro YUNOMAE * contol read/write threads by handling global_run_operation 90*108fc825SYoshihiro YUNOMAE */ 91*108fc825SYoshihiro YUNOMAE void *rw_ctl_loop(int ctl_fd) 92*108fc825SYoshihiro YUNOMAE { 93*108fc825SYoshihiro YUNOMAE ssize_t rlen; 94*108fc825SYoshihiro YUNOMAE char buf[HOST_MSG_SIZE]; 95*108fc825SYoshihiro YUNOMAE int ret; 96*108fc825SYoshihiro YUNOMAE 97*108fc825SYoshihiro YUNOMAE /* Setup signal handlers */ 98*108fc825SYoshihiro YUNOMAE signal(SIGTERM, signal_handler); 99*108fc825SYoshihiro YUNOMAE signal(SIGINT, signal_handler); 100*108fc825SYoshihiro YUNOMAE signal(SIGQUIT, signal_handler); 101*108fc825SYoshihiro YUNOMAE 102*108fc825SYoshihiro YUNOMAE while (!global_sig_receive) { 103*108fc825SYoshihiro YUNOMAE 104*108fc825SYoshihiro YUNOMAE ret = wait_order(ctl_fd); 105*108fc825SYoshihiro YUNOMAE if (ret < 0) 106*108fc825SYoshihiro YUNOMAE break; 107*108fc825SYoshihiro YUNOMAE 108*108fc825SYoshihiro YUNOMAE rlen = read(ctl_fd, buf, sizeof(buf)); 109*108fc825SYoshihiro YUNOMAE if (rlen < 0) { 110*108fc825SYoshihiro YUNOMAE pr_err("read data error in ctl thread\n"); 111*108fc825SYoshihiro YUNOMAE goto error; 112*108fc825SYoshihiro YUNOMAE } 113*108fc825SYoshihiro YUNOMAE 114*108fc825SYoshihiro YUNOMAE if (rlen == 2 && buf[0] == '1') { 115*108fc825SYoshihiro YUNOMAE /* 116*108fc825SYoshihiro YUNOMAE * If host writes '1' to a control path, 117*108fc825SYoshihiro YUNOMAE * this controller wakes all read/write threads. 118*108fc825SYoshihiro YUNOMAE */ 119*108fc825SYoshihiro YUNOMAE global_run_operation = true; 120*108fc825SYoshihiro YUNOMAE pthread_cond_broadcast(&cond_wakeup); 121*108fc825SYoshihiro YUNOMAE pr_debug("Wake up all read/write threads\n"); 122*108fc825SYoshihiro YUNOMAE } else if (rlen == 2 && buf[0] == '0') { 123*108fc825SYoshihiro YUNOMAE /* 124*108fc825SYoshihiro YUNOMAE * If host writes '0' to a control path, read/write 125*108fc825SYoshihiro YUNOMAE * threads will wait for notification from Host. 126*108fc825SYoshihiro YUNOMAE */ 127*108fc825SYoshihiro YUNOMAE global_run_operation = false; 128*108fc825SYoshihiro YUNOMAE pr_debug("Stop all read/write threads\n"); 129*108fc825SYoshihiro YUNOMAE } else 130*108fc825SYoshihiro YUNOMAE pr_info("Invalid host notification: %s\n", buf); 131*108fc825SYoshihiro YUNOMAE } 132*108fc825SYoshihiro YUNOMAE 133*108fc825SYoshihiro YUNOMAE return NULL; 134*108fc825SYoshihiro YUNOMAE 135*108fc825SYoshihiro YUNOMAE error: 136*108fc825SYoshihiro YUNOMAE exit(EXIT_FAILURE); 137*108fc825SYoshihiro YUNOMAE } 138