svn commit: trunk/busybox: applets include libbb procps

vda at busybox.net vda at busybox.net
Sat Jan 5 03:26:41 UTC 2008


Author: vda
Date: 2008-01-04 19:26:41 -0800 (Fri, 04 Jan 2008)
New Revision: 20710

Log:
ps: add conditional support for -o [e]time



Modified:
   trunk/busybox/applets/applet_tables.c
   trunk/busybox/include/libbb.h
   trunk/busybox/libbb/procps.c
   trunk/busybox/procps/Config.in
   trunk/busybox/procps/ps.c


Changeset:
Modified: trunk/busybox/applets/applet_tables.c
===================================================================
--- trunk/busybox/applets/applet_tables.c	2008-01-04 20:10:51 UTC (rev 20709)
+++ trunk/busybox/applets/applet_tables.c	2008-01-05 03:26:41 UTC (rev 20710)
@@ -71,7 +71,7 @@
 
 	puts("/* This is a generated file, don't edit */");
 
-	puts("const char applet_names[] ALIGN1 = \"\" \n");
+	puts("const char applet_names[] ALIGN1 = \"\"\n");
 	for (i = 0; i < NUM_APPLETS; i++) {
 		printf("\"%s\" \"\\0\"\n", applets[i].name);
 	}

Modified: trunk/busybox/include/libbb.h
===================================================================
--- trunk/busybox/include/libbb.h	2008-01-04 20:10:51 UTC (rev 20709)
+++ trunk/busybox/include/libbb.h	2008-01-05 03:26:41 UTC (rev 20710)
@@ -990,6 +990,7 @@
 	 * it is memset(0) for each process in procps_scan() */
 	unsigned long vsz, rss; /* we round it to kbytes */
 	unsigned long stime, utime;
+	unsigned long start_time;
 	unsigned pid;
 	unsigned ppid;
 	unsigned pgid;
@@ -1032,11 +1033,12 @@
 	PSSCAN_SMAPS	= (1 << 15) * ENABLE_FEATURE_TOPMEM,
 	PSSCAN_ARGVN    = (1 << 16) * (ENABLE_PGREP | ENABLE_PKILL),
 	USE_SELINUX(PSSCAN_CONTEXT = 1 << 17,)
+	PSSCAN_START_TIME = 1 << 18,
 	/* These are all retrieved from proc/NN/stat in one go: */
 	PSSCAN_STAT     = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID
 	                | PSSCAN_COMM | PSSCAN_STATE
 	                | PSSCAN_VSZ | PSSCAN_RSS
-			| PSSCAN_STIME | PSSCAN_UTIME
+			| PSSCAN_STIME | PSSCAN_UTIME | PSSCAN_START_TIME
 			| PSSCAN_TTY,
 };
 procps_status_t* alloc_procps_scan(int flags);

Modified: trunk/busybox/libbb/procps.c
===================================================================
--- trunk/busybox/libbb/procps.c	2008-01-04 20:10:51 UTC (rev 20709)
+++ trunk/busybox/libbb/procps.c	2008-01-05 03:26:41 UTC (rev 20710)
@@ -243,7 +243,8 @@
 				"%lu %lu "             /* utime, stime */
 				"%*s %*s %*s "         /* cutime, cstime, priority */
 				"%ld "                 /* nice */
-				"%*s %*s %*s "         /* timeout, it_real_value, start_time */
+				"%*s %*s "             /* timeout, it_real_value */
+				"%lu "                 /* start_time */
 				"%lu "                 /* vsize */
 				"%lu "                 /* rss */
 			/*	"%lu %lu %lu %lu %lu %lu " rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */
@@ -254,6 +255,7 @@
 				&sp->pgid, &sp->sid, &tty,
 				&sp->utime, &sp->stime,
 				&tasknice,
+				&sp->start_time,
 				&vsz,
 				&rss);
 			if (n != 10)
