Hello,

the attached patch adds 'time' and 'etime' for ps.
It adds more than 2k (but only for CONFIG_DESKTOP) because of
the expensive computation of HZ.
If we omit support for pre-2.4 Linux, the space addition would go
way done.

  Detlef

-- 
Detlef Vollmann   vollmann engineering gmbh
Linux and C++ for Embedded Systems    http://www.vollmann.ch/
diff -Nupr busybox-1.9.0-orig/include/libbb.h busybox-1.9.0/include/libbb.h
--- busybox-1.9.0-orig/include/libbb.h  Fri Dec 21 23:00:31 2007
+++ busybox-1.9.0/include/libbb.h       Thu Jan  3 21:59:37 2008
@@ -982,6 +982,7 @@ typedef struct procps_status_t {
         * 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;
@@ -1024,11 +1025,12 @@ enum {
        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);
@@ -1040,6 +1042,11 @@ void read_cmdline(char *buf, int col, un
 pid_t *find_pid_by_name(const char* procName);
 pid_t *pidlist_reverse(pid_t *pidList);
 
+#if ENABLE_DESKTOP
+extern unsigned long Hertz;
+extern unsigned long seconds_since_boot;
+void init_hertz(void);
+#endif
 
 extern const char bb_uuenc_tbl_base64[];
 extern const char bb_uuenc_tbl_std[];
diff -Nupr busybox-1.9.0-orig/libbb/procps.c busybox-1.9.0/libbb/procps.c
--- busybox-1.9.0-orig/libbb/procps.c   Fri Dec 21 23:00:29 2007
+++ busybox-1.9.0/libbb/procps.c        Thu Jan  3 22:52:59 2008
@@ -243,7 +243,8 @@ procps_status_t *procps_scan(procps_stat
                                "%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 @@ procps_status_t *procps_scan(procps_stat
                                &sp->pgid, &sp->sid, &tty,
                                &sp->utime, &sp->stime,
                                &tasknice,
+                               &sp->start_time,
                                &vsz,
                                &rss);
                        if (n != 10)
@@ -280,7 +282,8 @@ procps_status_t *procps_scan(procps_stat
                        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? */
diff -Nupr busybox-1.9.0-orig/procps/Kbuild busybox-1.9.0/procps/Kbuild
--- busybox-1.9.0-orig/procps/Kbuild    Fri Dec 21 23:00:32 2007
+++ busybox-1.9.0/procps/Kbuild Thu Jan  3 15:58:11 2008
@@ -14,6 +14,7 @@ lib-$(CONFIG_PGREP)   += pgrep.o
 lib-$(CONFIG_PKILL)    += pgrep.o
 lib-$(CONFIG_PIDOF)    += pidof.o
 lib-$(CONFIG_PS)       += ps.o
+lib-$(CONFIG_PS)       += sysinfo.o
 lib-$(CONFIG_RENICE)   += renice.o
 lib-$(CONFIG_BB_SYSCTL)        += sysctl.o
 lib-$(CONFIG_TOP)      += top.o
diff -Nupr busybox-1.9.0-orig/procps/ps.c busybox-1.9.0/procps/ps.c
--- busybox-1.9.0-orig/procps/ps.c      Fri Dec 21 23:00:32 2007
+++ busybox-1.9.0/procps/ps.c   Thu Jan  3 22:54:16 2008
@@ -73,6 +73,30 @@ static void func_tty(char *buf, int size
                snprintf(buf, size+1, "%u,%u", ps->tty_major, ps->tty_minor);
 }
 
+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 = seconds_since_boot - (unsigned long)(ps->start_time / Hertz);
+       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) / Hertz;
+       ss = mm % 60;
+       mm /= 60;
+       snprintf(buf, size+1, "%3lu:%02u", mm, ss);
+}
+
 #if ENABLE_SELINUX
 static void func_label(char *buf, int size, const procps_status_t *ps)
 {
@@ -86,16 +110,6 @@ static void func_nice(char *buf, int siz
        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)
 {
 }
@@ -117,13 +131,13 @@ static const ps_out_t out_spec[] = {
        { 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_        },
+       { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_START_TIME 
},
 //     { 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_        },
+       { 6                  , "time"  ,"TIME"   ,func_time  ,PSSCAN_STIME | 
PSSCAN_UTIME },
        { 6                  , "tty"   ,"TT"     ,func_tty   ,PSSCAN_TTY     },
        { 4                  , "vsz"   ,"VSZ"    ,func_vsz   ,PSSCAN_VSZ     },
 // Not mandated by POSIX, but useful:
@@ -137,7 +151,7 @@ static const ps_out_t out_spec[] = {
 #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"
+#define DEFAULT_O_STR    "pid,user,time" /* TODO: ,vsz,stat */ ",args"
 #endif
 
 struct globals {
@@ -317,6 +331,7 @@ int ps_main(int argc, char **argv)
                parse_o(default_o);
        }
        post_process();
+       init_hertz();
 
        /* Was INT_MAX, but some libc's go belly up with printf("%.*s")
         * and such large widths */
diff -Nupr busybox-1.9.0-orig/procps/sysinfo.c busybox-1.9.0/procps/sysinfo.c
--- busybox-1.9.0-orig/procps/sysinfo.c Thu Jan  1 01:00:00 1970
+++ busybox-1.9.0/procps/sysinfo.c      Fri Jan  4 15:04:46 2008
@@ -0,0 +1,247 @@
+// sysinfo.c - compute the Hertz value (HZ inside the kernel)
+// taken from procps-3.2.7
+//
+// adaption for busybox by Detlef Vollmann, Siemens, January 2008
+// original copyright notices:
+// Copyright (C) 1992-1998 by Michael K. Johnson, [EMAIL PROTECTED]
+// Copyright 1998-2003 Albert Cahalan
+//
+// This file is placed under the conditions of the GNU Library
+// General Public License, version 2, or any later version.
+// See file COPYING for information on distribution conditions.
+//
+
+#if ENABLE_DESKTOP
+#include "libbb.h"
+
+#ifndef HZ
+#include <netinet/in.h>        /* htons */
+#endif
+
+#define BAD_OPEN_MESSAGE "Error: /proc must be mounted\n"
+
+#define STAT_FILE    "/proc/stat"
+#define UPTIME_FILE  "/proc/uptime"
+
+#define PROCPS_BUF_SIZE 1024
+
+
+/************** this part taken from version.c of procps-3.2.7 *********
+ * Linux kernel version information for procps utilities
+ * Copyright (c) 1996 Charles Blake <[EMAIL PROTECTED]>
+ */
+#include <sys/utsname.h>
+
+#define LINUX_VERSION(x,y,z)   (0x10000*(x) + 0x100*(y) + z)
+
+static int linux_version_code;
+
+static void init_Linux_version(void)
+{
+       static struct utsname uts;
+       int x = 0, y = 0, z = 0;        /* cleared in case sscanf() < 3 */
+
+       if (uname(&uts) == -1) {        /* failure implies impending death */
+               exit(1);
+       }
+       if (sscanf(uts.release, "%d.%d.%d", &x, &y, &z) < 3) {
+               fprintf(stderr, /* *very* unlikely to happen by accident */
+                               "Non-standard uts for running kernel:\n"
+                               "release %s=%d.%d.%d gives version code %d\n",
+                               uts.release, x, y, z, LINUX_VERSION(x, y, z));
+       }
+       linux_version_code = LINUX_VERSION(x, y, z);
+}
+
+/*********************** end version.c part ****************************/
+
+/***********************************************************************
+ * Some values in /proc are expressed in units of 1/HZ seconds, where HZ
+ * is the kernel clock tick rate. One of these units is called a jiffy.
+ * The HZ value used in the kernel may vary according to hacker desire.
+ * According to Linus Torvalds, this is not true. He considers the values
+ * in /proc as being in architecture-dependant units that have no relation
+ * to the kernel clock tick rate. Examination of the kernel source code
+ * reveals that opinion as wishful thinking.
+ *
+ * In any case, we need the HZ constant as used in /proc. (the real HZ value
+ * may differ, but we don't care) There are several ways we could get HZ:
+ *
+ * 1. Include the kernel header file. If it changes, recompile this library.
+ * 2. Use the sysconf() function. When HZ changes, recompile the C library!
+ * 3. Ask the kernel. This is obviously correct...
+ *
+ * Linus Torvalds won't let us ask the kernel, because he thinks we should
+ * not know the HZ value. Oh well, we don't have to listen to him.
+ * Someone smuggled out the HZ value. :-)
+ *
+ * This code should work fine, even if Linus fixes the kernel to match his
+ * stated behavior. The code only fails in case of a partial conversion.
+ *
+ * Recent update: on some architectures, the 2.4 kernel provides an
+ * ELF note to indicate HZ. This may be for ARM or user-mode Linux
+ * support. This ought to be investigated. Note that sysconf() is still
+ * unreliable, because it doesn't return an error code when it is
+ * used with a kernel that doesn't support the ELF note. On some other
+ * architectures there may be a system call or sysctl() that will work.
+ */
+
+unsigned long Hertz = 0;
+unsigned long seconds_since_boot = 0;
+static long smp_num_cpus = 0;
+
+static inline void file_to_buf(char const *filename, char *buf)
+{
+       if (open_read_close(filename, buf, sizeof(buf)) < 0) {
+               bb_error_msg_and_die(BAD_OPEN_MESSAGE);
+       }
+}
+
+static void old_Hertz_hack(void)
+{
+       char buf[PROCPS_BUF_SIZE];
+       unsigned long long user_j, nice_j, sys_j, other_j;      /* jiffies 
(clock ticks) */
+       double up_1, up_2, seconds;
+       unsigned long long jiffies;
+       unsigned h;
+
+       if (smp_num_cpus == 0) {
+               smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+               if (smp_num_cpus < 1) {
+                       smp_num_cpus = 1;       /* SPARC glibc is buggy */
+               }
+       }
+#if ENABLE_LOCALE_SUPPORT
+       char *restrict savelocale;
+
+       savelocale = setlocale(LC_NUMERIC, NULL);
+       setlocale(LC_NUMERIC, "C");
+#endif
+       do {
+               file_to_buf(UPTIME_FILE, buf);
+               sscanf(buf, "%lf", &up_1);
+               file_to_buf(STAT_FILE, buf);
+               sscanf(buf, "cpu %Lu %Lu %Lu %Lu", &user_j, &nice_j, &sys_j,
+                          &other_j);
+               file_to_buf(UPTIME_FILE, buf);
+               sscanf(buf, "%lf", &up_2);
+       } while ((long long) ((up_2 - up_1) * 1000.0 / up_1));  /* want under 
0.1% error */
+#if ENABLE_LOCALE_SUPPORT
+       setlocale(LC_NUMERIC, savelocale);
+#endif
+       jiffies = user_j + nice_j + sys_j + other_j;
+       seconds = (up_1 + up_2) / 2;
+       h = (unsigned) ((double) jiffies / seconds / smp_num_cpus);
+       /* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
+       switch (h) {
+       case 9 ... 11:
+               Hertz = 10;             /* S/390 (sometimes) */
+               break;
+       case 18 ... 22:
+               Hertz = 20;             /* user-mode Linux */
+               break;
+       case 30 ... 34:
+               Hertz = 32;             /* ia64 emulator */
+               break;
+       case 48 ... 52:
+               Hertz = 50;
+               break;
+       case 58 ... 61:
+               Hertz = 60;
+               break;
+       case 62 ... 65:
+               Hertz = 64;             /* StrongARM /Shark */
+               break;
+       case 95 ... 105:
+               Hertz = 100;    /* normal Linux */
+               break;
+       case 124 ... 132:
+               Hertz = 128;    /* MIPS, ARM */
+               break;
+       case 195 ... 204:
+               Hertz = 200;    /* normal << 1 */
+               break;
+       case 253 ... 260:
+               Hertz = 256;
+               break;
+       case 393 ... 408:
+               Hertz = 400;    /* normal << 2 */
+               break;
+       case 790 ... 808:
+               Hertz = 800;    /* normal << 3 */
+               break;
+       case 990 ... 1010:
+               Hertz = 1000;   /* ARM */
+               break;
+       case 1015 ... 1035:
+               Hertz = 1024;   /* Alpha, ia64 */
+               break;
+       case 1180 ... 1220:
+               Hertz = 1200;   /* Alpha */
+               break;
+       default:
+#ifdef HZ
+               Hertz = (unsigned long long) HZ;        /* <asm/param.h> */
+#else
+               /* If 32-bit or big-endian (not Alpha or ia64), assume HZ is 
100. */
+               Hertz = (sizeof(long) == sizeof(int)
+                                || htons(999) == 999) ? 100UL : 1024UL;
+#endif
+               fprintf(stderr, "Unknown HZ value! (%d) Assume %ld.\n", h, 
Hertz);
+       }
+       seconds_since_boot = seconds;
+}
+
+static void get_uptime(void)
+{
+       char buf[PROCPS_BUF_SIZE];
+
+#if ENABLE_LOCALE_SUPPORT
+       char *restrict savelocale;
+
+       savelocale = setlocale(LC_NUMERIC, NULL);
+       setlocale(LC_NUMERIC, "C");
+#endif
+
+       file_to_buf(UPTIME_FILE, buf);
+       sscanf(buf, "%lu", &seconds_since_boot);
+
+#if ENABLE_LOCALE_SUPPORT
+       setlocale(LC_NUMERIC, savelocale);
+#endif
+}
+
+#ifndef AT_CLKTCK
+#define AT_CLKTCK       17     // frequency of times()
+#endif
+#define NOTE_NOT_FOUND 42
+
+/* for ELF executables, notes are pushed before environment and args */
+static unsigned long find_elf_note(unsigned long findme)
+{
+       unsigned long *ep = (unsigned long *) environ;
+
+       while (*ep++);
+       while (*ep) {
+               if (ep[0] == findme) {
+                       return ep[1];
+               }
+               ep += 2;
+       }
+       return NOTE_NOT_FOUND;
+}
+
+void init_hertz(void)
+{
+       init_Linux_version();
+       if (linux_version_code > LINUX_VERSION(2, 4, 0)) {
+               Hertz = find_elf_note(AT_CLKTCK);
+               if (Hertz != NOTE_NOT_FOUND) {
+                       get_uptime();
+                       return;
+               }
+               fputs("2.4+ kernel w/o ELF notes? -- report this\n", stderr);
+       }
+       old_Hertz_hack();
+}
+#endif /* ENABLE_DESKTOP */
_______________________________________________
busybox mailing list
busybox@busybox.net
http://busybox.net/cgi-bin/mailman/listinfo/busybox

Reply via email to