top: introduce a plug-in approach for the NUMA support
The NUMA/Nodes support in top has gone through several
evolutions (primarily dealing with build-sys options).
With this commit the library dependency issues are now
moot and the responsibilities for run-time loading and
dynamic linking are assumed by the top program itself.
Henceforth, if top is executed in an environment where
libnuma.so is present, top will offer such extensions.
Even more importantly, when a missing libnuma is later
installed, top will offer numa support auto-magically.
All NUMA/Node build-sys dependencies are thus removed.
The former NUMA_ENABLED define has become NUMA_DISABLE
should anyone wish to test user interface implications
in an environment that *does* have libnuma. It is also
represented as the ./configure option: --disable-numa.
Lastly, the 't' (View_STATES) toggle will be forced on
for sanity whenever the '1', '2' or '3' keys are used.
Reference(s):
. original idea from: Dr. Fink <werner@suse.de>
http://www.freelists.org/post/procps/top-NUMA-node-CPU-utilization-support,18
. original numa suppoort
commit 8d989c68c0
Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
parent
5686877cd4
commit
edba932a7e
87
top/top.c
87
top/top.c
@ -26,6 +26,9 @@
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <curses.h>
|
#include <curses.h>
|
||||||
|
#ifndef NUMA_DISABLE
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
@ -57,14 +60,6 @@
|
|||||||
#include "top.h"
|
#include "top.h"
|
||||||
#include "top_nls.h"
|
#include "top_nls.h"
|
||||||
|
|
||||||
#ifdef NUMA_ENABLED
|
|
||||||
#ifdef PRETEND_NUMA
|
|
||||||
static int numa_max_node(void) { return 2; }
|
|
||||||
static int numa_node_of_cpu(int num) { return (num % 3); }
|
|
||||||
#else
|
|
||||||
#include <numa.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*###### Miscellaneous global stuff ####################################*/
|
/*###### Miscellaneous global stuff ####################################*/
|
||||||
|
|
||||||
@ -219,9 +214,20 @@ static int Autox_array [P_MAXPFLGS],
|
|||||||
static char Scaled_sfxtab[] = { 'k', 'm', 'g', 't', 'p', 'e', 0 };
|
static char Scaled_sfxtab[] = { 'k', 'm', 'g', 't', 'p', 'e', 0 };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Support for NUMA Node display & expansion (targeting) */
|
/* Support for NUMA Node display, node expansion/targeting and
|
||||||
|
run-time dynamic linking with libnuma.so treated as a plugin */
|
||||||
static int Numa_node_tot;
|
static int Numa_node_tot;
|
||||||
static int Numa_node_sel = -1;
|
static int Numa_node_sel = -1;
|
||||||
|
#ifndef NUMA_DISABLE
|
||||||
|
static void *Libnuma_handle;
|
||||||
|
#if defined(PRETEND_NUMA) || defined(PRETEND8CPUS)
|
||||||
|
static int Numa_max_node(void) { return 3; }
|
||||||
|
static int Numa_node_of_cpu(int num) { return (num % 4); }
|
||||||
|
#else
|
||||||
|
static int (*Numa_max_node)(void);
|
||||||
|
static int (*Numa_node_of_cpu)(int num);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*###### Sort callbacks ################################################*/
|
/*###### Sort callbacks ################################################*/
|
||||||
|
|
||||||
@ -513,6 +519,9 @@ static void bye_bye (const char *str) {
|
|||||||
#endif // end: ATEOJ_RPTHSH
|
#endif // end: ATEOJ_RPTHSH
|
||||||
#endif // end: OFF_HST_HASH
|
#endif // end: OFF_HST_HASH
|
||||||
|
|
||||||
|
#ifndef NUMA_DISABLE
|
||||||
|
if (Libnuma_handle) dlclose(Libnuma_handle);
|
||||||
|
#endif
|
||||||
if (str) {
|
if (str) {
|
||||||
fputs(str, stderr);
|
fputs(str, stderr);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -2288,19 +2297,15 @@ static void zap_fieldstab (void) {
|
|||||||
* cpus[sumSLOT] == tics from the 1st /proc/stat line
|
* cpus[sumSLOT] == tics from the 1st /proc/stat line
|
||||||
* [ and beyond sumSLOT == tics for each cpu NUMA node ] */
|
* [ and beyond sumSLOT == tics for each cpu NUMA node ] */
|
||||||
static CPU_t *cpus_refresh (CPU_t *cpus) {
|
static CPU_t *cpus_refresh (CPU_t *cpus) {
|
||||||
|
#define sumSLOT ( smp_num_cpus )
|
||||||
|
#define totSLOT ( 1 + smp_num_cpus + Numa_node_tot)
|
||||||
static FILE *fp = NULL;
|
static FILE *fp = NULL;
|
||||||
static int siz, sav_slot = -1;
|
static int siz, sav_slot = -1;
|
||||||
static char *buf;
|
static char *buf;
|
||||||
#ifdef NUMA_ENABLED
|
int i, num, tot_read;
|
||||||
#define sumSLOT ( smp_num_cpus )
|
#ifndef NUMA_DISABLE
|
||||||
#define totSLOT ( 1 + smp_num_cpus + Numa_node_tot)
|
int node;
|
||||||
int i, node;
|
|
||||||
#else
|
|
||||||
#define sumSLOT ( Cpu_faux_tot )
|
|
||||||
#define totSLOT ( 1 + Cpu_faux_tot )
|
|
||||||
int i;
|
|
||||||
#endif
|
#endif
|
||||||
int num, tot_read;
|
|
||||||
char *bp;
|
char *bp;
|
||||||
|
|
||||||
/*** hotplug_acclimated ***/
|
/*** hotplug_acclimated ***/
|
||||||
@ -2359,7 +2364,7 @@ static CPU_t *cpus_refresh (CPU_t *cpus) {
|
|||||||
((cpus[sumSLOT].cur.tot - cpus[sumSLOT].sav.tot) / smp_num_cpus) / (100 / TICS_EDGE);
|
((cpus[sumSLOT].cur.tot - cpus[sumSLOT].sav.tot) / smp_num_cpus) / (100 / TICS_EDGE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NUMA_ENABLED
|
#ifndef NUMA_DISABLE
|
||||||
for (i = 0; i < Numa_node_tot; i++) {
|
for (i = 0; i < Numa_node_tot; i++) {
|
||||||
node = sumSLOT + 1 + i;
|
node = sumSLOT + 1 + i;
|
||||||
// remember from last time around
|
// remember from last time around
|
||||||
@ -2375,11 +2380,7 @@ static CPU_t *cpus_refresh (CPU_t *cpus) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// now value each separate cpu's tics...
|
// now value each separate cpu's tics...
|
||||||
#ifdef NUMA_ENABLED
|
|
||||||
for (i = 0; i < sumSLOT; i++) {
|
for (i = 0; i < sumSLOT; i++) {
|
||||||
#else
|
|
||||||
for (i = 0; i < sumSLOT && i < Screen_rows; i++) {
|
|
||||||
#endif
|
|
||||||
#ifdef PRETEND8CPUS
|
#ifdef PRETEND8CPUS
|
||||||
bp = buf;
|
bp = buf;
|
||||||
#endif
|
#endif
|
||||||
@ -2402,8 +2403,9 @@ static CPU_t *cpus_refresh (CPU_t *cpus) {
|
|||||||
#ifdef PRETEND8CPUS
|
#ifdef PRETEND8CPUS
|
||||||
cpus[i].id = i;
|
cpus[i].id = i;
|
||||||
#endif
|
#endif
|
||||||
#ifdef NUMA_ENABLED
|
#ifndef NUMA_DISABLE
|
||||||
if (-1 < (node = numa_node_of_cpu(cpus[i].id))) {
|
if (Numa_node_tot
|
||||||
|
&& -1 < (node = Numa_node_of_cpu(cpus[i].id))) {
|
||||||
node += (sumSLOT + 1);
|
node += (sumSLOT + 1);
|
||||||
cpus[node].cur.u += cpus[i].cur.u;
|
cpus[node].cur.u += cpus[i].cur.u;
|
||||||
cpus[node].cur.n += cpus[i].cur.n;
|
cpus[node].cur.n += cpus[i].cur.n;
|
||||||
@ -2652,8 +2654,9 @@ static void sysinfo_refresh (int forced) {
|
|||||||
cpuinfo();
|
cpuinfo();
|
||||||
Cpu_faux_tot = smp_num_cpus;
|
Cpu_faux_tot = smp_num_cpus;
|
||||||
cpu_secs = cur_secs;
|
cpu_secs = cur_secs;
|
||||||
#ifdef NUMA_ENABLED
|
#ifndef NUMA_DISABLE
|
||||||
Numa_node_tot = numa_max_node() + 1;
|
if (Libnuma_handle)
|
||||||
|
Numa_node_tot = Numa_max_node() + 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -3241,8 +3244,22 @@ static void before (char *me) {
|
|||||||
memcpy(HHash_two, HHash_nul, sizeof(HHash_nul));
|
memcpy(HHash_two, HHash_nul, sizeof(HHash_nul));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NUMA_ENABLED
|
#ifndef NUMA_DISABLE
|
||||||
Numa_node_tot = numa_max_node() + 1;
|
#if defined(PRETEND_NUMA) || defined(PRETEND8CPUS)
|
||||||
|
Numa_node_tot = Numa_max_node() + 1;
|
||||||
|
#else
|
||||||
|
Libnuma_handle = dlopen("libnuma.so", RTLD_LAZY);
|
||||||
|
if (Libnuma_handle) {
|
||||||
|
Numa_max_node = dlsym(Libnuma_handle, "numa_max_node");
|
||||||
|
Numa_node_of_cpu = dlsym(Libnuma_handle, "numa_node_of_cpu");
|
||||||
|
if (Numa_max_node && Numa_node_of_cpu)
|
||||||
|
Numa_node_tot = Numa_max_node() + 1;
|
||||||
|
else {
|
||||||
|
dlclose(Libnuma_handle);
|
||||||
|
Libnuma_handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SIGRTMAX // not available on hurd, maybe others too
|
#ifndef SIGRTMAX // not available on hurd, maybe others too
|
||||||
@ -4387,7 +4404,7 @@ static void keys_summary (int ch) {
|
|||||||
if (CHKw(w, View_CPUNOD)) OFFw(w, View_CPUSUM);
|
if (CHKw(w, View_CPUNOD)) OFFw(w, View_CPUSUM);
|
||||||
else TOGw(w, View_CPUSUM);
|
else TOGw(w, View_CPUSUM);
|
||||||
OFFw(w, View_CPUNOD);
|
OFFw(w, View_CPUNOD);
|
||||||
Numa_node_sel = -1;
|
SETw(w, View_STATES);
|
||||||
break;
|
break;
|
||||||
case '2':
|
case '2':
|
||||||
if (!Numa_node_tot)
|
if (!Numa_node_tot)
|
||||||
@ -4395,6 +4412,7 @@ static void keys_summary (int ch) {
|
|||||||
else {
|
else {
|
||||||
if (Numa_node_sel < 0) TOGw(w, View_CPUNOD);
|
if (Numa_node_sel < 0) TOGw(w, View_CPUNOD);
|
||||||
if (!CHKw(w, View_CPUNOD)) SETw(w, View_CPUSUM);
|
if (!CHKw(w, View_CPUNOD)) SETw(w, View_CPUSUM);
|
||||||
|
SETw(w, View_STATES);
|
||||||
Numa_node_sel = -1;
|
Numa_node_sel = -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -4406,7 +4424,7 @@ static void keys_summary (int ch) {
|
|||||||
if (GET_INTNONE < num) {
|
if (GET_INTNONE < num) {
|
||||||
if (num >= 0 && num < Numa_node_tot) {
|
if (num >= 0 && num < Numa_node_tot) {
|
||||||
Numa_node_sel = num;
|
Numa_node_sel = num;
|
||||||
SETw(w, View_CPUNOD);
|
SETw(w, View_CPUNOD | View_STATES);
|
||||||
OFFw(w, View_CPUSUM);
|
OFFw(w, View_CPUSUM);
|
||||||
} else
|
} else
|
||||||
show_msg(N_txt(NUMA_nodebad_txt));
|
show_msg(N_txt(NUMA_nodebad_txt));
|
||||||
@ -4998,7 +5016,9 @@ static void summary_show (void) {
|
|||||||
|
|
||||||
smpcpu = cpus_refresh(smpcpu);
|
smpcpu = cpus_refresh(smpcpu);
|
||||||
|
|
||||||
#ifdef NUMA_ENABLED
|
#ifndef NUMA_DISABLE
|
||||||
|
if (!Numa_node_tot) goto numa_nope;
|
||||||
|
|
||||||
if (CHKw(w, View_CPUNOD)) {
|
if (CHKw(w, View_CPUNOD)) {
|
||||||
if (Numa_node_sel < 0) {
|
if (Numa_node_sel < 0) {
|
||||||
// display the 1st /proc/stat line, then the nodes (if room)
|
// display the 1st /proc/stat line, then the nodes (if room)
|
||||||
@ -5017,7 +5037,7 @@ static void summary_show (void) {
|
|||||||
summary_hlp(&smpcpu[1 + smp_num_cpus + Numa_node_sel], tmp);
|
summary_hlp(&smpcpu[1 + smp_num_cpus + Numa_node_sel], tmp);
|
||||||
Msg_row += 1;
|
Msg_row += 1;
|
||||||
for (i = 0; i < Cpu_faux_tot; i++) {
|
for (i = 0; i < Cpu_faux_tot; i++) {
|
||||||
if (Numa_node_sel == numa_node_of_cpu(smpcpu[i].id)) {
|
if (Numa_node_sel == Numa_node_of_cpu(smpcpu[i].id)) {
|
||||||
if (!isROOM(anyFLG, 1)) break;
|
if (!isROOM(anyFLG, 1)) break;
|
||||||
snprintf(tmp, sizeof(tmp), N_fmt(WORD_eachcpu_fmt), smpcpu[i].id);
|
snprintf(tmp, sizeof(tmp), N_fmt(WORD_eachcpu_fmt), smpcpu[i].id);
|
||||||
summary_hlp(&smpcpu[i], tmp);
|
summary_hlp(&smpcpu[i], tmp);
|
||||||
@ -5026,6 +5046,7 @@ static void summary_show (void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
numa_nope:
|
||||||
#endif
|
#endif
|
||||||
if (CHKw(w, View_CPUSUM)) {
|
if (CHKw(w, View_CPUSUM)) {
|
||||||
// display just the 1st /proc/stat line
|
// display just the 1st /proc/stat line
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include "../proc/readproc.h"
|
#include "../proc/readproc.h"
|
||||||
|
|
||||||
/* Defines represented in configure.ac ----------------------------- */
|
/* Defines represented in configure.ac ----------------------------- */
|
||||||
//#define NUMA_ENABLED /* enable summary area NUMA/Node extension */
|
//#define NUMA_DISABLE /* disable summary area NUMA/Nodes display */
|
||||||
//#define OOMEM_ENABLE /* enable the SuSE out-of-memory additions */
|
//#define OOMEM_ENABLE /* enable the SuSE out-of-memory additions */
|
||||||
//#define SIGNALS_LESS /* favor reduced signal load over response */
|
//#define SIGNALS_LESS /* favor reduced signal load over response */
|
||||||
|
|
||||||
@ -619,8 +619,8 @@ typedef struct WIN_t {
|
|||||||
#if defined(RECALL_FIXED) && defined(TERMIOS_ONLY)
|
#if defined(RECALL_FIXED) && defined(TERMIOS_ONLY)
|
||||||
# error 'RECALL_FIXED' conflicts with 'TERMIOS_ONLY'
|
# error 'RECALL_FIXED' conflicts with 'TERMIOS_ONLY'
|
||||||
#endif
|
#endif
|
||||||
#if defined(PRETEND_NUMA) && !defined(NUMA_ENABLED)
|
#if defined(PRETEND_NUMA) && defined(NUMA_DISABLE)
|
||||||
# error 'PRETEND_NUMA' also requires 'NUMA_ENABLED'
|
# error 'PRETEND_NUMA' confilcts with 'NUMA_DISABLE'
|
||||||
#endif
|
#endif
|
||||||
#if (LRGBUFSIZ < SCREENMAX)
|
#if (LRGBUFSIZ < SCREENMAX)
|
||||||
# error 'LRGBUFSIZ' must NOT be less than 'SCREENMAX'
|
# error 'LRGBUFSIZ' must NOT be less than 'SCREENMAX'
|
||||||
|
Loading…
Reference in New Issue
Block a user