@@ -280,7 +282,8 @@
 			sp->stime = fast_strtoul_10(&cp);
 			cp = skip_fields(cp, 3); /* cutime, cstime, priority */
 			tasknice = fast_strtoul_10(&cp);
-			cp = skip_fields(cp, 3); /* timeout, it_real_value, start_time */
+			cp = skip_fields(cp, 2); /* timeout, it_real_value */
+			sp->start_time = fast_strtoul_10(&cp);
 			/* vsz is in bytes and we want kb */
 			sp->vsz = fast_strtoul_10(&cp) >> 10;
 			/* vsz is in bytes but rss is in *PAGES*! Can you believe that? */

Modified: trunk/busybox/procps/Config.in
===================================================================
--- trunk/busybox/procps/Config.in	2008-01-04 20:10:51 UTC (rev 20709)
+++ trunk/busybox/procps/Config.in	2008-01-05 03:26:41 UTC (rev 20710)
@@ -99,6 +99,21 @@
 	  If given once, 132 chars are printed and given more than
 	  one, the length is unlimited.
 
+config FEATURE_PS_TIME
+	bool "Enable time and elapsed time output"
+	default n
+	depends on PS && DESKTOP
+	help
+	  Support -o time and -o etime output specifiers.
+
+config FEATURE_PS_UNUSUAL_SYSTEMS
+	bool "Support Linux prior to 2.4.0 and non-ELF systems"
+	default n
+	depends on FEATURE_PS_TIME
+	help
+	  Include support for measuring HZ on old kernels and non-ELF systems
+	  (if you are on Linux 2.4.0+ and use ELF, you don't need this)
+
 config RENICE
 	bool "renice"
 	default n

Modified: trunk/busybox/procps/ps.c
===================================================================
--- trunk/busybox/procps/ps.c	2008-01-04 20:10:51 UTC (rev 20709)
+++ trunk/busybox/procps/ps.c	2008-01-05 03:26:41 UTC (rev 20710)
@@ -16,6 +16,143 @@
 
 #if ENABLE_DESKTOP
 
+#include <sys/times.h> /* for times() */
+//#include <sys/sysinfo.h> /* for sysinfo() */
+#ifndef AT_CLKTCK
+#define AT_CLKTCK 17
+#endif
+
+
+#if ENABLE_SELINUX
+#define SELINIX_O_PREFIX "label,"
+#define DEFAULT_O_STR    (SELINIX_O_PREFIX "pid,user" USE_FEATURE_PS_TIME(",time"))
+#else
+#define DEFAULT_O_STR    ("pid,user" USE_FEATURE_PS_TIME(",time"))
+#endif
+
+typedef struct {
+	uint16_t width;
+	char name[6];
+	const char *header;
+	void (*f)(char *buf, int size, const procps_status_t *ps);
+	int ps_flags;
+} ps_out_t;
+
+struct globals {
+	ps_out_t* out;
+	int out_cnt;
+	int print_header;
+	int need_flags;
+	char *buffer;
+	unsigned terminal_width;
+#if ENABLE_FEATURE_PS_TIME
+	unsigned kernel_HZ;
+	unsigned long long seconds_since_boot;
+#endif
+	char default_o[sizeof(DEFAULT_O_STR)];
+};
+#define G (*(struct globals*)&bb_common_bufsiz1)
+#define out                (G.out               )
+#define out_cnt            (G.out_cnt           )
+#define print_header       (G.print_header      )
+#define need_flags         (G.need_flags        )
+#define buffer             (G.buffer            )
+#define terminal_width     (G.terminal_width    )
+#define kernel_HZ          (G.kernel_HZ         )
+#define seconds_since_boot (G.seconds_since_boot)
+#define default_o          (G.default_o         )
+
+#if ENABLE_FEATURE_PS_TIME
+/* for ELF executables, notes are pushed before environment and args */
+static ptrdiff_t find_elf_note(ptrdiff_t findme)
+{
+        ptrdiff_t *ep = (ptrdiff_t *) environ;
+
+        while (*ep++);
+        while (*ep) {
+                if (ep[0] == findme) {
+                        return ep[1];
+                }
+                ep += 2;
+        }
+        return -1;
+}
+
+#if ENABLE_FEATURE_PS_UNUSUAL_SYSTEMS
+static unsigned get_HZ_by_waiting(void)
+{
+        struct timeval tv1, tv2;
+        unsigned t1, t2, r, hz;
+        unsigned cnt = cnt; /* for compiler */
+        int diff;
+
+        r = 0;
+
+        /* Wait for times() to reach new tick */
+        t1 = times(NULL);
+        do {
+                t2 = times(NULL);
+        } while (t2 == t1);
+        gettimeofday(&tv2, NULL);
+
+        do {
+                t1 = t2;
+                tv1.tv_usec = tv2.tv_usec;
+
+                /* Wait exactly one times() tick */
+                do {
+                        t2 = times(NULL);
+                } while (t2 == t1);
+                gettimeofday(&tv2, NULL);
+
+                /* Calculate ticks per sec, rounding up to even */
+                diff = tv2.tv_usec - tv1.tv_usec;
+                if (diff <= 0) diff += 1000000;
+                hz = 1000000u / (unsigned)diff;
+                hz = (hz+1) & ~1;
+
+		/* Count how many same hz values we saw */
+                if (r != hz) {
+                        r = hz;
+                        cnt = 0;
+                }
+                cnt++;
+        } while (cnt < 3); /* exit if saw 3 same values */
+
+        return r;
+}
+#else
+static inline unsigned get_HZ_by_waiting(void)
+{
+	/* Better method? */
+	return 100;
+}
+#endif
+
+static unsigned get_kernel_HZ(void)
+{
+	//char buf[64];
+	struct sysinfo info;
+
+	if (kernel_HZ)
+		return kernel_HZ;
+
+	/* Works for ELF only, Linux 2.4.0+ */
+	kernel_HZ = find_elf_note(AT_CLKTCK);
+	if (kernel_HZ == (unsigned)-1)
+		kernel_HZ = get_HZ_by_waiting();
+
+	//if (open_read_close("/proc/uptime", buf, sizeof(buf) <= 0)
+	//	bb_perror_msg_and_die("cannot read %s", "/proc/uptime");
+	//buf[sizeof(buf)-1] = '\0';
+	///sscanf(buf, "%llu", &seconds_since_boot);
+	sysinfo(&info);
+	seconds_since_boot = info.uptime;
+
+	return kernel_HZ;
+}
+#endif
+
 /* Print value to buf, max size+1 chars (including trailing '\0') */
 
 static void func_user(char *buf, int size, const procps_status_t *ps)
@@ -73,6 +210,34 @@
 		snprintf(buf, size+1, "%u,%u", ps->tty_major, ps->tty_minor);
 }
 
