From 08278d0e75e1d8eed7660fb80ed6b5354d5a5407 Mon Sep 17 00:00:00 2001 From: jrray Date: Mon, 14 Feb 2000 13:19:19 +0000 Subject: [PATCH] Added a multi-processor CPU usage display, doesn't work on uni-processor machines (would show a blank screen, I think). --- clients/lcdproc/Makefile.am | 2 +- clients/lcdproc/cpu_smp.c | 249 ++++++++++++++++++++++++++++++++++++ clients/lcdproc/cpu_smp.h | 11 ++ clients/lcdproc/main.c | 3 +- clients/lcdproc/mode.c | 9 +- 5 files changed, 271 insertions(+), 3 deletions(-) create mode 100644 clients/lcdproc/cpu_smp.c create mode 100644 clients/lcdproc/cpu_smp.h diff --git a/clients/lcdproc/Makefile.am b/clients/lcdproc/Makefile.am index 959dae8..9f8a4b2 100644 --- a/clients/lcdproc/Makefile.am +++ b/clients/lcdproc/Makefile.am @@ -1,3 +1,3 @@ bin_PROGRAMS = lcdproc -lcdproc_SOURCES = main.c main.h mode.c mode.h batt.c batt.h chrono.c chrono.h cpu.c cpu.h disk.c disk.h load.c load.h mem.c mem.h +lcdproc_SOURCES = main.c main.h mode.c mode.h batt.c batt.h chrono.c chrono.h cpu.c cpu.h cpu_smp.c cpu_smp.h disk.c disk.h load.c load.h mem.c mem.h lcdproc_LDADD = ../../shared/libLCDstuff.a diff --git a/clients/lcdproc/cpu_smp.c b/clients/lcdproc/cpu_smp.c new file mode 100644 index 0000000..fd89664 --- /dev/null +++ b/clients/lcdproc/cpu_smp.c @@ -0,0 +1,249 @@ +/****************************************************************************** +* +* cpu_smp.c - dipslay cpu info for multi-processor machines +* Copyright (C) 2000 J Robert Ray +* +* Adapted from cpu.c. +* +* Really boring for the moment, it only shows a current usage percentage graph +* for each CPU. +* +* It will handle up to 2xlcd_hgt or 8 CPUs, whichever is less. If there are +* more CPUs than lines on the LCD, it puts 2 CPUs per line, splitting the line +* in half. Otherwise, it uses one line per CPU. +* +* If you have a four-line display and a dual-processor machine, two lines will +* go unused. This would be a good spot for a histogram or other info. Also, +* it could always display two CPUs per line to provide extra space for other +* info, when there otherwise wouldn't be extra space (e.g., on a two proc- +* machine, with a two-line LCD [this is my setup]). +* +* --- +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* --- +* +* $Source$ +* $Revision$ $Date$ +* Checked in by: $Author$ +* +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "../../shared/sockets.h" +#include "../../shared/debug.h" + +#include "main.h" +#include "mode.h" +#include "cpu_smp.h" + +#define MAX_CPUS 8 + +struct load { unsigned long total, user, system, nice, idle; }; + +static int load_fd = 0; + +static char *numnames[MAX_CPUS] = {"one", "two", "three", "four", "five", "six", "seven", "eight"}; + +static void +get_load(struct load *result, int *numcpus) +{ + char *token; + static struct load last_load[MAX_CPUS]; + struct load curr_load[MAX_CPUS]; + + *numcpus = 0; + + reread (load_fd, "get_load"); + + // Look for lines starting with "cpu0", "cpu1", etc. + + token = strtok (buffer, "\n"); + while (token) { + if (token[0] == 'c') { + if (isdigit (token[3])) { + sscanf(token, "%*s %lu %lu %lu %lu", + &curr_load[*numcpus].user, + &curr_load[*numcpus].nice, + &curr_load[*numcpus].system, + &curr_load[*numcpus].idle); + + curr_load[*numcpus].total = curr_load[*numcpus].user + + curr_load[*numcpus].nice + + curr_load[*numcpus].system + + curr_load[*numcpus].idle; + result[*numcpus].total = curr_load[*numcpus].total - last_load[*numcpus].total; + result[*numcpus].user = curr_load[*numcpus].user - last_load[*numcpus].user; + result[*numcpus].nice = curr_load[*numcpus].nice - last_load[*numcpus].nice; + result[*numcpus].system = curr_load[*numcpus].system - last_load[*numcpus].system; + result[*numcpus].idle = curr_load[*numcpus].idle - last_load[*numcpus].idle; + last_load[*numcpus].total = curr_load[*numcpus].total; + last_load[*numcpus].user = curr_load[*numcpus].user; + last_load[*numcpus].nice = curr_load[*numcpus].nice; + last_load[*numcpus].system = curr_load[*numcpus].system; + last_load[*numcpus].idle = curr_load[*numcpus].idle; + + (*numcpus)++; + } + } else { + break; + } + token = strtok (NULL, "\n"); + } +} + + +int +cpu_smp_init() +{ + if(!load_fd) { + load_fd = open ("/proc/stat", O_RDONLY); + } + + return 0; +} + +int +cpu_smp_close() +{ + if (load_fd) + close (load_fd); + + load_fd = 0; + + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +// CPU screen shows info about percentage of the CPU being used +// +int +cpu_smp_screen(int rep, int display) +{ +#undef CPU_BUF_SIZE +#define CPU_BUF_SIZE 4 + int i, j, n, z; + static int first = 1; + float value; + static float cpu[MAX_CPUS][CPU_BUF_SIZE + 1][5];// last buffer is scratch + struct load load[MAX_CPUS]; + int numprocs; + char buf[256]; + char* graphsize; + + if(first) + { + first = 0; + + get_load(load, &numprocs); + + sock_send_string(sock, "screen_add P\n"); + sock_send_string(sock, "widget_del P heartbeat\n"); + + sprintf(buffer, "screen_set P -name {CPU Use: %s}\n", host); + sock_send_string(sock, buffer); + + graphsize = calloc (sizeof (char), lcd_wid); + if (numprocs > lcd_hgt) { + for (i=0; i lcd_hgt*2) break; + + sprintf (buf, "widget_add P %s_title string\n", numnames[i]); + sock_send_string (sock, buf); + + if (numprocs > lcd_hgt) { + sprintf (buf, "widget_set P %s_title %d %d \"CPU%d[%s]\"\n", numnames[i], i%2 * lcd_wid/2 + 1, i/2+1, i, graphsize); + } else { + sprintf (buf, "widget_set P %s_title 1 %d \"CPU%d[%s]\"\n", numnames[i], i+1, i, graphsize); + } + sock_send_string (sock, buf); + + sprintf (buf, "widget_add P %s_bar hbar\n", numnames[i]); + sock_send_string (sock, buf); + } + + free (graphsize); + + return 0; + } + + get_load(load, &numprocs); + + for (z=0; z lcd_hgt) { + n = (float)(value * lcd_cellwid * ((float)lcd_wid/2.f-6.f)) / 100.f + .5f; + sprintf (buf, "widget_set P %s_bar %d %d %d\n", numnames[z], z%2 * lcd_wid/2 + 6, z/2+1, n); + } else { + n = (float)(value * lcd_cellwid * ((float)lcd_wid-6.f)) / 100.f + .5f; + sprintf (buf, "widget_set P %s_bar 6 %d %d\n", numnames[z], z+1, n); + } + sock_send_string (sock, buf); + + if (z+1 > lcd_hgt*2) break; + } + + return 0; +} // End cpu_screen() diff --git a/clients/lcdproc/cpu_smp.h b/clients/lcdproc/cpu_smp.h new file mode 100644 index 0000000..ac2c1fa --- /dev/null +++ b/clients/lcdproc/cpu_smp.h @@ -0,0 +1,11 @@ +#ifndef CPU_SMP_H +#define CPU_SMP_H + + +int cpu_smp_init(); +int cpu_smp_close(); + + +int cpu_smp_screen(int rep, int display); + +#endif diff --git a/clients/lcdproc/main.c b/clients/lcdproc/main.c index 3a72043..ff31296 100644 --- a/clients/lcdproc/main.c +++ b/clients/lcdproc/main.c @@ -61,6 +61,7 @@ mode default_sequence[] = { 1 , 0, 0, 0, 0,0,},// Modes after this line will not be run by default... // ... all non-default modes must be in here! // ... they will not show up otherwise. + { 'P', 1, 2, 0, 0xffff,0,},// [O]ld Timescreen { 'O', 4, 64, 0, 0xffff,0,},// [O]ld Timescreen { 'K', 4, 64, 0, 0xffff,0,},// big cloc[K] { 'U', 4, 128, 0, 0xffff,0,},// Old [U]ptime Screen @@ -191,7 +192,7 @@ void HelpScreen() printf("Usage: lcdproc [-s server] [-p port] [modelist]\n"); printf("\tOptions in []'s are optional.\n"); printf("\tmodelist is \"mode [mode mode ...]\"\n"); - printf("\tMode letters: \t[C]pu [G]raph [T]ime [M]emory [X]load [D]isk [B]attery\n\t\t\tproc_[S]izes [O]ld_time big_cloc[K] [U]ptime [A]bout\n"); + printf("\tMode letters: \t[C]pu [G]raph [T]ime [M]emory [X]load [D]isk [B]attery\n\t\t\tproc_[S]izes [O]ld_time big_cloc[K] [U]ptime CPU_SM[P]\n\t\t\t[A]bout\n"); printf("\n"); printf("\tUse \"man lcdproc\" for more info.\n"); printf("Example:\n"); diff --git a/clients/lcdproc/mode.c b/clients/lcdproc/mode.c index dabc197..1553056 100644 --- a/clients/lcdproc/mode.c +++ b/clients/lcdproc/mode.c @@ -24,6 +24,7 @@ #include "batt.h" #include "chrono.h" #include "cpu.h" +#include "cpu_smp.h" #include "disk.h" #include "load.h" #include "mem.h" @@ -113,6 +114,10 @@ int mode_init(mode *sequence) case 'a': case 'A': // credit_screen break; + case 'p': + case 'P': // cpu_smp_screen + cpu_smp_init (); + break; default: break; } } @@ -130,7 +135,7 @@ void mode_close() disk_close(); load_close(); mem_close(); - + cpu_smp_close (); } @@ -167,6 +172,8 @@ int update_screen(mode *m, int display) case 'B': status = battery_screen(m->timer, display); break; case 'a': case 'A': status = credit_screen(m->timer, display); break; + case 'p': + case 'P': status = cpu_smp_screen (m->timer, display); break; default: break; } /* Debugging tool...