]> granicus.if.org Git - procps-ng/commitdiff
top: introduce a plug-in approach for the NUMA support
authorJim Warner <james.warner@comcast.net>
Thu, 25 Apr 2013 05:00:00 +0000 (00:00 -0500)
committerCraig Small <csmall@enc.com.au>
Sat, 4 May 2013 23:12:08 +0000 (09:12 +1000)
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 8d989c68c068541a814bf0d2340ac9b0373f24b5

Signed-off-by: Jim Warner <james.warner@comcast.net>
top/top.c
top/top.h

index 422c622f05096cf5a7f26042762dc4cd0b86a15d..01ea383544dc884f2b457592af52199ef4b126bf 100644 (file)
--- a/top/top.c
+++ b/top/top.c
@@ -26,6 +26,9 @@
 
 #include <ctype.h>
 #include <curses.h>
+#ifndef NUMA_DISABLE
+#include <dlfcn.h>
+#endif
 #include <errno.h>
 #include <fcntl.h>
 #include <pwd.h>
 #include "top.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  ####################################*/
 
@@ -219,9 +214,20 @@ static int Autox_array [P_MAXPFLGS],
    static char Scaled_sfxtab[] =  { 'k', 'm', 'g', 't', 'p', 'e', 0 };
 #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_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
 \f
 /*######  Sort callbacks  ################################################*/
 
@@ -513,6 +519,9 @@ static void bye_bye (const char *str) {
 #endif // end: ATEOJ_RPTHSH
 #endif // end: OFF_HST_HASH
 
+#ifndef NUMA_DISABLE
+  if (Libnuma_handle) dlclose(Libnuma_handle);
+#endif
    if (str) {
       fputs(str, stderr);
       exit(EXIT_FAILURE);
@@ -2288,19 +2297,15 @@ static void zap_fieldstab (void) {
          *    cpus[sumSLOT]        == tics from the 1st /proc/stat line
          *  [ and beyond sumSLOT   == tics for each cpu NUMA node ] */
 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 int siz, sav_slot = -1;
    static char *buf;
-#ifdef NUMA_ENABLED
- #define sumSLOT ( smp_num_cpus )
- #define totSLOT ( 1 + smp_num_cpus + Numa_node_tot)
-   int i, node;
-#else
- #define sumSLOT ( Cpu_faux_tot )
- #define totSLOT ( 1 + Cpu_faux_tot )
-   int i;
+   int i, num, tot_read;
+#ifndef NUMA_DISABLE
+   int node;
 #endif
-   int num, tot_read;
    char *bp;
 
    /*** 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);
 #endif
 
-#ifdef NUMA_ENABLED
+#ifndef NUMA_DISABLE
    for (i = 0; i < Numa_node_tot; i++) {
       node = sumSLOT + 1 + i;
       // remember from last time around
@@ -2375,11 +2380,7 @@ static CPU_t *cpus_refresh (CPU_t *cpus) {
 #endif
 
    // now value each separate cpu's tics...
-#ifdef NUMA_ENABLED
    for (i = 0; i < sumSLOT; i++) {
-#else
-   for (i = 0; i < sumSLOT && i < Screen_rows; i++) {
-#endif
 #ifdef PRETEND8CPUS
       bp = buf;
 #endif
@@ -2402,8 +2403,9 @@ static CPU_t *cpus_refresh (CPU_t *cpus) {
 #ifdef PRETEND8CPUS
       cpus[i].id = i;
 #endif
-#ifdef NUMA_ENABLED
-      if (-1 < (node = numa_node_of_cpu(cpus[i].id))) {
+#ifndef NUMA_DISABLE
+      if (Numa_node_tot
+      && -1 < (node = Numa_node_of_cpu(cpus[i].id))) {
          node += (sumSLOT + 1);
          cpus[node].cur.u += cpus[i].cur.u;
          cpus[node].cur.n += cpus[i].cur.n;
@@ -2652,8 +2654,9 @@ static void sysinfo_refresh (int forced) {
       cpuinfo();
       Cpu_faux_tot = smp_num_cpus;
       cpu_secs = cur_secs;
-#ifdef NUMA_ENABLED
-      Numa_node_tot = numa_max_node() + 1;
+#ifndef NUMA_DISABLE
+      if (Libnuma_handle)
+         Numa_node_tot = Numa_max_node() + 1;
 #endif
    }
 #endif
@@ -3241,8 +3244,22 @@ static void before (char *me) {
    memcpy(HHash_two, HHash_nul, sizeof(HHash_nul));
 #endif
 
-#ifdef NUMA_ENABLED
-   Numa_node_tot = numa_max_node() + 1;
+#ifndef NUMA_DISABLE
+#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
 
 #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);
          else TOGw(w, View_CPUSUM);
          OFFw(w, View_CPUNOD);
-         Numa_node_sel = -1;
+         SETw(w, View_STATES);
          break;
       case '2':
          if (!Numa_node_tot)
@@ -4395,6 +4412,7 @@ static void keys_summary (int ch) {
          else {
             if (Numa_node_sel < 0) TOGw(w, View_CPUNOD);
             if (!CHKw(w, View_CPUNOD)) SETw(w, View_CPUSUM);
+            SETw(w, View_STATES);
             Numa_node_sel = -1;
          }
          break;
@@ -4406,7 +4424,7 @@ static void keys_summary (int ch) {
             if (GET_INTNONE < num) {
                if (num >= 0 && num < Numa_node_tot) {
                   Numa_node_sel = num;
-                  SETw(w, View_CPUNOD);
+                  SETw(w, View_CPUNOD | View_STATES);
                   OFFw(w, View_CPUSUM);
                } else
                   show_msg(N_txt(NUMA_nodebad_txt));
@@ -4998,7 +5016,9 @@ static void summary_show (void) {
 
       smpcpu = cpus_refresh(smpcpu);
 
-#ifdef NUMA_ENABLED
+#ifndef NUMA_DISABLE
+      if (!Numa_node_tot) goto numa_nope;
+
       if (CHKw(w, View_CPUNOD)) {
          if (Numa_node_sel < 0) {
             // 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);
             Msg_row += 1;
             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;
                   snprintf(tmp, sizeof(tmp), N_fmt(WORD_eachcpu_fmt), smpcpu[i].id);
                   summary_hlp(&smpcpu[i], tmp);
@@ -5026,6 +5046,7 @@ static void summary_show (void) {
             }
          }
       } else
+numa_nope:
 #endif
       if (CHKw(w, View_CPUSUM)) {
          // display just the 1st /proc/stat line
index ace057853f90b3bb3be01936f709e560d5f98949..7c595348212719cd62e7d9ef5a3092066280dabb 100644 (file)
--- a/top/top.h
+++ b/top/top.h
@@ -23,7 +23,7 @@
 #include "../proc/readproc.h"
 
         /* 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 SIGNALS_LESS            /* favor reduced signal load over response */
 
@@ -619,8 +619,8 @@ typedef struct WIN_t {
 #if defined(RECALL_FIXED) && defined(TERMIOS_ONLY)
 # error 'RECALL_FIXED' conflicts with 'TERMIOS_ONLY'
 #endif
-#if defined(PRETEND_NUMA) && !defined(NUMA_ENABLED)
-# error 'PRETEND_NUMA' also requires 'NUMA_ENABLED'
+#if defined(PRETEND_NUMA) && defined(NUMA_DISABLE)
+# error 'PRETEND_NUMA' confilcts with 'NUMA_DISABLE'
 #endif
 #if (LRGBUFSIZ < SCREENMAX)
 # error 'LRGBUFSIZ' must NOT be less than 'SCREENMAX'