+#if ENABLE_FEATURE_PS_TIME
+static void func_etime(char *buf, int size, const procps_status_t *ps)
+{
+	/* elapsed time [[dd-]hh:]mm:ss; here only mm:ss */
+	unsigned long mm;
+	unsigned ss;
+
+	mm = ps->start_time / get_kernel_HZ();
+	/* must be after get_kernel_HZ()! */
+	mm = seconds_since_boot - mm;
+	ss = mm % 60;
+	mm /= 60;
+	snprintf(buf, size+1, "%3lu:%02u", mm, ss);
+}
+
+static void func_time(char *buf, int size, const procps_status_t *ps)
+{
+	/* cumulative time [[dd-]hh:]mm:ss; here only mm:ss */
+	unsigned long mm;
+	unsigned ss;
+
+	mm = (ps->utime + ps->stime) / get_kernel_HZ();
+	ss = mm % 60;
+	mm /= 60;
+	snprintf(buf, size+1, "%3lu:%02u", mm, ss);
+}
+#endif
+
 #if ENABLE_SELINUX
 static void func_label(char *buf, int size, const procps_status_t *ps)
 {
@@ -86,29 +251,11 @@
 	ps->???
 }
 
-static void func_etime(char *buf, int size, const procps_status_t *ps)
-{
-	elapled time [[dd-]hh:]mm:ss
-}
-
-static void func_time(char *buf, int size, const procps_status_t *ps)
-{
-	cumulative time [[dd-]hh:]mm:ss
-}
-
 static void func_pcpu(char *buf, int size, const procps_status_t *ps)
 {
 }
 */
 
