RFC: cyclictest patch to dump stats on demand via fifo

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch is in addition to the dump-stats-on-SIGUSR1 I posted
previously.

I occurred to me that dumping stats to stdout was cool, except for when
someone had stdout redirected to a pipe; then not so much. So I came up
with an option to create a named fifo and to dump the current run stats
out to the fifo whenever someone opened and read it. 

diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index 0a15dcb..a8f9534 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -1,6 +1,8 @@
 /*
  * High resolution timer test software
  *
+ * (C) 2013      Clark Williams <williams@xxxxxxxxxx>
+ * (C) 2013      John Kacur <jkacur@xxxxxxxxxx>
  * (C) 2008-2012 Clark Williams <williams@xxxxxxxxxx>
  * (C) 2005-2007 Thomas Gleixner <tglx@xxxxxxxxxxxxx>
  *
@@ -178,6 +180,8 @@ static int force_sched_other;
 static int priospread = 0;
 static int check_clock_resolution;
 static int ct_debug;
+static int use_fifo = 0;
+static pthread_t fifo_threadid;
 
 static pthread_cond_t refresh_on_max_cond = PTHREAD_COND_INITIALIZER;
 static pthread_mutex_t refresh_on_max_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -195,10 +199,16 @@ static struct kvars {
 static char *procfileprefix = "/proc/sys/kernel/";
 static char *fileprefix;
 static char tracer[MAX_PATH];
+static char fifopath[MAX_PATH];
 static char **traceptr;
 static int traceopt_count;
 static int traceopt_size;
 
+static struct thread_param **parameters;
+static struct thread_stat **statistics;
+
+static void print_stat(FILE *fp, struct thread_param *par, int index, int verbose, int quiet);
+
 static int latency_target_fd = -1;
 static int32_t latency_target_value = 0;
 
@@ -961,6 +971,7 @@ static void display_help(int error)
 	       "-e       --latency=PM_QOS  write PM_QOS to /dev/cpu_dma_latency\n"
 	       "-E       --event           event tracing (used with -b)\n"
 	       "-f       --ftrace          function trace (when -b is active)\n"
+	       "-F       --fifo=<path>     create a named pipe at path and write stats to it\n"
 	       "-h       --histogram=US    dump a latency histogram to stdout after the run\n"
 	       "                           (with same priority about many threads)\n"
 	       "                           US is the max time to be be tracked in microseconds\n"
@@ -1099,6 +1110,7 @@ static void process_options (int argc, char *argv[])
 			{"latency",          required_argument, NULL, 'e'},
 			{"event",            no_argument,       NULL, 'E'},
 			{"ftrace",           no_argument,       NULL, 'f'},
+			{"fifo",             required_argument, NULL, 'F'},
 			{"histogram",        required_argument, NULL, 'h'},
 			{"histofall",        required_argument, NULL, 'H'},
 			{"interval",         required_argument, NULL, 'i'},
@@ -1163,6 +1175,10 @@ static void process_options (int argc, char *argv[])
 			break;
 		case 'E': enable_events = 1; break;
 		case 'f': tracetype = FUNCTION; ftrace = 1; break;
+		case 'F': 
+			use_fifo = 1; 
+			strncpy(fifopath, optarg, strlen(optarg));
+			break;
 		case 'H': histofall = 1; /* fall through */
 		case 'h': histogram = atoi(optarg); break;
 		case 'i': interval = atoi(optarg); break;
@@ -1368,6 +1384,19 @@ static int check_timer(void)
 
 static void sighand(int sig)
 {
+	if (sig == SIGUSR1) {
+		int i;
+		int oldquiet = quiet;
+
+		quiet = 0;
+		printf("#---------------------------\n");
+		printf("# cyclictest current status:\n");
+		for (i = 0; i < num_threads; i++)
+			print_stat(stdout, parameters[i], i, 0, 0);
+		printf("#---------------------------\n");
+		quiet = oldquiet;
+		return;
+	}
 	shutdown = 1;
 	if (refresh_on_max)
 		pthread_cond_signal(&refresh_on_max_cond);
@@ -1460,7 +1489,7 @@ static void print_hist(struct thread_param *par[], int nthreads)
 	printf("\n");
 }
 
