--- wmcpu-1.3/wmcpu.c.bak 2001-05-25 15:30:58.000000000 +0300 +++ wmcpu-1.3/wmcpu.c 2007-01-06 04:56:16.606645294 +0200 @@ -1,3 +1,7 @@ +/* +vim:tw=76:ts=4:sw=4:cindent:expandtab +*/ + /* WMCPU 1.3 (c) 1998, 1999, 2000, 2001 timecop@japan.co.jp * Dockapp CPU usage monitor similar to XosView. * @@ -26,13 +30,44 @@ #include #include #include - +#include #include #include #include #include "master.xpm" +typedef unsigned long long jiff; + +extern void getstat(jiff *cuse, jiff *cice, jiff *csys, jiff *cide, + jiff *ciow, jiff *cxxx, jiff *cyyy, jiff *czzz, + unsigned long *pin, unsigned long *pout, + unsigned long *s_in, unsigned long *sout, + unsigned *intr, unsigned *ctxt, + unsigned int *running, unsigned int *blocked, + unsigned int *btime, unsigned int *processes); +extern void loadavg(double*, double*, double*); +extern void meminfo(void); +extern int uptime(double*, double*); + +extern unsigned long kb_main_total; +extern unsigned long kb_main_used; +extern unsigned long kb_main_free; +extern unsigned long kb_main_shared; +extern unsigned long kb_main_buffers; +extern unsigned long kb_main_cached; +extern unsigned long kb_active; +extern unsigned long kb_inactive; +extern unsigned long kb_slab; +extern unsigned long kb_pagetables; +extern unsigned long kb_dirty; +extern unsigned long kb_writeback; +extern unsigned long kb_swap_free; +extern unsigned long kb_swap_total; +extern unsigned long kb_swap_cached; +extern unsigned long kb_committed_as; +extern unsigned long kb_commitlimit; + #define WMCPU_VERSION "1.3" #define copy_xpm_area(x, y, w, h, dx, dy) \ @@ -40,14 +75,14 @@ #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define HELP_TEXT \ - "wmcpu: cpu usage monitor dockapp that looks like xosview\n" \ - " timecop@japan.co.jp\n" \ - "usage:\n" \ - "\t-display \n" \ - "\t-h\tthis screen\n" \ - "\t-v\tprint the version number\n" \ - "\t-l\tshow load as numbers\n" \ - "\t-t\ttime between refresh in usec (def= 250000)\n" + "wmcpu: cpu usage monitor dockapp that looks like xosview\n" \ + " timecop@japan.co.jp\n" \ + "usage:\n" \ + "\t-display \n" \ + "\t-h\tthis screen\n" \ + "\t-v\tprint the version number\n" \ + "\t-l\tshow load as numbers\n" \ + "\t-t\ttime between refresh in usec (def= 250000)\n" static char *display_name = NULL; static Display *display; @@ -56,11 +91,12 @@ static Window iconwin; static GC gc; static Pixmap pixmap; static Pixmap mask; -static unsigned long udelay = 250000; +static unsigned long udelay = 150000; static int gfx_loadbar = 1; +static int flag_swap; +static int flag_comm; static void wmcpu_routine(void); -static int uptime(void); static void redraw_window(void); static void new_window(char *name, int width, int height); @@ -68,33 +104,42 @@ int main(int argc, char **argv) { int ch; - while ((ch = getopt(argc, argv, "d:hvlt:")) != EOF) { - switch (ch) { - case 'd': - if (optarg) - display_name = strdup(optarg); - break; - case 'v': - fprintf(stderr, "%s\n", WMCPU_VERSION); - exit(0); - break; - case 'l': - gfx_loadbar = 0; - break; - case 't': - if (optarg) - udelay = atol(optarg); - break; - default: - fputs(HELP_TEXT, stdout); - exit(0); - break; - } + while ((ch = getopt(argc, argv, "d:hvlt:sc")) != EOF) { + switch (ch) { + case 'd': + if (optarg) + display_name = strdup(optarg); + break; + case 'v': + fprintf(stderr, "%s\n", WMCPU_VERSION); + exit(0); + break; + case 'l': + gfx_loadbar = 0; + break; + case 't': + if (optarg) { + udelay = atol(optarg); + if (udelay <= 10000) + udelay = 10000; + } + break; + case 's': + flag_swap = 1; + break; + case 'c': + flag_comm = 1; + break; + default: + fputs(HELP_TEXT, stdout); + exit(0); + break; + } } if ((display = XOpenDisplay(display_name)) == NULL) { - fprintf(stderr, "Unable to open display \"%s\"\n", display_name); - return EXIT_FAILURE; + fprintf(stderr, "Unable to open display \"%s\"\n", display_name); + return EXIT_FAILURE; } wmcpu_routine(); @@ -112,188 +157,281 @@ void wmcpu_routine(void) value should be 100 times the second entry in the uptime pseudo-file. */ - static float cpustat[4]; /* remember the statistics read last time */ int tempy; int upt, days = 0, hours = 0, mins = 0; + double uptime_secs, idle_secs; XEvent Event; - FILE *fp; - char str[32]; - float info[4], ftmp; + jiff info[7]; int old_mins = -1; int i; new_window("wmcpu", 64, 64); while (1) { - if ((fp = fopen("/proc/stat", "r")) != NULL) { - long int CPUuser, CPUnice, CPUsyst; - fscanf(fp, "%s %f %f %f %f", str, info, info + 1, info + 2, - info + 3); - - if (cpustat[0] != 0) { - float fields[4], total = 0.0; - for (i = 0; i < 4; i++) { - fields[i] = info[i] - cpustat[i]; - total += fields[i]; - } - if (total > 0) { - int xoffset = 5; - int barwidth = 54; - CPUuser = fields[0] / total * (barwidth - 0.5); - CPUnice = fields[1] / total * (barwidth - 0.5); - CPUsyst = fields[2] / total * (barwidth - 0.5); - copy_xpm_area(3, 93, CPUuser, 9, xoffset, 5); - copy_xpm_area(3, 75, CPUnice, 9, xoffset + CPUuser, 5); - copy_xpm_area(3, 84, CPUsyst, 9, - xoffset + CPUuser + CPUnice, 5); - copy_xpm_area(3, 102, - (54 - (CPUuser + CPUnice + CPUsyst)), 9, - xoffset + CPUuser + CPUnice + CPUsyst, 5); - - } - } - for (i = 0; i < 4; i++) - cpustat[i] = info[i]; - fclose(fp); - } - - /* /proc/loadavg - The load average numbers give the number of jobs in - the run queue averaged over 1, 5 and 15 minutes. - They are the same as the load average numbers given - by uptime(1) and other programs. */ - if ((fp = fopen("/proc/loadavg", "r")) != NULL) { - static float oldv = 0.0; - fscanf(fp, "%f", &ftmp); - if (oldv != ftmp) { - int tempx; - oldv = info[0]; - if (gfx_loadbar) { - oldv = ftmp; - i = MIN(54, (ftmp * 54)); - copy_xpm_area(3, 75, i, 9, 5, 33); - copy_xpm_area(3, 102, 54 - i, 9, 5 + i, 33); - } else { - tempx = ftmp * 100; - if (tempx > 9999) - tempx = 9999; - if (tempx > 1000) { - tempy = tempx / 1000; - copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 15, 33); - } else - copy_xpm_area(68, 66, 6, 9, 15, 33); - tempy = (tempx / 100) % 10; - copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 21, 33); - - copy_xpm_area(65, 66, 3, 9, 28, 33); - - tempy = (tempx / 10) % 10; - copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 31, 33); - - tempy = tempx % 10; - copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 37, 33); - } - } - fclose(fp); - } - - /* /proc/meminfo - This is used by free(1) to report the amount of - free and used memory (both physical and swap) on - the system as well as the shared memory and buffers - used by the kernel. */ - if ((fp = fopen("/proc/meminfo", "r")) != NULL) { - static float stotal = 0.0; - static float suser = 0.0; - static float sshared = 0.0; - static float sbuffers = 0.0; - char junk[512]; - float total, used, freeM, shared, buffers, cached, progs; - long int MEMshar, MEMbuff, MEMcach, MEMprog; - - fgets(junk, 500, fp); - fscanf(fp, "%s %f %f %f %f %f %f", junk, &total, &used, &freeM, - &shared, &buffers, &cached); - progs = used - cached - buffers - shared; - if (stotal != total || suser != progs || sshared != shared - || sbuffers != buffers) { - int xoffset = 5; - int barwidth = 54; - stotal = total; - suser = progs; - sshared = shared; - sbuffers = buffers; - MEMprog = (progs * barwidth) / total; - MEMshar = (shared * barwidth) / total; - MEMbuff = (buffers * barwidth) / total; - MEMcach = (cached * barwidth) / total; - copy_xpm_area(3, 111, MEMprog, 9, xoffset, 19); - copy_xpm_area(3, 129, MEMshar, 9, xoffset + MEMprog, 19); - copy_xpm_area(3, 120, MEMbuff, 9, - xoffset + MEMprog + MEMshar, 19); - copy_xpm_area(3, 84, MEMcach, 9, - xoffset + MEMprog + MEMshar + MEMbuff, 19); - copy_xpm_area(3, 102, - (barwidth - - (MEMprog + MEMshar + MEMbuff + MEMcach)), 9, - xoffset + MEMprog + MEMshar + MEMbuff + - MEMcach, 19); - } - fclose(fp); - } - - /* End meminfo */ - upt = uptime(); - mins = (upt / 60) % 60; - hours = (upt / 3600) % 24; - days = (upt / 86400); - if (old_mins != mins) { - old_mins = mins; - tempy = mins % 10; - copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 50, 48); - tempy = mins / 10; - copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 44, 48); - copy_xpm_area(63, 66, 3, 9, 41, 48); - tempy = hours % 10; - copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 34, 48); - tempy = hours / 10; - copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 28, 48); - copy_xpm_area(63, 66, 3, 9, 25, 48); - tempy = days % 10; - copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 18, 48); - tempy = days / 10; - copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 12, 48); - tempy = days / 100; - copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 6, 48); - } - - while (XPending(display)) { - XNextEvent(display, &Event); - switch (Event.type) { - case Expose: - redraw_window(); - break; - case DestroyNotify: - XCloseDisplay(display); - exit(0); - break; - } - } - redraw_window(); - usleep(udelay); + static jiff cpustat[7]; /* remember the statistics read last time */ + jiff CPUuser, CPUsyst, CPUiow; + unsigned long unusedl; + unsigned long long unusedll; + unsigned int unusedint; + + getstat(&info[0], &info[1], &info[2], &info[3], &info[4], &info[5], &info[6], + &unusedll, &unusedl, &unusedl, &unusedl, &unusedl, + &unusedint, &unusedint, &unusedint, &unusedint, &unusedint, &unusedint); + + if (cpustat[0] != 0) { + jiff fields[7]; + jiff Div, divo2; + jiff duse, dsys, didl, diow; + int xoffset = 5; + int barwidth = 54; + +#if 0 + fprintf(stderr, "getstat: %llu %llu %llu %llu %llu %llu %llu\n", + info[0], info[1], info[2], info[3], info[4], info[5], info[6]); +#endif + for (i = 0; i < 7; i++) { + fields[i] = info[i] - cpustat[i]; + } + + duse = fields[0] + fields[1]; + dsys = fields[2] + fields[5] + fields[6]; + didl = fields[3]; + diow = fields[4]; + Div = duse + dsys + didl + diow; + divo2 = Div/2UL; +#if 0 + fprintf(stderr, "duse=%llu dsys=%llu didl=%llu diow=%llu Div=%llu\n", + duse, dsys, didl, diow, Div); +#endif + + if (Div > 0) { + CPUuser = (duse * barwidth) / Div; + CPUsyst = (dsys * barwidth) / Div; + CPUiow = (diow * barwidth) / Div; +#if 0 + fprintf(stderr, "CPUuser=%llu CPUsyst=%llu CPUiow=%llu\n", + CPUuser, CPUsyst, CPUiow); +#endif + copy_xpm_area(3, 93, CPUuser, 9, xoffset, 5); + xoffset += CPUuser; + copy_xpm_area(3, 75, CPUsyst, 9, xoffset, 5); + xoffset += CPUsyst; + copy_xpm_area(3, 84, CPUiow, 9, xoffset, 5); + xoffset += CPUiow; + copy_xpm_area(3, 102, + (54 - (CPUuser + CPUsyst + CPUiow)), 9, xoffset, 5); + } + } + for (i = 0; i < 7; i++) + cpustat[i] = info[i]; + + /* /proc/loadavg + The load average numbers give the number of jobs in + the run queue averaged over 1, 5 and 15 minutes. + They are the same as the load average numbers given + by uptime(1) and other programs. */ + if (1) { + static double oldv = 0; + double av1, av5, av15; + + loadavg(&av1, &av5, &av15); + if (oldv != av1) { + int tempx; + oldv = info[0]; + if (gfx_loadbar) { + oldv = av1; + i = MIN(54, (av1 * 54)); + copy_xpm_area(3, 75, i, 9, 5, 33); + copy_xpm_area(3, 102, 54 - i, 9, 5 + i, 33); + } else { + tempx = av1 * 100; + if (tempx > 9999) + tempx = 9999; + if (tempx > 1000) { + tempy = tempx / 1000; + copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 15, 33); + } else + copy_xpm_area(68, 66, 6, 9, 15, 33); + tempy = (tempx / 100) % 10; + copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 21, 33); + + copy_xpm_area(65, 66, 3, 9, 28, 33); + + tempy = (tempx / 10) % 10; + copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 31, 33); + + tempy = tempx % 10; + copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 37, 33); + } + } + } + + meminfo(); + + /* /proc/meminfo + This is used by free(1) to report the amount of + free and used memory (both physical and swap) on + the system as well as the shared memory and buffers + used by the kernel. */ + if (1) { + static unsigned long stotal = 0; + static unsigned long sactive = 0; + static unsigned long sinactive = 0; + static unsigned long sdirty = 0; + static unsigned long swriteback = 0; + uint64_t total, active, inactive, dirty, writeback; + + total = kb_main_total; + active = kb_active + kb_slab + kb_pagetables; + inactive = kb_inactive - kb_dirty - kb_writeback; + dirty = kb_dirty - kb_writeback; + writeback = kb_writeback; + + if ((stotal != total) || (sactive != active) || + (sinactive != inactive) || (sdirty != dirty) || + (swriteback != writeback)) { + int xoffset = 5; + int barwidth = 54; + + stotal = total; + sactive = active; + sinactive = inactive; + sdirty = dirty; + swriteback = writeback; + + active *= barwidth; + active /= total; + inactive *= barwidth; + inactive /= total; + dirty *= barwidth; + dirty /= total; + writeback *= barwidth; + writeback /= total; + copy_xpm_area(3, 111, active, 9, xoffset, 19); + xoffset += active; + copy_xpm_area(3, 129, inactive, 9, xoffset, 19); + xoffset += inactive; + copy_xpm_area(3, 120, dirty, 9, xoffset, 19); + xoffset += dirty; + copy_xpm_area(3, 84, writeback, 9, xoffset, 19); + xoffset += writeback; + copy_xpm_area(3, 102, + (barwidth - (active + inactive + dirty + writeback)), + 9, xoffset, 19); + } + } + + if (flag_swap) { + static unsigned long sswaptotal = 0; + static unsigned long sswapfree = 0; + static unsigned long sswapcached = 0; + /* unsigned long long to prevent overflow when multiplying */ + uint64_t swaptotal, swapfree, swapcached; + + swaptotal = kb_swap_total; + swapfree = kb_swap_free; + swapcached = kb_swap_cached; + + if ((sswaptotal != swaptotal) || (sswapfree != swapfree) || + (sswapcached != swapcached)) { + int xoffset = 5; + int barwidth = 54; + + sswaptotal = swaptotal; + sswapfree = swapfree; + sswapcached = swapcached; + + swapcached *= barwidth; + swapcached /= swaptotal; + swapfree *= barwidth; + swapfree /= swaptotal; + copy_xpm_area(3, 111, swapfree, 9, xoffset, 49); + xoffset += swapfree; + copy_xpm_area(3, 129, swapcached, 9, xoffset, 49); + xoffset += swapcached; + copy_xpm_area(3, 102, (barwidth - (swapfree + swapcached)), + 9, xoffset, 49); + } + } else if (flag_comm) { + static unsigned long scommtotal = 0; + static unsigned long scommas = 0; + static unsigned long sactive = 0; + static unsigned long sinactive = 0; + uint64_t commtotal, commas, active, inactive, other; + + commtotal = kb_commitlimit; + commas = kb_committed_as; + active = kb_active; + inactive = kb_inactive; + + if ((scommtotal != commtotal) || (scommas != commas) || + (sactive != active) || (sinactive != inactive)) { + int xoffset = 5; + int barwidth = 54; + + scommtotal = commtotal; + scommas = commas; + sactive = active; + sinactive = inactive; + + active *= barwidth; + active /= commtotal; + inactive *= barwidth; + inactive /= commtotal; + other = (commas - active - inactive) * barwidth; + other /= commtotal; + copy_xpm_area(3, 111, active, 9, xoffset, 49); + xoffset += active; + copy_xpm_area(3, 129, inactive, 9, xoffset, 49); + xoffset += inactive; + copy_xpm_area(3, 120, other, 9, xoffset, 49); + xoffset += other; + copy_xpm_area(3, 102, (barwidth - (active + inactive + other)), + 9, xoffset, 49); + } + } else { + upt = uptime(&uptime_secs, &idle_secs); + mins = (upt / 60) % 60; + hours = (upt / 3600) % 24; + days = (upt / 86400); + if (old_mins != mins) { + old_mins = mins; + tempy = mins % 10; + copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 50, 48); + tempy = mins / 10; + copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 44, 48); + copy_xpm_area(63, 66, 3, 9, 41, 48); + tempy = hours % 10; + copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 34, 48); + tempy = hours / 10; + copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 28, 48); + copy_xpm_area(63, 66, 3, 9, 25, 48); + tempy = days % 10; + copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 18, 48); + tempy = days / 10; + copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 12, 48); + tempy = days / 100; + copy_xpm_area(3 + (tempy * 6), 66, 6, 9, 6, 48); + } + } + + while (XPending(display)) { + XNextEvent(display, &Event); + switch (Event.type) { + case Expose: + redraw_window(); + break; + case DestroyNotify: + XCloseDisplay(display); + exit(0); + break; + } + } + redraw_window(); + usleep(udelay); } } -static int uptime(void) -{ - FILE *fp; - float fupt; - if ((fp = fopen("/proc/uptime", "r")) != NULL) - fscanf(fp, "%f", &fupt); - fclose(fp); - return fupt; -} - static void new_window(char *name, int width, int height) { XpmAttributes attr; @@ -314,13 +452,13 @@ static void new_window(char *name, int w bg = WhitePixel(display, DefaultScreen(display)); win = XCreateSimpleWindow(display, DefaultRootWindow(display), - sizehints.x, sizehints.y, - sizehints.width, sizehints.height, 1, fg, - bg); + sizehints.x, sizehints.y, + sizehints.width, sizehints.height, 1, fg, + bg); iconwin = XCreateSimpleWindow(display, win, sizehints.x, sizehints.y, - sizehints.width, sizehints.height, 1, fg, - bg); + sizehints.width, sizehints.height, 1, fg, + bg); XSetWMNormalHints(display, win, &sizehints); classhint.res_name = name; @@ -344,24 +482,24 @@ static void new_window(char *name, int w gcval.graphics_exposures = 0; gc = XCreateGC(display, win, - GCForeground | GCBackground | GCGraphicsExposures, - &gcval); + GCForeground | GCBackground | GCGraphicsExposures, + &gcval); attr.exactColors = 0; attr.alloc_close_colors = 1; attr.closeness = 30000; attr.valuemask = (XpmExactColors | XpmAllocCloseColors | XpmCloseness); if ((XpmCreatePixmapFromData(display, DefaultRootWindow(display), - master_xpm, &pixmap, &mask, - &attr) != XpmSuccess)) { - fputs("Cannot allocate colors for the dockapp pixmap!\n", stderr); - exit(EXIT_FAILURE); + master_xpm, &pixmap, &mask, + &attr) != XpmSuccess)) { + fputs("Cannot allocate colors for the dockapp pixmap!\n", stderr); + exit(EXIT_FAILURE); } XShapeCombineMask(display, win, ShapeBounding, 0, 0, mask, - ShapeSet); + ShapeSet); XShapeCombineMask(display, iconwin, ShapeBounding, 0, 0, mask, - ShapeSet); + ShapeSet); wmhints.initial_state = WithdrawnState; wmhints.icon_window = iconwin; @@ -369,7 +507,7 @@ static void new_window(char *name, int w wmhints.icon_y = sizehints.y; wmhints.window_group = win; wmhints.flags = - StateHint | IconWindowHint | IconPositionHint | WindowGroupHint; + StateHint | IconWindowHint | IconPositionHint | WindowGroupHint; XSetWMHints(display, win, &wmhints); XMapWindow(display, win); @@ -380,3 +518,4 @@ static void redraw_window(void) XCopyArea(display, pixmap, iconwin, gc, 0, 0, 64, 64, 0, 0); XCopyArea(display, pixmap, win, gc, 0, 0, 64, 64, 0, 0); } +