-typedef struct {
-	uint16_t width;
-	char name[6];
-	const char *header;
-	void (*f)(char *buf, int size, const procps_status_t *ps);
-	int ps_flags;
-} ps_out_t;
-
 static const ps_out_t out_spec[] = {
 // Mandated by POSIX:
 	{ 8                  , "user"  ,"USER"   ,func_user  ,PSSCAN_UIDGID  },
@@ -117,13 +264,17 @@
 	{ 5                  , "pid"   ,"PID"    ,func_pid   ,PSSCAN_PID     },
 	{ 5                  , "ppid"  ,"PPID"   ,func_ppid  ,PSSCAN_PPID    },
 	{ 5                  , "pgid"  ,"PGID"   ,func_pgid  ,PSSCAN_PGID    },
-//	{ sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_        },
+#if ENABLE_FEATURE_PS_TIME
+	{ sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_START_TIME },
+#endif
 //	{ sizeof("GROUP"  )-1, "group" ,"GROUP"  ,func_group ,PSSCAN_UIDGID  },
 //	{ sizeof("NI"     )-1, "nice"  ,"NI"     ,func_nice  ,PSSCAN_        },
 //	{ sizeof("%CPU"   )-1, "pcpu"  ,"%CPU"   ,func_pcpu  ,PSSCAN_        },
 //	{ sizeof("RGROUP" )-1, "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID  },
 //	{ sizeof("RUSER"  )-1, "ruser" ,"RUSER"  ,func_ruser ,PSSCAN_UIDGID  },
-//	{ sizeof("TIME"   )-1, "time"  ,"TIME"   ,func_time  ,PSSCAN_        },
+#if ENABLE_FEATURE_PS_TIME
+	{ 6                  , "time"  ,"TIME"   ,func_time  ,PSSCAN_STIME | PSSCAN_UTIME },
+#endif
 	{ 6                  , "tty"   ,"TT"     ,func_tty   ,PSSCAN_TTY     },
 	{ 4                  , "vsz"   ,"VSZ"    ,func_vsz   ,PSSCAN_VSZ     },
 // Not mandated by POSIX, but useful:
@@ -133,31 +284,6 @@
 #endif
 };
 
-#if ENABLE_SELINUX
-#define SELINIX_O_PREFIX "label,"
-#define DEFAULT_O_STR    SELINIX_O_PREFIX "pid,user" /* TODO: ,vsz,stat */ ",args"
-#else
-#define DEFAULT_O_STR    "pid,user" /* TODO: ,vsz,stat */ ",args"
-#endif
-
-struct globals {
-	ps_out_t* out;
-	int out_cnt;
-	int print_header;
-	int need_flags;
-	char *buffer;
-	unsigned terminal_width;
-	char default_o[sizeof(DEFAULT_O_STR)];
-};
-#define G (*(struct globals*)&bb_common_bufsiz1)
-#define out            (G.out           )
-#define out_cnt        (G.out_cnt       )
-#define print_header   (G.print_header  )
-#define need_flags     (G.need_flags    )
-#define buffer         (G.buffer        )
-#define terminal_width (G.terminal_width)
-#define default_o      (G.default_o     )
-
 static ps_out_t* new_out_t(void)
 {
 	int i = out_cnt++;




More information about the busybox-cvs mailing list