123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Controller of read/write threads for virtio-trace
- *
- * Copyright (C) 2012 Hitachi, Ltd.
- * Created by Yoshihiro Yunomae <[email protected]>
- * Masami Hiramatsu <[email protected]>
- */
- #define _GNU_SOURCE
- #include <fcntl.h>
- #include <poll.h>
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include "trace-agent.h"
- #define HOST_MSG_SIZE 256
- #define EVENT_WAIT_MSEC 100
- static volatile sig_atomic_t global_signal_val;
- bool global_sig_receive; /* default false */
- bool global_run_operation; /* default false*/
- /* Handle SIGTERM/SIGINT/SIGQUIT to exit */
- static void signal_handler(int sig)
- {
- global_signal_val = sig;
- }
- int rw_ctl_init(const char *ctl_path)
- {
- int ctl_fd;
- ctl_fd = open(ctl_path, O_RDONLY);
- if (ctl_fd == -1) {
- pr_err("Cannot open ctl_fd\n");
- goto error;
- }
- return ctl_fd;
- error:
- exit(EXIT_FAILURE);
- }
- static int wait_order(int ctl_fd)
- {
- struct pollfd poll_fd;
- int ret = 0;
- while (!global_sig_receive) {
- poll_fd.fd = ctl_fd;
- poll_fd.events = POLLIN;
- ret = poll(&poll_fd, 1, EVENT_WAIT_MSEC);
- if (global_signal_val) {
- global_sig_receive = true;
- pr_info("Receive interrupt %d\n", global_signal_val);
- /* Wakes rw-threads when they are sleeping */
- if (!global_run_operation)
- pthread_cond_broadcast(&cond_wakeup);
- ret = -1;
- break;
- }
- if (ret < 0) {
- pr_err("Polling error\n");
- goto error;
- }
- if (ret)
- break;
- };
- return ret;
- error:
- exit(EXIT_FAILURE);
- }
- /*
- * contol read/write threads by handling global_run_operation
- */
- void *rw_ctl_loop(int ctl_fd)
- {
- ssize_t rlen;
- char buf[HOST_MSG_SIZE];
- int ret;
- /* Setup signal handlers */
- signal(SIGTERM, signal_handler);
- signal(SIGINT, signal_handler);
- signal(SIGQUIT, signal_handler);
- while (!global_sig_receive) {
- ret = wait_order(ctl_fd);
- if (ret < 0)
- break;
- rlen = read(ctl_fd, buf, sizeof(buf));
- if (rlen < 0) {
- pr_err("read data error in ctl thread\n");
- goto error;
- }
- if (rlen == 2 && buf[0] == '1') {
- /*
- * If host writes '1' to a control path,
- * this controller wakes all read/write threads.
- */
- global_run_operation = true;
- pthread_cond_broadcast(&cond_wakeup);
- pr_debug("Wake up all read/write threads\n");
- } else if (rlen == 2 && buf[0] == '0') {
- /*
- * If host writes '0' to a control path, read/write
- * threads will wait for notification from Host.
- */
- global_run_operation = false;
- pr_debug("Stop all read/write threads\n");
- } else
- pr_info("Invalid host notification: %s\n", buf);
- }
- return NULL;
- error:
- exit(EXIT_FAILURE);
- }
|