-static void print_stat(struct thread_param *par, int index, int verbose)
+static void print_stat(FILE *fp, struct thread_param *par, int index, int verbose, int quiet)
 {
 	struct thread_stat *stat = par->stats;
 
@@ -1473,10 +1502,10 @@ static void print_stat(struct thread_param *par, int index, int verbose)
 			else
 				fmt = "T:%2d (%5d) P:%2d I:%ld C:%7lu "
 					"Min:%7ld Act:%5ld Avg:%5ld Max:%8ld\n";
-				printf(fmt, index, stat->tid, par->prio,
-				       par->interval, stat->cycles, stat->min, stat->act,
-				       stat->cycles ?
-				       (long)(stat->avg/stat->cycles) : 0, stat->max);
+			fprintf(fp, fmt, index, stat->tid, par->prio,
+				par->interval, stat->cycles, stat->min, stat->act,
+				stat->cycles ?
+				(long)(stat->avg/stat->cycles) : 0, stat->max);
 		}
 	} else {
 		while (stat->cycles != stat->cyclesread) {
@@ -1488,8 +1517,8 @@ static void print_stat(struct thread_param *par, int index, int verbose)
 				stat->cycleofmax = stat->cyclesread;
 			}
 			if (++stat->reduce == oscope_reduction) {
-				printf("%8d:%8lu:%8ld\n", index,
-				       stat->cycleofmax, stat->redmax);
+				fprintf(fp, "%8d:%8lu:%8ld\n", index,
+					stat->cycleofmax, stat->redmax);
 				stat->reduce = 0;
 				stat->redmax = 0;
 			}
@@ -1498,13 +1527,49 @@ static void print_stat(struct thread_param *par, int index, int verbose)
 	}
 }
 
+
+/* 
+ * thread that creates a named fifo and hands out run stats when someone
+ * reads from the fifo.
+ */
+void *fifothread(void *param)
+{
+	int ret;
+	int fd;
+	FILE *fp;
+	int i;
+
+	if (use_fifo == 0)
+		return NULL;
+
+	unlink(fifopath);
+	ret = mkfifo(fifopath, 0666);
+	if (ret) {
+		fprintf(stderr, "Error creating fifo %s: %s\n", fifopath, strerror(errno));
+		return NULL;
+	}
+	while (!shutdown) {
+		fd = open(fifopath, O_WRONLY|O_NONBLOCK);
+		if (fd < 0) {
+			usleep(500000);
+			continue;
+		}
+		fp = fdopen(fd, "w");
+		for (i=0; i < num_threads; i++)
+			print_stat(fp, parameters[i], i, 0, 0);
+		fclose(fp);
+		usleep(250);
+	}
+	unlink(fifopath);
+	return NULL;
+}
+
+
 int main(int argc, char **argv)
 {
 	sigset_t sigset;
 	int signum = SIGALRM;
 	int mode;
-	struct thread_param **parameters;
-	struct thread_stat **statistics;
 	int max_cpus = sysconf(_SC_NPROCESSORS_CONF);
 	int i, ret = -1;
 	int status;
@@ -1642,6 +1707,7 @@ int main(int argc, char **argv)
 
 	signal(SIGINT, sighand);
 	signal(SIGTERM, sighand);
+	signal(SIGUSR1, sighand);
 
 	parameters = calloc(num_threads, sizeof(struct thread_param *));
 	if (!parameters)
@@ -1755,6 +1821,8 @@ int main(int argc, char **argv)
 			fatal("failed to create thread %d: %s\n", i, strerror(status));
 
 	}
+	if (use_fifo)
+		status = pthread_create(&fifo_threadid, NULL, fifothread, NULL);
 
 	while (!shutdown) {
 		char lavg[256];
@@ -1784,7 +1852,7 @@ int main(int argc, char **argv)
 
 		for (i = 0; i < num_threads; i++) {
 
-			print_stat(parameters[i], i, verbose);
+			print_stat(stdout, parameters[i], i, verbose, quiet);
 			if(max_cycles && statistics[i]->cycles >= max_cycles)
 				allstopped++;
 		}
@@ -1816,7 +1884,7 @@ int main(int argc, char **argv)
 		if (statistics[i]->threadstarted) {
 			pthread_join(statistics[i]->thread, NULL);
 			if (quiet && !histogram)
-				print_stat(parameters[i], i, 0);
+				print_stat(stdout, parameters[i], i, 0, 0);
 		}
 		if (statistics[i]->values)
 			threadfree(statistics[i]->values, VALBUF_SIZE*sizeof(long), parameters[i]->node);

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [RT Stable]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]

  Powered by Linux