[powerdebug] add window to display status of running processes

Message ID 1375795284-7395-1-git-send-email-sanjay.rawat@linaro.org
State New
Headers show

Commit Message

Sanjay Singh Rawat Aug. 6, 2013, 1:21 p.m.
display various stats of running processes (state, priority, time, load),
more info in README file.

Signed-off-by: Sanjay Singh Rawat <sanjay.rawat@linaro.org>
---
 Makefile     |    4 +-
 README       |    7 +++
 display.c    |    2 +-
 display.h    |    2 +-
 powerdebug.c |    3 ++
 process.c    |  152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 166 insertions(+), 4 deletions(-)
 create mode 100644 process.c

Patch

diff --git a/Makefile b/Makefile
index 2da9d67..a0d9e02 100644
--- a/Makefile
+++ b/Makefile
@@ -4,8 +4,8 @@  MANDIR=/usr/share/man/man8
 CFLAGS?=-O1 -g -Wall -Wshadow
 CC?=gcc
 
-OBJS = powerdebug.o sensor.o clocks.o regulator.o gpio.o \
-	display.o tree.o utils.o mainloop.o
+OBJS = powerdebug.o sensor.o clocks.o regulator.o gpio.o\
+	display.o tree.o utils.o mainloop.o process.o
 
 default: powerdebug
 
diff --git a/README b/README
index fa997f6..659f1dd 100644
--- a/README
+++ b/README
@@ -8,3 +8,10 @@  Current version only displays regulator information and clock tree from
 debugfs. Support will be added for sensors later.
 
  -- Amit Arora <amit.arora@linaro.org>  Fri, 08 Sep 2010 
+
+# Process Window information:
+
+It lists the currently running processes in the system. Each line prints
+line number, name, state(running/sleeping), priority, pid, time(seconds
+process ran), load %(contribution to total system ticks since process
+started).
diff --git a/display.c b/display.c
index 41a511d..65d0616 100644
--- a/display.c
+++ b/display.c
@@ -64,6 +64,7 @@  struct windata windata[] = {
 	[REGULATOR] = { .name = "Regulators" },
 	[SENSOR]    = { .name = "Sensors"    },
 	[GPIO]      = { .name = "Gpio"    },
+	[PROCESS]      = { .name = "Process"    },
 };
 
 static void display_fini(void)
@@ -194,7 +195,6 @@  static int display_next_line(void)
 	struct rowdata *rowdata = windata[current_win].rowdata;
 
 	getmaxyx(stdscr, maxy, maxx);
-
 	if (cursor >= nrdata)
 		return cursor;
 
diff --git a/display.h b/display.h
index 6362a48..5b94401 100644
--- a/display.h
+++ b/display.h
@@ -13,7 +13,7 @@ 
  *       - initial API and implementation
  *******************************************************************************/
 
-enum { CLOCK, REGULATOR, SENSOR, GPIO };
+enum { CLOCK, REGULATOR, SENSOR, GPIO, PROCESS };
 
 struct display_ops {
 	int (*display)(bool refresh);
diff --git a/powerdebug.c b/powerdebug.c
index 6cf3a1b..d04dd85 100644
--- a/powerdebug.c
+++ b/powerdebug.c
@@ -266,6 +266,9 @@  int main(int argc, char **argv)
 		options->gpios = false;
 	}
 
+	if (process_check())
+		printf("error: failed to check status of processes");
+
 	ret = options->dump ? powerdebug_dump(options) :
 		powerdebug_display(options);
 
