top hotplug memory support
Another patch from Jim for top to support hot-pluggable memory. Not fully tested on real hot-pluggable memory because neither of us have it
This commit is contained in:
parent
29b8775c39
commit
a26c3bfa39
@ -13,7 +13,7 @@ global:
|
||||
Hertz; smp_num_cpus; have_privs; getbtime;
|
||||
sprint_uptime; uptime; user_from_uid; print_uptime; loadavg;
|
||||
pretty_print_signals; print_given_signals; unix_print_signals; signal_name_to_number; signal_number_to_name;
|
||||
meminfo; vminfo; getstat; getdiskstat; getpartitions_num; getslabinfo; get_pid_digits;
|
||||
cpuinfo; meminfo; vminfo; getstat; getdiskstat; getpartitions_num; getslabinfo; get_pid_digits;
|
||||
kb_active; kb_inactive; kb_main_buffers; kb_main_cached;
|
||||
kb_main_free; kb_main_total; kb_main_used; kb_swap_free;
|
||||
kb_swap_total; kb_swap_used; kb_main_shared;
|
||||
|
@ -24,9 +24,7 @@
|
||||
#include <netinet/in.h> /* htons */
|
||||
#endif
|
||||
|
||||
#ifndef OOMEM_ENABLE
|
||||
long smp_num_cpus; /* number of CPUs */
|
||||
#endif
|
||||
|
||||
#define BAD_OPEN_MESSAGE \
|
||||
"Error: /proc must be mounted\n" \
|
||||
@ -182,11 +180,7 @@ static void old_Hertz_hack(void){
|
||||
setlocale(LC_NUMERIC, savelocale);
|
||||
jiffies = user_j + nice_j + sys_j + other_j;
|
||||
seconds = (up_1 + up_2) / 2;
|
||||
#ifndef OOMEM_ENABLE
|
||||
h = (unsigned)( (double)jiffies/seconds/smp_num_cpus );
|
||||
#else
|
||||
h = (unsigned)( (double)jiffies/seconds/smp_num_cpus() );
|
||||
#endif
|
||||
/* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
|
||||
switch(h){
|
||||
case 9 ... 11 : Hertz = 10; break; /* S/390 (sometimes) */
|
||||
@ -252,44 +246,13 @@ static int check_for_privs(void){
|
||||
return !!rc;
|
||||
}
|
||||
|
||||
#ifdef OOMEM_ENABLE
|
||||
long smp_num_cpus(void)
|
||||
{
|
||||
static long _smp_num_cpus=-1; /* number of CPUs */
|
||||
|
||||
if (_smp_num_cpus != -1)
|
||||
return(_smp_num_cpus);
|
||||
|
||||
// ought to count CPUs in /proc/stat instead of relying
|
||||
// on glibc, which foolishly tries to parse /proc/cpuinfo
|
||||
//
|
||||
// SourceForge has an old Alpha running Linux 2.2.20 that
|
||||
// appears to have a non-SMP kernel on a 2-way SMP box.
|
||||
// _SC_NPROCESSORS_CONF returns 2, resulting in HZ=512
|
||||
// _SC_NPROCESSORS_ONLN returns 1, which should work OK
|
||||
|
||||
_smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if(_smp_num_cpus<1) _smp_num_cpus=1; /* SPARC glibc is buggy */
|
||||
|
||||
return(_smp_num_cpus);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void init_libproc(void) __attribute__((constructor));
|
||||
static void init_libproc(void){
|
||||
have_privs = check_for_privs();
|
||||
init_Linux_version(); /* Must be called before we check code */
|
||||
#ifndef OOMEM_ENABLE
|
||||
// ought to count CPUs in /proc/stat instead of relying
|
||||
// on glibc, which foolishly tries to parse /proc/cpuinfo
|
||||
//
|
||||
// SourceForge has an old Alpha running Linux 2.2.20 that
|
||||
// appears to have a non-SMP kernel on a 2-way SMP box.
|
||||
// _SC_NPROCESSORS_CONF returns 2, resulting in HZ=512
|
||||
// _SC_NPROCESSORS_ONLN returns 1, which should work OK
|
||||
smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if(smp_num_cpus<1) smp_num_cpus=1; /* SPARC glibc is buggy */
|
||||
#endif
|
||||
|
||||
cpuinfo();
|
||||
|
||||
if(linux_version_code > LINUX_VERSION(2, 4, 0)){
|
||||
Hertz = find_elf_note(AT_CLKTCK);
|
||||
if(Hertz!=NOTE_NOT_FOUND) return;
|
||||
@ -978,3 +941,19 @@ unsigned get_pid_digits(void){
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void cpuinfo (void) {
|
||||
// ought to count CPUs in /proc/stat instead of relying
|
||||
// on glibc, which foolishly tries to parse /proc/cpuinfo
|
||||
//
|
||||
// SourceForge has an old Alpha running Linux 2.2.20 that
|
||||
// appears to have a non-SMP kernel on a 2-way SMP box.
|
||||
// _SC_NPROCESSORS_CONF returns 2, resulting in HZ=512
|
||||
// _SC_NPROCESSORS_ONLN returns 1, which should work OK
|
||||
|
||||
smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (smp_num_cpus<1) /* SPARC glibc is buggy */
|
||||
smp_num_cpus=1;
|
||||
}
|
||||
|
@ -7,12 +7,8 @@
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
extern unsigned long long Hertz; /* clock tick frequency */
|
||||
#ifndef OOMEM_ENABLE
|
||||
extern long smp_num_cpus; /* number of CPUs */
|
||||
#else
|
||||
extern long smp_num_cpus(void); /* number of CPUs */
|
||||
#endif
|
||||
extern int have_privs; /* boolean, true if setuid or similar */
|
||||
extern long smp_num_cpus; /* number of CPUs */
|
||||
extern int have_privs; /* boolean, true if setuid or similar */
|
||||
|
||||
#if 0
|
||||
#define JT double
|
||||
@ -136,5 +132,7 @@ extern unsigned int getslabinfo (struct slab_cache**);
|
||||
|
||||
extern unsigned get_pid_digits(void) FUNCTION;
|
||||
|
||||
extern void cpuinfo (void);
|
||||
|
||||
EXTERN_C_END
|
||||
#endif /* SYSINFO_H */
|
||||
|
10
top.1
10
top.1
@ -59,9 +59,9 @@
|
||||
.ds FM full\-screen mode
|
||||
.ds KA arrow key
|
||||
.ds KS scrolling key
|
||||
.ds MP \fBphysical\fR memory
|
||||
.ds MS \fBshared\fR memory
|
||||
.ds MV \fBvirtual\fR memory
|
||||
.ds MP physical memory
|
||||
.ds MS shared memory
|
||||
.ds MV virtual memory
|
||||
.ds NT \fBNote\fR:
|
||||
.ds PU CPU
|
||||
.ds Pu cpu
|
||||
@ -775,9 +775,9 @@ line.
|
||||
|
||||
.TP 7
|
||||
\ \ \<\fBEnter\fR> or <\fBSpace\fR> :\fIRefresh-Display \fR
|
||||
These commands do nothing, they are simply ignored.
|
||||
However, they will awaken \*(We and following receipt of any input
|
||||
These commands awaken \*(We and following receipt of any input
|
||||
the entire display will be repainted.
|
||||
They also force an update of any hotplugged \*(Pu or \*(MP changes.
|
||||
|
||||
Use either of these keys if you have a large delay interval and wish
|
||||
to see current status,
|
||||
|
51
top.c
51
top.c
@ -1679,7 +1679,7 @@ static void zap_fieldstab (void) {
|
||||
|
||||
Cpu_pmax = 99.0;
|
||||
Fieldstab[P_CPU].fmts = "%#4.1f ";
|
||||
if (Rc.mode_irixps && Cpu_tot > 1 && !Thread_mode) {
|
||||
if (Rc.mode_irixps && Cpu_tot > 1 && !Thread_mode) {
|
||||
Cpu_pmax = 9999.0;
|
||||
Fieldstab[P_CPU].fmts = "%4.0f ";
|
||||
}
|
||||
@ -1696,13 +1696,13 @@ static void zap_fieldstab (void) {
|
||||
static CPU_t *cpus_refresh (CPU_t *cpus) {
|
||||
static const char err_read[] = "failed /proc/stat read";
|
||||
static FILE *fp = NULL;
|
||||
static int smp_sav = -1;
|
||||
static int sav_cpus = -1;
|
||||
char buf[MEDBUFSIZ]; // enough for /proc/stat CPU line (not the intr line)
|
||||
int i;
|
||||
|
||||
/*** hotplug_acclimated ***/
|
||||
if (smp_sav != SMP_NUM_CPUS) {
|
||||
Cpu_tot = smp_sav = SMP_NUM_CPUS;
|
||||
if (sav_cpus != smp_num_cpus) {
|
||||
Cpu_tot = sav_cpus = smp_num_cpus;
|
||||
zap_fieldstab();
|
||||
calibrate_fields();
|
||||
if (fp) { fclose(fp); fp = NULL; }
|
||||
@ -2000,11 +2000,38 @@ static proc_t **procs_refresh (proc_t **ppt) {
|
||||
#undef PTRsz
|
||||
#undef ENTsz
|
||||
} // end: procs_refresh
|
||||
|
||||
|
||||
/*
|
||||
* This serves as our interface to the memory & cpu count (sysinfo)
|
||||
* portion of libproc. In support of those hotpluggable resources,
|
||||
* the sampling frequencies are reduced so as to minimize overhead.
|
||||
* We'll strive to verify the number of cpus every 5 minutes and the
|
||||
* memory availability/usage every 3 seconds. */
|
||||
static void sysinfo_refresh (int forced) {
|
||||
static time_t mem_secs, cpu_secs;
|
||||
time_t cur_secs;
|
||||
|
||||
if (forced)
|
||||
mem_secs = cpu_secs = 0;
|
||||
time(&cur_secs);
|
||||
|
||||
if (3 <= cur_secs - mem_secs) {
|
||||
meminfo();
|
||||
mem_secs = cur_secs;
|
||||
}
|
||||
#ifndef PRETEND4CPUS
|
||||
if (300 <= cur_secs - cpu_secs) {
|
||||
cpuinfo();
|
||||
cpu_secs = cur_secs;
|
||||
}
|
||||
#endif
|
||||
} // end: sysinfo_refresh
|
||||
|
||||
/*###### Startup routines ##############################################*/
|
||||
|
||||
/*
|
||||
* No mater what *they* say, we handle the really really BIG and
|
||||
* No matter what *they* say, we handle the really really BIG and
|
||||
* IMPORTANT stuff upon which all those lessor functions depend! */
|
||||
static void before (char *me) {
|
||||
int i;
|
||||
@ -2015,10 +2042,9 @@ static void before (char *me) {
|
||||
|
||||
// establish cpu particulars -- even bigger!
|
||||
#ifdef PRETEND4CPUS
|
||||
SMP_NUM_CPUS = Cpu_tot = 4;
|
||||
#else
|
||||
Cpu_tot = SMP_NUM_CPUS;
|
||||
smp_num_cpus = 4;
|
||||
#endif
|
||||
Cpu_tot = smp_num_cpus;
|
||||
if (linux_version_code > LINUX_VERSION(2, 5, 41))
|
||||
Cpu_States_fmts = STATES_line2x5;
|
||||
if (linux_version_code >= LINUX_VERSION(2, 6, 0))
|
||||
@ -2081,6 +2107,7 @@ static void configs_read (void) {
|
||||
fbuf[0] = '\0';
|
||||
fgets(fbuf, sizeof(fbuf), fp); // sys rc file, line 2
|
||||
sscanf(fbuf, "%f", &Rc.delay_time);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
fp = fopen(Rc_name, "r");
|
||||
@ -3009,7 +3036,8 @@ static void do_key (int ch) {
|
||||
help_view();
|
||||
break;
|
||||
case kbd_ENTER: // these two will have the effect of waking us
|
||||
case kbd_SPACE: // from 'select()' then refreshing the display
|
||||
case kbd_SPACE: // from 'select()', updating hotplugged resources
|
||||
sysinfo_refresh(1); // and then refreshing the display
|
||||
break;
|
||||
default: // and now, the real work...
|
||||
for (i = 0; i < MAXTBL(key_tab); ++i)
|
||||
@ -3110,14 +3138,14 @@ static proc_t **summary_show (void) {
|
||||
|
||||
// whoa first time, gotta' prime the pump...
|
||||
if (!p_table) {
|
||||
struct timeval tv = { 0, 300000 };
|
||||
p_table = procs_refresh(NULL);
|
||||
putp(Cap_clr_scr);
|
||||
select(0, NULL, NULL, NULL, &tv); // sleep for a bit...
|
||||
usleep(LIB_USLEEP);
|
||||
} else
|
||||
putp(Batch ? "\n\n" : Cap_home);
|
||||
|
||||
p_table = procs_refresh(p_table);
|
||||
sysinfo_refresh(0);
|
||||
|
||||
// Display Uptime and Loadavg
|
||||
if (isROOM(View_LOADAV, 1)) {
|
||||
@ -3157,7 +3185,6 @@ static proc_t **summary_show (void) {
|
||||
}
|
||||
|
||||
// Display Memory and Swap stats
|
||||
meminfo();
|
||||
if (isROOM(View_MEMORY, 2)) {
|
||||
#define mkM(x) (unsigned long)(kb_main_ ## x >> shift)
|
||||
#define mkS(x) (unsigned long)(kb_swap_ ## x >> shift)
|
||||
|
17
top.h
17
top.h
@ -62,23 +62,16 @@
|
||||
#define STRSORTCMP strcmp
|
||||
#endif
|
||||
|
||||
#ifdef OOMEM_ENABLE
|
||||
/* FIXME: perhaps making this a function in the suse version of
|
||||
sysinfo.c was a prelude to hotpluggable updates -- unfortunately,
|
||||
the return value is invariant as currently implemented! */
|
||||
#define SMP_NUM_CPUS smp_num_cpus()
|
||||
#else
|
||||
#define SMP_NUM_CPUS smp_num_cpus
|
||||
#endif
|
||||
|
||||
|
||||
/*###### Some Miscellaneous constants ##################################*/
|
||||
|
||||
/* The default delay twix updates */
|
||||
#define DEF_DELAY 3.0
|
||||
|
||||
/* Length of time a 'message' is displayed (in microseconds) */
|
||||
/* Length of time a message is displayed and the duration
|
||||
of a 'priming' wait during library startup (in microseconds) */
|
||||
#define MSG_USLEEP (useconds_t)1250000
|
||||
#define LIB_USLEEP (useconds_t)150000
|
||||
|
||||
/* Specific process id monitoring support (command line only) */
|
||||
#define MONPIDMAX 20
|
||||
@ -592,9 +585,6 @@ typedef struct WIN_t {
|
||||
#if defined(ATEOJ_RPTHSH) && defined(OFF_HST_HASH)
|
||||
# error 'ATEOJ_RPTHSH' conflicts with 'OFF_HST_HASH'
|
||||
#endif
|
||||
#if defined(PRETEND4CPUS) && defined (OOMEM_ENABLE)
|
||||
# error 'PRETEND4CPUS' conflicts with 'OOMEM_ENABLE'
|
||||
#endif
|
||||
#if (LRGBUFSIZ < SCREENMAX)
|
||||
# error 'LRGBUFSIZ' must NOT be less than 'SCREENMAX'
|
||||
#endif
|
||||
@ -655,6 +645,7 @@ typedef struct WIN_t {
|
||||
#endif
|
||||
//atic void prochlp (proc_t *p);
|
||||
//atic proc_t **procs_refresh (proc_t **ppt);
|
||||
//atic void sysinfo_refresh (int forced);
|
||||
/*------ Startup routines ----------------------------------------------*/
|
||||
//atic void before (char *me);
|
||||
//atic void configs_read (void);
|
||||
|
69
w.c
69
w.c
@ -29,6 +29,7 @@
|
||||
#include <utmp.h>
|
||||
#include <locale.h>
|
||||
#include <termios.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
static int ignoreuser = 0; /* for '-u' */
|
||||
static proc_t **procs; /* our snapshot of the process table */
|
||||
@ -44,6 +45,7 @@ typedef struct utmp utmp_t;
|
||||
/* Uh... same thing as UT_NAMESIZE */
|
||||
#define USERSZ (sizeof u->ut_user)
|
||||
|
||||
#define MAX_FROM_LEN 16
|
||||
|
||||
/* This routine is careful since some programs leave utmp strings
|
||||
* unprintable. Always outputs at least 16 chars padded with spaces
|
||||
@ -57,7 +59,7 @@ static void print_host(const char *restrict host, int len) {
|
||||
/* for now, we'll just limit it to the 16 that the libc5 version
|
||||
* of utmp uses.
|
||||
*/
|
||||
if (len > 16) len = 16;
|
||||
if (len > MAX_FROM_LEN) len = MAX_FROM_LEN;
|
||||
last = host + len;
|
||||
for ( ; host < last ; host++){
|
||||
if (isprint(*host) && *host != ' ') {
|
||||
@ -67,8 +69,45 @@ static void print_host(const char *restrict host, int len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// space-fill, and a '-' too if needed to ensure the column exists
|
||||
if(width < 16) fputs("- "+width, stdout);
|
||||
/* space-fill, and a '-' too if needed to ensure the column exists */
|
||||
if(width < MAX_FROM_LEN) fputs("- "+width, stdout);
|
||||
}
|
||||
|
||||
/* This routine prints either the hostname or the IP address of the remote */
|
||||
static void print_from(const utmp_t *restrict const u, int ip_addresses) {
|
||||
char buf[MAX_FROM_LEN + 1];
|
||||
char buf_ipv6[INET6_ADDRSTRLEN];
|
||||
int len;
|
||||
int32_t ut_addr_v6[4]; /* IP address of remote host. */
|
||||
|
||||
if (ip_addresses) { /* -n switch used */
|
||||
memcpy(&ut_addr_v6, &u->ut_addr_v6, sizeof(ut_addr_v6));
|
||||
if (IN6_IS_ADDR_V4MAPPED(&ut_addr_v6)) {
|
||||
/* map back */
|
||||
ut_addr_v6[0] = ut_addr_v6[3];
|
||||
ut_addr_v6[1] = 0;
|
||||
ut_addr_v6[2] = 0;
|
||||
ut_addr_v6[3] = 0;
|
||||
}
|
||||
if (ut_addr_v6[1] || ut_addr_v6[2] || ut_addr_v6[3]) {
|
||||
/* IPv6 */
|
||||
if (!inet_ntop(AF_INET6, &ut_addr_v6, buf_ipv6, sizeof(buf_ipv6))) {
|
||||
snprintf(buf_ipv6, INET6_ADDRSTRLEN, "?");
|
||||
}
|
||||
strncpy(buf, buf_ipv6, MAX_FROM_LEN);
|
||||
} else {
|
||||
/* IPv4 */
|
||||
if (!inet_ntop(AF_INET, &ut_addr_v6[0], buf, sizeof(buf))) {
|
||||
snprintf(buf, MAX_FROM_LEN, "?");
|
||||
}
|
||||
}
|
||||
buf[MAX_FROM_LEN] = 0;
|
||||
for (len = strlen(buf); len < MAX_FROM_LEN; len++) buf[len]=' ';
|
||||
buf[MAX_FROM_LEN] = 0;
|
||||
fputs(buf, stdout);
|
||||
} else {
|
||||
print_host(u->ut_host, sizeof u->ut_host);
|
||||
}
|
||||
}
|
||||
|
||||
/***** compact 7 char format for time intervals (belongs in libproc?) */
|
||||
@ -169,7 +208,7 @@ static const proc_t *getproc(const utmp_t *restrict const u, const char *restric
|
||||
|
||||
|
||||
/***** showinfo */
|
||||
static void showinfo(utmp_t *u, int formtype, int maxcmd, int from) {
|
||||
static void showinfo(utmp_t *u, int formtype, int maxcmd, int from, int ip_addresses) {
|
||||
unsigned long long jcpu;
|
||||
int ut_pid_found;
|
||||
unsigned i;
|
||||
@ -196,7 +235,7 @@ static void showinfo(utmp_t *u, int formtype, int maxcmd, int from) {
|
||||
if (formtype) {
|
||||
printf("%-9.8s%-9.8s", uname, u->ut_line);
|
||||
if (from)
|
||||
print_host(u->ut_host, sizeof u->ut_host);
|
||||
print_from(u, ip_addresses);
|
||||
print_logintime(u->ut_time, stdout);
|
||||
if (*u->ut_line == ':') /* idle unknown for xdm logins */
|
||||
printf(" ?xdm? ");
|
||||
@ -211,7 +250,7 @@ static void showinfo(utmp_t *u, int formtype, int maxcmd, int from) {
|
||||
} else {
|
||||
printf("%-9.8s%-9.8s", u->ut_user, u->ut_line);
|
||||
if (from)
|
||||
print_host(u->ut_host, sizeof u->ut_host);
|
||||
print_from(u, ip_addresses);
|
||||
if (*u->ut_line == ':') /* idle unknown for xdm logins */
|
||||
printf(" ?xdm? ");
|
||||
else
|
||||
@ -233,14 +272,22 @@ int main(int argc, char **argv) {
|
||||
char *user = NULL;
|
||||
utmp_t *u;
|
||||
struct winsize win;
|
||||
int header=1, longform=1, from=1, args, maxcmd=80, ch;
|
||||
int args;
|
||||
int maxcmd = 80;
|
||||
int ch;
|
||||
|
||||
/* defaults */
|
||||
int header = 1;
|
||||
int longform = 1;
|
||||
int from = 1;
|
||||
int ip_addresses = 0;
|
||||
|
||||
#ifndef W_SHOWFROM
|
||||
from = 0;
|
||||
#endif
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
for (args=0; (ch = getopt(argc, argv, "hlusfV")) != EOF; args++)
|
||||
for (args=0; (ch = getopt(argc, argv, "hlusfnV")) != EOF; args++)
|
||||
switch (ch) {
|
||||
case 'h': header = 0; break;
|
||||
case 'l': longform = 1; break;
|
||||
@ -248,6 +295,7 @@ int main(int argc, char **argv) {
|
||||
case 'f': from = !from; break;
|
||||
case 'V': display_version(); exit(0);
|
||||
case 'u': ignoreuser = 1; break;
|
||||
case 'n': ip_addresses = 1; break;
|
||||
default:
|
||||
printf("usage: w -hlsufV [user]\n"
|
||||
" -h skip header\n"
|
||||
@ -255,6 +303,7 @@ int main(int argc, char **argv) {
|
||||
" -s short listing\n"
|
||||
" -u ignore uid of processes\n"
|
||||
" -f toggle FROM field (default %s)\n"
|
||||
" -n use IP addresses instead of hostname\n"
|
||||
" -V display version\n", FROM_STRING);
|
||||
exit(1);
|
||||
}
|
||||
@ -292,14 +341,14 @@ int main(int argc, char **argv) {
|
||||
u = getutent();
|
||||
if (unlikely(!u)) break;
|
||||
if (u->ut_type != USER_PROCESS) continue;
|
||||
if (!strncmp(u->ut_user, user, USERSZ)) showinfo(u, longform, maxcmd, from);
|
||||
if (!strncmp(u->ut_user, user, USERSZ)) showinfo(u, longform, maxcmd, from, ip_addresses);
|
||||
}
|
||||
} else {
|
||||
for (;;) {
|
||||
u = getutent();
|
||||
if (unlikely(!u)) break;
|
||||
if (u->ut_type != USER_PROCESS) continue;
|
||||
if (*u->ut_user) showinfo(u, longform, maxcmd, from);
|
||||
if (*u->ut_user) showinfo(u, longform, maxcmd, from, ip_addresses);
|
||||
}
|
||||
}
|
||||
endutent();
|
||||
|
Loading…
Reference in New Issue
Block a user