138 lines
		
	
	
	
		
			2.6 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			138 lines
		
	
	
	
		
			2.6 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * Controller of read/write threads for virtio-trace | ||
|  |  * | ||
|  |  * Copyright (C) 2012 Hitachi, Ltd. | ||
|  |  * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com> | ||
|  |  *            Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | ||
|  |  * | ||
|  |  * Licensed under GPL version 2 only. | ||
|  |  * | ||
|  |  */ | ||
|  | 
 | ||
|  | #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); | ||
|  | } |