]> granicus.if.org Git - procps-ng/commitdiff
library: set stage for NUMA node field display support
authorJim Warner <james.warner@comcast.net>
Sat, 13 May 2017 05:02:00 +0000 (00:02 -0500)
committerCraig Small <csmall@enc.com.au>
Mon, 22 May 2017 11:34:32 +0000 (21:34 +1000)
In response to that suggestion referenced below, these
changes allow display of task/thread level NUMA nodes.

Currently, only the 'top' program offers any NUMA type
support and it is limited to the Summary Area display.
With this commit both the 'top' and 'ps' programs will
be able to display NUMA nodes associated with threads.

[ this patch has been adapted from the newlib branch ]
[ and implemented so as to preserve the existing ABI ]

Reference(s):
https://gitlab.com/procps-ng/procps/issues/58

Signed-off-by: Jim Warner <james.warner@comcast.net>
Makefile.am
proc/libprocps.sym
proc/numa.c [new file with mode: 0644]
proc/numa.h [new file with mode: 0644]

index 9f052c0ed2c56a5b532bc83dc93eccec9f9e0fd3..bf77c4dff4bc0fb85df9cbd3caf4c0946002e890 100644 (file)
@@ -168,6 +168,8 @@ proc_libprocps_la_SOURCES = \
        proc/devname.h \
        proc/escape.c \
        proc/escape.h \
+       proc/numa.c \
+       proc/numa.h \
        proc/procps-private.h \
        proc/procps.h \
        proc/pwcache.c \
@@ -192,6 +194,7 @@ proc_libprocps_la_include_HEADERS = \
        proc/alloc.h \
        proc/devname.h \
        proc/escape.h \
+       proc/numa.h \
        proc/procps.h \
        proc/pwcache.h \
        proc/readproc.h \
index 7e0a1001fa7e0c30f951ce188cccba3eb654cdd5..1996dc5a03b9131d7dabc49c06ac5b406622fd09 100644 (file)
@@ -39,6 +39,10 @@ global:
        look_up_our_self;
        lookup_wchan;
        meminfo;
+       numa_init;
+       numa_max_node;
+       numa_node_of_cpu;
+       numa_uninit;
        openproc;
        page_bytes;
        pretty_print_signals;
diff --git a/proc/numa.c b/proc/numa.c
new file mode 100644 (file)
index 0000000..10a3452
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * NUMA node support for <PIDS> & <STAT> interfaces
+ * Copyright 2017 by James C. Warmer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef NUMA_DISABLE
+#include <dlfcn.h>
+#endif
+#include <stdlib.h>
+
+#include "numa.h"
+
+/*
+ * We're structured so that if numa_init() is NOT called or that ./configure |
+ * --disable-numa WAS specified, then calls to both of our primary functions |
+ * of numa_max_node() plus numa_node_of_cpu() would always return a negative |
+ * 1 which signifies that NUMA information isn't available. That ./configure |
+ * option might be required when libdl.so (necessary for dlopen) is missing. |
+ */
+
+
+/* ------------------------------------------------------------------------- +
+   a strictly development #define, existing specifically for the top program |
+   ( and it has no affect if ./configure --disable-numa has been specified ) | */
+//#define PRETEND_NUMA     // pretend there are 3 'discontiguous' numa nodes |
+// ------------------------------------------------------------------------- +
+
+
+static int null_max_node (void) { return -1; }
+static int null_node_of_cpu (int n) { (void)n; return -1; }
+
+
+#ifndef NUMA_DISABLE
+ #ifdef PRETEND_NUMA
+static int fake_max_node (void) { return 3; }
+static int fake_node_of_cpu (int n) { return (1 == (n % 4)) ? 0 : (n % 4); }
+ #endif
+#endif
+
+
+#ifndef NUMA_DISABLE
+static void *libnuma_handle;
+#endif
+int (*numa_max_node) (void)   = null_max_node;
+int (*numa_node_of_cpu) (int) = null_node_of_cpu;
+
+
+void numa_init (void) {
+    static int initialized;
+
+    if (initialized)
+        return;
+
+#ifndef NUMA_DISABLE
+ #ifndef PRETEND_NUMA
+    // we'll try for the most recent version, then a version we know works...
+    if ((libnuma_handle = dlopen("libnuma.so", RTLD_LAZY))
+    || (libnuma_handle = dlopen("libnuma.so.1", RTLD_LAZY))) {
+        numa_max_node = dlsym(libnuma_handle, "numa_max_node");
+        numa_node_of_cpu = dlsym(libnuma_handle, "numa_node_of_cpu");
+        if (numa_max_node == NULL
+        || (numa_node_of_cpu == NULL)) {
+            // this dlclose is safe - we've yet to call numa_node_of_cpu
+            // ( there's one other dlclose which has now been disabled )
+            dlclose(libnuma_handle);
+            libnuma_handle = NULL;
+            numa_max_node = null_max_node;
+            numa_node_of_cpu = null_node_of_cpu;
+        }
+    }
+ #else
+    libnuma_handle = (void *)-1;
+    numa_max_node = fake_max_node;
+    numa_node_of_cpu = fake_node_of_cpu;
+ #endif
+#endif
+    initialized = 1;
+} // end: numa_init
+
+
+void numa_uninit (void) {
+#ifndef PRETEND_NUMA
+    /* note: we'll skip a dlcose() to avoid the following libnuma memory
+     *       leak which is triggered after a call to numa_node_of_cpu():
+     *         ==1234== LEAK SUMMARY:
+     *         ==1234==    definitely lost: 512 bytes in 1 blocks
+     *         ==1234==    indirectly lost: 48 bytes in 2 blocks
+     *         ==1234==    ...
+     * [ thanks very much libnuma for all the pains you have caused us ]
+     */
+//  if (libnuma_handle)
+//      dlclose(libnuma_handle);
+#endif
+} // end: numa_uninit
+
+
+#if defined(PRETEND_NUMA) && defined(NUMA_DISABLE)
+# warning 'PRETEND_NUMA' ignored, 'NUMA_DISABLE' is active
+#endif
diff --git a/proc/numa.h b/proc/numa.h
new file mode 100644 (file)
index 0000000..c198d9d
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * NUMA node support for <PIDS> & <STAT> interfaces
+ * Copyright 2017 by James C. Warmer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef PROCPS_NUMA_H
+#define PROCPS_NUMA_H
+
+#include <features.h>
+
+__BEGIN_DECLS
+
+void numa_init (void);
+void numa_uninit (void);
+
+extern int (*numa_max_node) (void);
+extern int (*numa_node_of_cpu) (int);
+
+__END_DECLS
+
+#endif