diff --git a/process.c b/process.c
new file mode 100644
index 0000000..f6f5a04
--- /dev/null
+++ b/process.c
@@ -0,0 +1,152 @@ 
+/*******************************************************************************
+ * Copyright (C) 2013, Linaro Limited.
+ *
+ * This file is part of PowerDebug.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Sanjay Singh Rawat <sanjay.rawat@linaro.org>
+ *       - initial API and implementation
+ *
+ *******************************************************************************/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#undef _GNU_SOURCE
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/time.h>
+#include <ncurses.h>
+
+#include "powerdebug.h"
+#include "display.h"
+#include "tree.h"
+#include "utils.h"
+
+static int process_stat_print_header(void)
+{
+	char *buf;
+	int ret;
+
+	if (asprintf(&buf, "%-4s %-6s %-6s %-6s %-8s %-8s %-10s",
+		"No", "Name", "State", "Priority", "Pid", "Time", "load") < 0)
+		return -1;
+	ret = display_column_name(buf);
+
+	free(buf);
+	return ret;
+}
+
+void get_tick(long int *tticks)
+{
+	struct timeval t;
+	long int curr_time;
+
+	gettimeofday(&t, NULL);
+	curr_time = (double)(t.tv_usec)/1000000 + (double)(t.tv_sec);
+	*tticks = curr_time * CLOCKS_PER_SEC;
+}
+
+int get_process_stat(int count, char *file_path, char *linebuf)
+{
+	FILE *fp;
+	char *name, buf[512], state;
+	int pid, pri;
+	/* will be using in future */
+	int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,
+		a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27,
+		a28, a29, a30, a31, a32, a33, a34, a35, a36, a37;
+	long int putime, pstime, ttick, starttime;
+	double load, sec;
+
+	name = buf;
+	memset(buf, 0, 512);
+	fp = fopen(file_path, "r");
+	if (fp == NULL) {
+		/* todo: file opening failures */
+		printf("error: unable to open file %s\n", file_path);
+		return 0;
+	}
+
+	if (NULL == fgets(buf, 512, fp)) {
+		printf("*process status empty*\n");
+		return 0;
+	}
+	fclose(fp);
+
+	sscanf(buf, "%d %s %c %d %d %d %d %d %d %d %d %d %d %ld %ld %d %d %d \
+		%d %d %d %ld %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d \
+		%d %d %d %d %d %d", &pid, name, &state, &a1, &a2, &a3, &a4,
+		&a5, &a6, &a7, &a8, &a9, &a10, &putime, &pstime, &a11, &a12,
+		&pri, &a13, &a14, &a15, &starttime, &a16, &a17, &a18, &a19,
+		&a20, &a21, &a22, &a23, &a24, &a25, &a26, &a27, &a28, &a29,
+		&a30, &a31, &a32, &a33, &a34, &a35, &a36, &a37);
+
+	get_tick(&ttick);
+	sec = (putime + pstime) / (double) CLOCKS_PER_SEC;
+	load = (putime + pstime)/(double)(ttick - starttime);
+
+	sprintf(linebuf, "%d - %s %c %d [%d] %.6f %.20f",
+			count, name, state, pri, pid, sec, (load*100));
+
+	return 0;
+}
+
+static int process_display(bool rescan)
+{
+	DIR *dirp;
+	struct dirent entry, *entryp;
+	int line = 0;
+
+	display_reset_cursor(PROCESS);
+	process_stat_print_header();
+
+	dirp = opendir("/proc");
+	while (!readdir_r(dirp, &entry, &entryp)) {
+		char path[30], linebuf[512];
+
+		if (!entryp)
+			break;
+
+		memset(path, 0, 30);
+		memset(linebuf, 0, 512);
+		if (entryp->d_name[0] > 47 && entryp->d_name[0] < 58) {
+			int pid = atoi(entryp->d_name);
+			snprintf(path, sizeof(path), "/%s/%d/%s", "proc", pid,
+				"stat");
+			get_process_stat(line, path, linebuf);
+			display_print_line(PROCESS, line, linebuf, 0, NULL);
+			line++;
+		}
+	}
+	display_refresh_pad(PROCESS);
+
+	return 0;
+}
+
+static struct display_ops process_ops = {
+	.display = process_display,
+};
+
+int process_check(void)
+{
+	DIR *dirp;
+
+	dirp = opendir("/proc");
+	if (!dirp) {
+		printf("error: can't open proc dir");
+		return -1;
+	}
+
+	return display_register(PROCESS, &process_ops);
+}