Added simple logging capability

BUG=chromium-os:25959
TEST=ran on stumpy

Change-Id: I17547aa43172f62c85bed44d39886d18596050b0
Reviewed-on: https://gerrit.chromium.org/gerrit/15542
Commit-Ready: Paul Taysom <taysom@chromium.org>
Reviewed-by: Paul Taysom <taysom@chromium.org>
Tested-by: Paul Taysom <taysom@chromium.org>
diff --git a/display.c b/display.c
index a87b789..a5cb2c2 100644
--- a/display.c
+++ b/display.c
@@ -155,7 +155,7 @@
 		pc = Rank_pidcall[i];
 		pid = get_pid(pc->pidcall);
 		if (!pc->name) {
-			pc->name = getpidname(pid);
+			pc->name = get_exe_path(pid);
 		}
 		mvprintw(row, col, "%3d. %5d %6d %10lld %-22.22s %-28.28s",
 			i + 1, pid, pc->snap.count,
@@ -295,7 +295,7 @@
 		pc = Pidcall_summary[i];
 		pid = get_pid(pc->pidcall);
 		if (!pc->name) {
-			pc->name = getpidname(pid);
+			pc->name = get_exe_path(pid);
 		}
 		num_intervals = Current_interval - pc->start_interval;
 		avg_count = ROUNDED_DIVIDE(pc->summary.total_count, num_intervals);
diff --git a/ktop.h b/ktop.h
index a915401..6743a64 100644
--- a/ktop.h
+++ b/ktop.h
@@ -80,6 +80,7 @@
 extern bool Trace_self;	/* Trace myself and ignore others */
 extern bool Pause;	/* Pause display */
 extern bool Help;	/* Display help screen */
+extern char *Log_file;	/* If set, use this file for logging */
 
 extern Display_s Display;
 
@@ -129,6 +130,10 @@
 
 void graph(void);
 
+void log_open(const char *file);
+void log_close(void);
+void log_pidcalls(void);
+
 /* Rounded integer divide - x/y -> (x + y/2) / y */
 #define ROUNDED_DIVIDE(x, y)	((y) ? (((x) + (y) / 2) / (y)) : 0)
 
diff --git a/logging.c b/logging.c
new file mode 100644
index 0000000..0bc9afb
--- /dev/null
+++ b/logging.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Distributed under the terms of the GNU General Public License v2
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "eprintf.h"
+#include "ktop.h"
+#include "reduce.h"
+#include "util.h"
+
+static FILE	*Fp;
+static char	*File;
+
+void log_open (const char *file)
+{
+	if (Fp) {
+		warn("Log file already in use %s", file);
+	} else {
+		Fp = fopen(file, "w");
+		if (!Fp) fatal("Couldn't open log file %s:", file);
+		File = strdup(file);
+	}
+}
+
+void log_close (void)
+{
+	if (Fp) {
+		fclose(Fp);
+		free(File);
+		Fp = NULL;
+		File = NULL;
+	}
+}
+
+void log_pidcalls (void)
+{
+	static unint	interval = 0;
+	Pidcall_s	*pc;
+	int		pid;
+	int		i;
+	int		rc;
+
+	if (!Fp) return;
+	++interval;
+	for (i = 0; i < Num_rank; i++) {
+		pc = Rank_pidcall[i];
+		pid = get_pid(pc->pidcall);
+		if (!pc->name) {
+			pc->name = get_exe_path(pid);
+		}
+		rc = fprintf(Fp, "%ld,%d,%d,%lld,%s,%s\n",
+			interval, pid, pc->snap.count,
+			pc->snap.total_time,
+			Syscall[get_call(pc->pidcall)],
+			pc->name);
+		if (rc < 0) {
+			warn("Log failed %s:", File);
+			log_close();
+		}
+	}
+}
+
diff --git a/main.c b/main.c
index f7ba50c..838264b 100644
--- a/main.c
+++ b/main.c
@@ -24,6 +24,7 @@
 bool Trace_self = FALSE;
 bool Pause = FALSE;
 bool Help = FALSE;
+char *Log_file = NULL;
 
 Display_s Display;
 
@@ -86,9 +87,10 @@
 
 static void usage(void)
 {
-	fprintf(stderr, "usage: %s [-dhs]\n"
+	fprintf(stderr, "usage: %s [-dhs] [-l <log path name>]\n"
 		"\td - dump of ftrace log of cpu 0 for debugging\n"
 		"\th - usage\n"
+		"\tl - create a log file\n"
 		"\ts - trace self\n\n"
 		"\tCommands while running:\n"
 		"\t? - help for current screen\n"
@@ -113,7 +115,7 @@
 	setprogname(argv[0]);
 	set_signals();
 
-	while ((c = getopt(argc, argv, "dhs")) != -1) {
+	while ((c = getopt(argc, argv, "dhsl:")) != -1) {
 		switch (c) {
 		case 'd':
 			Dump = TRUE;
@@ -124,6 +126,9 @@
 		case 'h':
 			usage();
 			break;
+		case 'l':
+			Log_file = optarg;
+			break;
 		default:
 			fprintf(stderr, "unknown flag '%c'\n", c);
 			usage();
@@ -207,6 +212,7 @@
 	if (!Dump) {
 		rc = pthread_create(&reduce_thread, NULL, reduce, NULL);
 		if (rc) fatal("creating reduce thread:");
+		if (Log_file) log_open(Log_file);
 	}
 	commander();
 
diff --git a/reduce.c b/reduce.c
index e478f82..ab9725d 100644
--- a/reduce.c
+++ b/reduce.c
@@ -68,7 +68,7 @@
 	tc->tick    = Num_ticks;
 	tc->time    = pc->snap.total_time;
 	if (!pc->name) {
-		pc->name = getpidname(get_pid(pc->pidcall));
+		pc->name = get_exe_path(get_pid(pc->pidcall));
 	}
 	strncpy(tc->name, pc->name, MAX_THREAD_NAME);
 	tc->name[MAX_THREAD_NAME - 1] = '\0';
@@ -233,6 +233,7 @@
 			if (Help) Display.help();
 			else Display.normal();
 		}
+		if (Log_file) log_pidcalls();
 		nanosleep(&Sleep, NULL);
 	}
 }
diff --git a/util.c b/util.c
index 4c37756..9245c61 100644
--- a/util.c
+++ b/util.c
@@ -37,7 +37,7 @@
 	return release_to_int(buf.release);
 }
 
-char *getpidname (int pid)
+char *get_exe_path (int pid)
 {
 	char path[100];
 	static char name[4096];
diff --git a/util.h b/util.h
index 141fc4a..c1eaf9e 100644
--- a/util.h
+++ b/util.h
@@ -8,6 +8,6 @@
 
 int release_to_int(char *r);
 int kernel_release(void);
-char *getpidname(int pid);
+char *get_exe_path(int pid);
 
 #endif /* _UTIL_H_ */