]> granicus.if.org Git - procps-ng/commitdiff
library: slab is redesigned to use 'stack' vs. 'chain'
authorJim Warner <james.warner@comcast.net>
Tue, 21 Jul 2015 05:00:00 +0000 (00:00 -0500)
committerCraig Small <csmall@enc.com.au>
Thu, 23 Jul 2015 12:31:32 +0000 (22:31 +1000)
In addition to that text shown below the line which is
common to several commit messages, this patch contains
several minor changes with lessor impact upon the API:

. A 'read' was added to function procps_slabnode_count
(but only when necessary, i.e. info->nodes_used == 0).

. The #include header files are ordered alphabetically
now, with all those <sys/??> types separately grouped.

------------------------------------------------------
. The former 'chains' have now become 'stacks' without
the 'next' pointer in each result struct. The pointers
initially seemed to offer some flexibility with memory
allocations and benefits for the library access logic.
However, user access was always via displacement and a
a statically allocated chain was cumbersome to define.

. An enumerator ending in '_noop' will no longer serve
as a fencepost delimiter. Rather, it has become a much
more important and flexible user oriented tool. Adding
one or more such 'items' in any items list passed into
the library becomes the means of extending the 'stack'
to also include user (not just library) data. Any such
data is guaranteed to never be altered by the library.

. Anticipating PID support, where many different types
must be represented in a result structure, we'll adopt
a common naming standard. And, while not every results
structure currently needs to reflect disparate types a
union will be employed so the same dot qualifier ('.')
can be used consistently when accessing all such data.

Signed-off-by: Jim Warner <james.warner@comcast.net>
proc/libprocps.sym
proc/slab.c
proc/slab.h
slabtop.c
vmstat.c

index 16d0bcbdd2edceefc754ee3cb3383fd84d5a54ea..655e8eec017eefcdaf95205c5adcbee365e33971 100644 (file)
@@ -47,16 +47,16 @@ global:
        procps_slabinfo_ref;
        procps_slabinfo_unref;
        procps_slabs_get;
-       procps_slabs_getchain;
+       procps_slabs_getstack;
        procps_slabnode_count;
        procps_slabnode_getname;
        procps_slabnode_get;
-       procps_slabnode_getchain;
-       procps_slabnode_chain_fill;
-       procps_slabnode_chain_alloc;
-       procps_slabnode_chains_fill;
-       procps_slabnode_chains_sort;
-       procps_slabnode_chains_alloc;
+       procps_slabnode_getstack;
+       procps_slabnode_stack_fill;
+       procps_slabnode_stack_alloc;
+       procps_slabnode_stacks_fill;
+       procps_slabnode_stacks_sort;
+       procps_slabnode_stacks_alloc;
        procps_stat_new;
        procps_stat_read;
        procps_stat_read_jiffs;
index aae816450c446f2da87ad5ae079ea8fd24491c52..a400a469fa3faea510580427257753e5777b9e14 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <limits.h>
 #include <ctype.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
+#include <unistd.h>
+
 #include <sys/stat.h>
-#include <fcntl.h>
+#include <sys/types.h>
 
 #include <proc/slab.h>
 #include "procps-private.h"
 #define SLABINFO_LINE_LEN    2048
 #define SLAB_INFO_NAME_LEN   128
 
-struct slabinfo_node {
-    char name[SLAB_INFO_NAME_LEN];  /* name of this cache */
-    unsigned long cache_size;       /* size of entire cache */
-    unsigned nr_objs;               /* number of objects in this cache */
-    unsigned nr_active_objs;        /* number of active objects */
-    unsigned obj_size;              /* size of each object */
-    unsigned objs_per_slab;         /* number of objects per slab */
-    unsigned pages_per_slab;        /* number of pages per slab */
-    unsigned nr_slabs;              /* number of slabs in this cache */
-    unsigned nr_active_slabs;       /* number of active slabs */
-    unsigned use;                   /* percent full: total / active */
-};
-
 struct slabinfo_stats {
     unsigned long total_size;       /* size of all objects */
     unsigned long active_size;      /* size of all active objects */
-    unsigned nr_objs;               /* number of objects, among all caches */
-    unsigned nr_active_objs;        /* number of active objects, among all caches */
-    unsigned nr_pages;              /* number of pages consumed by all objects */
-    unsigned nr_slabs;              /* number of slabs, among all caches */
-    unsigned nr_active_slabs;       /* number of active slabs, among all caches */
-    unsigned nr_caches;             /* number of caches */
-    unsigned nr_active_caches;      /* number of active caches */
-    unsigned avg_obj_size;          /* average object size */
-    unsigned min_obj_size;          /* size of smallest object */
-    unsigned max_obj_size;          /* size of largest object */
+    unsigned int  nr_objs;          /* number of objects, among all caches */
+    unsigned int  nr_active_objs;   /* number of active objects, among all caches */
+    unsigned int  nr_pages;         /* number of pages consumed by all objects */
+    unsigned int  nr_slabs;         /* number of slabs, among all caches */
+    unsigned int  nr_active_slabs;  /* number of active slabs, among all caches */
+    unsigned int  nr_caches;        /* number of caches */
+    unsigned int  nr_active_caches; /* number of active caches */
+    unsigned int  avg_obj_size;     /* average object size */
+    unsigned int  min_obj_size;     /* size of smallest object */
+    unsigned int  max_obj_size;     /* size of largest object */
+};
+
+struct slabinfo_node {
+    char name[SLAB_INFO_NAME_LEN];  /* name of this cache */
+    unsigned long cache_size;       /* size of entire cache */
+    unsigned int  nr_objs;          /* number of objects in this cache */
+    unsigned int  nr_active_objs;   /* number of active objects */
+    unsigned int  obj_size;         /* size of each object */
+    unsigned int  objs_per_slab;    /* number of objects per slab */
+    unsigned int  pages_per_slab;   /* number of pages per slab */
+    unsigned int  nr_slabs;         /* number of slabs in this cache */
+    unsigned int  nr_active_slabs;  /* number of active slabs */
+    unsigned int  use;              /* percent full: total / active */
 };
 
 struct procps_slabinfo {
@@ -76,21 +77,21 @@ struct procps_slabinfo {
     struct slabinfo_node *nodes;    /* first slabnode of this list */
     int nodes_alloc;                /* nodes alloc()ed */
     int nodes_used;                 /* nodes using alloced memory */
-    struct chains_anchor *chained;
+    struct stacks_anchor *stacked;
 };
 
-struct chain_vectors {
-    struct chains_anchor *owner;
-    struct slabnode_chain **heads;
+struct stack_vectors {
+    struct stacks_anchor *owner;
+    struct slabnode_stack **heads;
 };
 
-struct chains_anchor {
+struct stacks_anchor {
     int depth;
     int inuse;
     int header_size;
-    struct chain_vectors *vectors;
-    struct chains_anchor *self;
-    struct chains_anchor *next;
+    struct stack_vectors *vectors;
+    struct stacks_anchor *self;
+    struct stacks_anchor *next;
 };
 
 
@@ -207,9 +208,9 @@ static int parse_slabinfo20 (
             return retval;
 
         if (sscanf(buffer,
-                   "%" STRINGIFY(SLAB_INFO_NAME_LEN)
-                   "s %d %d %d %d %d : tunables %*d %*d %*d : \
-                   slabdata %d %d %*d", node->name,
+                   "%" STRINGIFY(SLAB_INFO_NAME_LEN) "s" \
+                   "%u %u %u %u %u : tunables %*u %*u %*u : slabdata %u %u %*u",
+                   node->name,
                    &node->nr_active_objs, &node->nr_objs,
                    &node->obj_size, &node->objs_per_slab,
                    &node->pages_per_slab, &node->nr_active_slabs,
@@ -231,7 +232,7 @@ static int parse_slabinfo20 (
             * page_size;
 
         if (node->nr_objs) {
-            node->use = 100 * node->nr_active_objs / node->nr_objs;
+            node->use = (unsigned int)100 * node->nr_active_objs / node->nr_objs;
             stats->nr_active_caches++;
         } else
             node->use = 0;
@@ -283,7 +284,7 @@ PROCPS_EXPORT int procps_slabinfo_new (
 /* procps_slabinfo_read():
  *
  * Read the data out of /proc/slabinfo putting the information
- * into the supplie info container
+ * into the supplied info container
  *
  * Returns: 0 on success, negative on error
  */
@@ -329,6 +330,7 @@ PROCPS_EXPORT int procps_slabinfo_ref (
 {
     if (info == NULL)
         return -EINVAL;
+
     info->refcount++;
     return info->refcount;
 }
@@ -338,18 +340,19 @@ PROCPS_EXPORT int procps_slabinfo_unref (
 {
     if (info == NULL || *info == NULL)
         return -EINVAL;
+
     (*info)->refcount--;
     if ((*info)->refcount == 0) {
         if ((*info)->slabinfo_fp) {
             fclose((*info)->slabinfo_fp);
             (*info)->slabinfo_fp = NULL;
         }
-        if ((*info)->chained) {
+        if ((*info)->stacked) {
             do {
-                struct chains_anchor *p = (*info)->chained;
-                (*info)->chained = (*info)->chained->next;
+                struct stacks_anchor *p = (*info)->stacked;
+                (*info)->stacked = (*info)->stacked->next;
                 free(p);
-            } while((*info)->chained);
+            } while((*info)->stacked);
         }
         free((*info)->nodes);
         free(*info);
@@ -363,6 +366,9 @@ PROCPS_EXPORT unsigned long procps_slabs_get (
         struct procps_slabinfo *info,
         enum slabs_item item)
 {
+    /* note: most of the results we might return are actually just
+       unsigned int, but we must accommodate the largest potential
+       result and so return an unsigned long */
     if (info == NULL)
         return -EINVAL;
 
@@ -391,68 +397,66 @@ PROCPS_EXPORT unsigned long procps_slabs_get (
             return info->stats.total_size;
         case PROCPS_SLABS_SIZE_ACTIVE:
             return info->stats.active_size;
-        case PROCPS_SLABS_noop:
-            return 0;
         default:
-            return -EINVAL;
+            return 0;
     }
-    return 0;
 }
 
-PROCPS_EXPORT int procps_slabs_getchain (
+PROCPS_EXPORT int procps_slabs_getstack (
         struct procps_slabinfo *info,
-        struct slabs_result *these)
+        struct slab_result *these)
 {
     if (info == NULL || these == NULL)
         return -EINVAL;
 
-    do {
+    for (;;) {
         switch (these->item) {
             case PROCPS_SLABS_OBJS:
-                these->result = info->stats.nr_objs;
+                these->result.u_int = info->stats.nr_objs;
                 break;
             case PROCPS_SLABS_AOBJS:
-                these->result = info->stats.nr_active_objs;
+                these->result.u_int = info->stats.nr_active_objs;
                 break;
             case PROCPS_SLABS_PAGES:
-                these->result = info->stats.nr_pages;
+                these->result.u_int = info->stats.nr_pages;
                 break;
             case PROCPS_SLABS_SLABS:
-                these->result = info->stats.nr_slabs;
+                these->result.u_int = info->stats.nr_slabs;
                 break;
             case PROCPS_SLABS_ASLABS:
-                these->result = info->stats.nr_active_slabs;
+                these->result.u_int = info->stats.nr_active_slabs;
                 break;
             case PROCPS_SLABS_CACHES:
-                these->result = info->stats.nr_caches;
+                these->result.u_int = info->stats.nr_caches;
                 break;
             case PROCPS_SLABS_ACACHES:
-                these->result = info->stats.nr_active_caches;
+                these->result.u_int = info->stats.nr_active_caches;
                 break;
             case PROCPS_SLABS_SIZE_AVG:
-                these->result = info->stats.avg_obj_size;
+                these->result.u_int = info->stats.avg_obj_size;
                 break;
             case PROCPS_SLABS_SIZE_MIN:
-                these->result = info->stats.min_obj_size;
+                these->result.u_int = info->stats.min_obj_size;
                 break;
             case PROCPS_SLABS_SIZE_MAX:
-                these->result = info->stats.max_obj_size;
+                these->result.u_int = info->stats.max_obj_size;
                 break;
             case PROCPS_SLABS_SIZE_TOTAL:
-                these->result = info->stats.total_size;
+                these->result.ul_int = info->stats.total_size;
                 break;
             case PROCPS_SLABS_SIZE_ACTIVE:
-                these->result = info->stats.active_size;
+                these->result.ul_int = info->stats.active_size;
                 break;
             case PROCPS_SLABS_noop:
-                these->result = 0;
+                // don't disturb potential user data in the result struct
                 break;
+            case PROCPS_SLABS_stack_end:
+                return 0;
             default:
                 return -EINVAL;
         }
-        these = these->next;
-    } while(these);
-    return 0;
+        ++these;
+    }
 }
 
 /*
@@ -481,6 +485,9 @@ PROCPS_EXPORT unsigned long procps_slabnode_get (
         enum slabnode_item item,
         int nodeid)
 {
+    /* note: most of the results we might return are actually just
+       unsigned int, but we must accommodate the largest potential
+       result and so return an unsigned long */
     if (info == NULL)
         return -EINVAL;
 
@@ -503,18 +510,14 @@ PROCPS_EXPORT unsigned long procps_slabnode_get (
             return info->nodes[nodeid].nr_active_slabs;
         case PROCPS_SLABNODE_USE:
             return info->nodes[nodeid].use;
-        case PROCPS_SLABNODE_noop:
-            return 0;
-        //   PROCPS_SLABNODE_NAME also invalid in this context
         default:
-            return -EINVAL;
+            return 0;
     }
-    return 0;
 }
 
-PROCPS_EXPORT int procps_slabnode_getchain (
+PROCPS_EXPORT int procps_slabnode_getstack (
         struct procps_slabinfo *info,
-        struct slabnode_result *these,
+        struct slab_result *these,
         int nodeid)
 {
     if (info == NULL || these == NULL)
@@ -522,64 +525,65 @@ PROCPS_EXPORT int procps_slabnode_getchain (
     if (nodeid > info->nodes_used)
         return -EINVAL;
 
-    do {
+    for (;;) {
         switch (these->item) {
             case PROCPS_SLABNODE_SIZE:
-                these->result.num = info->nodes[nodeid].cache_size;
+                these->result.ul_int = info->nodes[nodeid].cache_size;
                 break;
             case PROCPS_SLABNODE_OBJS:
-                these->result.num = info->nodes[nodeid].nr_objs;
+                these->result.u_int = info->nodes[nodeid].nr_objs;
                 break;
             case PROCPS_SLABNODE_AOBJS:
-                these->result.num = info->nodes[nodeid].nr_active_objs;
+                these->result.u_int = info->nodes[nodeid].nr_active_objs;
                 break;
             case PROCPS_SLABNODE_OBJ_SIZE:
-                these->result.num = info->nodes[nodeid].obj_size;
+                these->result.u_int = info->nodes[nodeid].obj_size;
                 break;
             case PROCPS_SLABNODE_OBJS_PER_SLAB:
-                these->result.num = info->nodes[nodeid].objs_per_slab;
+                these->result.u_int = info->nodes[nodeid].objs_per_slab;
                 break;
             case PROCPS_SLABNODE_PAGES_PER_SLAB:
-                these->result.num = info->nodes[nodeid].pages_per_slab;
+                these->result.u_int = info->nodes[nodeid].pages_per_slab;
                 break;
             case PROCPS_SLABNODE_SLABS:
-                these->result.num = info->nodes[nodeid].nr_slabs;
+                these->result.u_int = info->nodes[nodeid].nr_slabs;
                 break;
             case PROCPS_SLABNODE_ASLABS:
-                these->result.num = info->nodes[nodeid].nr_active_slabs;
+                these->result.u_int = info->nodes[nodeid].nr_active_slabs;
                 break;
             case PROCPS_SLABNODE_USE:
-                these->result.num = info->nodes[nodeid].use;
+                these->result.u_int = info->nodes[nodeid].use;
                 break;
             case PROCPS_SLABNODE_NAME:
                 these->result.str = info->nodes[nodeid].name;
                 break;
             case PROCPS_SLABNODE_noop:
-                these->result.num = 0;
+                // don't disturb potential user data in the result struct
                 break;
+            case PROCPS_SLABNODE_stack_end:
+                return 0;
             default:
                 return -EINVAL;
         }
-        these = these->next;
-    } while(these);
-    return 0;
+        ++these;
+    }
 }
 
 
-PROCPS_EXPORT int procps_slabnode_chain_fill (
+PROCPS_EXPORT int procps_slabnode_stack_fill (
     struct procps_slabinfo *info,
-    struct slabnode_chain *chain,
+    struct slabnode_stack *stack,
     int nodeid)
 {
     int rc;
 
-    if (info == NULL || chain == NULL || chain->head == NULL)
+    if (info == NULL || stack == NULL || stack->head == NULL)
         return -EINVAL;
 
     if ((rc = procps_slabinfo_read(info)) < 0)
         return rc;
 
-    return procps_slabnode_getchain(info, chain->head, nodeid);
+    return procps_slabnode_getstack(info, stack->head, nodeid);
 }
 
 /*
@@ -590,245 +594,276 @@ PROCPS_EXPORT int procps_slabnode_chain_fill (
  * Returns: number of nodes in @info or <0 on error
  */
 PROCPS_EXPORT int procps_slabnode_count (
-        const struct procps_slabinfo *info)
+        struct procps_slabinfo *info)
 {
+    int rc = 0;
+
     if (!info)
         return -EINVAL;
+    if (!info->nodes_used)
+        rc = procps_slabinfo_read(info);
+    if (rc < 0)
+        return rc;
     return info->nodes_used;
 }
 
-PROCPS_EXPORT int procps_slabnode_chains_fill (
+PROCPS_EXPORT int procps_slabnode_stacks_fill (
     struct procps_slabinfo *info,
-    struct slabnode_chain **chains,
-    int maxchains)
+    struct slabnode_stack **stacks,
+    int maxstacks)
 {
     int i, rc;
 
-    if (info == NULL || *chains == NULL)
+    if (info == NULL || *stacks == NULL)
         return -EINVAL;
-    if (maxchains < 1)
+    if (maxstacks < 1)
         return -EINVAL;
 
     if ((rc = procps_slabinfo_read(info)) < 0)
         return rc;
 
-    if (maxchains > info->chained->depth)
-        maxchains = info->chained->depth;
-    if (maxchains > info->nodes_used)
-        maxchains = info->nodes_used;
+    if (maxstacks > info->stacked->depth)
+        maxstacks = info->stacked->depth;
+    if (maxstacks > info->nodes_used)
+        maxstacks = info->nodes_used;
 
-    for (i = 0; i < maxchains; i++) {
-        if (chains[i] == NULL)
+    for (i = 0; i < maxstacks; i++) {
+        if (stacks[i] == NULL)
             break;
-        if ((rc = procps_slabnode_getchain(info, chains[i]->head, i) < 0))
+        if ((rc = procps_slabnode_getstack(info, stacks[i]->head, i) < 0))
             return rc;
     }
 
-    info->chained->inuse = i;
-    return info->chained->inuse;
+    info->stacked->inuse = i;
+    return info->stacked->inuse;
 }
 
-static void chains_validate (struct slabnode_chain **v, const char *who)
+static void stacks_validate (struct slabnode_stack **v, const char *who)
 {
 #if 0
     #include <stdio.h>
-    int i, x, n = 0;
-    struct chain_vectors *p = (struct chain_vectors *)v - 1;
+    int i, t, x, n = 0;
+    struct stack_vectors *p = (struct stack_vectors *)v - 1;
 
     fprintf(stderr, "%s: called by '%s'\n", __func__, who);
     fprintf(stderr, "%s: owned by %p (whose self = %p)\n", __func__, p->owner, p->owner->self);
     for (x = 0; v[x]; x++) {
-        struct slabnode_chain *h = v[x];
-        struct slabnode_result *r = h->head;
+        struct slabnode_stack *h = v[x];
+        struct slab_result *r = h->head;
         fprintf(stderr, "%s:   vector[%02d] = %p", __func__, x, h);
-        i = 0;
-        do {
-            i++;
-            r = r->next;
-        } while (r);
-        fprintf(stderr, ", chain %d found %d elements\n", n, i);
+        for (i = 0; r->item < PROCPS_SLABNODE_stack_end; i++, r++)
+            ;
+        t = i + 1;
+        fprintf(stderr, ", stack %d found %d elements\n", n, i);
         ++n;
     }
-    fprintf(stderr, "%s: found %d chain(s)\n", __func__, x);
+    fprintf(stderr, "%s: found %d stack(s), each %d bytes (including eos)\n", __func__, x, (int)sizeof(struct slab_result) * t);
+    fprintf(stderr, "%s: found %d stack(s)\n", __func__, x);
     fprintf(stderr, "%s: this header size = %2d\n", __func__, (int)p->owner->header_size);
-    fprintf(stderr, "%s: sizeof(struct slabnode_chain)  = %2d\n", __func__, (int)sizeof(struct slabnode_chain));
-    fprintf(stderr, "%s: sizeof(struct slabnode_result) = %2d\n", __func__, (int)sizeof(struct slabnode_result));
+    fprintf(stderr, "%s: sizeof(struct slabnode_stack)  = %2d\n", __func__, (int)sizeof(struct slabnode_stack));
+    fprintf(stderr, "%s: sizeof(struct slab_result) = %2d\n", __func__, (int)sizeof(struct slab_result));
     fputc('\n', stderr);
     return;
 #endif
 }
 
-static struct slabnode_result *chain_make (
-        struct slabnode_result *p,
+static struct slab_result *stack_make (
+        struct slab_result *p,
         int maxitems,
         enum slabnode_item *items)
 {
-    struct slabnode_result *p_sav = p;
+    struct slab_result *p_sav = p;
     int i;
 
     for (i = 0; i < maxitems; i++) {
-        if (i > PROCPS_SLABNODE_noop)
-            p->item = PROCPS_SLABNODE_noop;
-        else
-            p->item = items[i];
-        p->result.num = 0;
-        p->next = p + 1;
+        p->item = items[i];
+        // note: we rely on calloc to initialize actual result
         ++p;
     }
-    (--p)->next = NULL;
 
     return p_sav;
 }
 
+static int stack_items_valid (
+        int maxitems,
+        enum slabnode_item *items)
+{
+    int i;
+
+    for (i = 0; i < maxitems; i++) {
+        if (items[i] < PROCPS_SLABNODE_SIZE)
+            return 0;
+        if (items[i] > PROCPS_SLABNODE_stack_end)
+            return 0;
+    }
+    if (items[maxitems -1] != PROCPS_SLABNODE_stack_end)
+        return 0;
+    return 1;
+}
+
 /*
- * procps_slabnode_chains_alloc():
+ * procps_slabnode_stacks_alloc():
  *
- * Allocate and initialize one or more chains each of which is anchored in an
- * associated meminfo_chain structure (which may include extra user space).
+ * Allocate and initialize one or more stacks each of which is anchored in an
+ * associated slabnode_stack structure (which may include extra user space).
  *
- * All such chains will will have their result structures properly primed with
- * 'items' and 'next' pointers, while the result itself will be zeroed.
+ * All such stacks will will have their result structures properly primed with
+ * 'items', while the result itself will be zeroed.
  *
- * Returns an array of pointers representing the 'heads' of each new chain.
+ * Returns an array of pointers representing the 'heads' of each new stack.
  */
-PROCPS_EXPORT struct slabnode_chain **procps_slabnode_chains_alloc (
+PROCPS_EXPORT struct slabnode_stack **procps_slabnode_stacks_alloc (
         struct procps_slabinfo *info,
-        int maxchains,
-        int chain_extra,
+        int maxstacks,
+        int stack_extra,
         int maxitems,
         enum slabnode_item *items)
 {
-    struct chains_anchor *p_blob;
-    struct chain_vectors *p_vect;
-    struct slabnode_chain *p_head;
+    struct stacks_anchor *p_blob;
+    struct stack_vectors *p_vect;
+    struct slabnode_stack *p_head;
     size_t vect_size, head_size, list_size, blob_size;
     void *v_head, *v_list;
     int i;
 
     if (info == NULL || items == NULL)
         return NULL;
-    if (maxchains < 1 || maxitems < 1)
+    if (maxstacks < 1 || maxitems < 1)
+        return NULL;
+    if (!stack_items_valid(maxitems, items))
         return NULL;
 
-    vect_size  = sizeof(struct chain_vectors);                 // address vector struct
-    vect_size += sizeof(void *) * maxchains;                   // plus vectors themselves
+    vect_size  = sizeof(struct stack_vectors);                 // address vector struct
+    vect_size += sizeof(void *) * maxstacks;                   // plus vectors themselves
     vect_size += sizeof(void *);                               // plus NULL delimiter
-    head_size  = sizeof(struct slabnode_chain) + chain_extra;  // a head struct + user stuff
-    list_size  = sizeof(struct slabnode_result) * maxitems;    // a results chain
-    blob_size  = sizeof(struct chains_anchor);                 // the anchor itself
+    head_size  = sizeof(struct slabnode_stack) + stack_extra;  // a head struct + user stuff
+    list_size  = sizeof(struct slab_result) * maxitems;        // a results stack
+    blob_size  = sizeof(struct stacks_anchor);                 // the anchor itself
     blob_size += vect_size;                                    // all vectors + delims
-    blob_size += head_size * maxchains;                        // all head structs + user stuff
-    blob_size += list_size * maxchains;                        // all results chains
+    blob_size += head_size * maxstacks;                        // all head structs + user stuff
+    blob_size += list_size * maxstacks;                        // all results stacks
 
     /* note: all memory is allocated in a single blob, facilitating a later free().
        as a minimum, it's important that the result structures themselves always be
-       contiguous for any given chain (just as they are when defined statically). */
+       contiguous for any given stack (just as they are when defined statically). */
     if (NULL == (p_blob = calloc(1, blob_size)))
         return NULL;
 
-    p_blob->next = info->chained;
-    info->chained = p_blob;
+    p_blob->next = info->stacked;
+    info->stacked = p_blob;
     p_blob->self  = p_blob;
     p_blob->header_size = head_size;
-    p_blob->vectors = (void *)p_blob + sizeof(struct chains_anchor);
+    p_blob->vectors = (void *)p_blob + sizeof(struct stacks_anchor);
     p_vect = p_blob->vectors;
     p_vect->owner = p_blob->self;
-    p_vect->heads = (void *)p_vect + sizeof(struct chain_vectors);
+    p_vect->heads = (void *)p_vect + sizeof(struct stack_vectors);
     v_head = (void *)p_vect + vect_size;
-    v_list = v_head + (head_size * maxchains);
+    v_list = v_head + (head_size * maxstacks);
 
-    for (i = 0; i < maxchains; i++) {
-        p_head = (struct slabnode_chain *)v_head;
-        p_head->head = chain_make((struct slabnode_result *)v_list, maxitems, items);
+    for (i = 0; i < maxstacks; i++) {
+        p_head = (struct slabnode_stack *)v_head;
+        p_head->head = stack_make((struct slab_result *)v_list, maxitems, items);
         p_blob->vectors->heads[i] = p_head;
         v_list += list_size;
         v_head += head_size;
     }
-    p_blob->depth = maxchains;
-    chains_validate(p_blob->vectors->heads, __func__);
+    p_blob->depth = maxstacks;
+    stacks_validate(p_blob->vectors->heads, __func__);
     return p_blob->vectors->heads;
 }
 
 /*
- * procps_slabnode_chain_alloc():
+ * procps_slabnode_stack_alloc():
  *
- * Allocate and initialize a single result chain under a simplified interface.
+ * Allocate and initialize a single result stack under a simplified interface.
  *
- * Such a chain will will have its result structures properly primed with
- * 'items' and 'next' pointers, while the result itself will be zeroed.
+ * Such a stack will will have its result structures properly primed with
+ * 'items', while the result itself will be zeroed.
  *
  */
-PROCPS_EXPORT struct slabnode_chain *procps_slabnode_chain_alloc (
+PROCPS_EXPORT struct slabnode_stack *procps_slabnode_stack_alloc (
         struct procps_slabinfo *info,
         int maxitems,
         enum slabnode_item *items)
 {
-    struct slabnode_chain **v;
+    struct slabnode_stack **v;
 
     if (info == NULL || items == NULL || maxitems < 1)
         return NULL;
-    v = procps_slabnode_chains_alloc(info, 1, 0, maxitems, items);
+    v = procps_slabnode_stacks_alloc(info, 1, 0, maxitems, items);
     if (!v)
         return NULL;
-    chains_validate(v, __func__);
+    stacks_validate(v, __func__);
     return v[0];
 }
 
-static int chains_sort (
-        const struct slabnode_chain **A,
-        const struct slabnode_chain **B,
+static int stacks_sort (
+        const struct slabnode_stack **A,
+        const struct slabnode_stack **B,
         enum slabnode_item *offset)
 {
-    const struct slabnode_result *a = (*A)->head + *offset;
-    const struct slabnode_result *b = (*B)->head + *offset;
+    const struct slab_result *a = (*A)->head + *offset;
+    const struct slab_result *b = (*B)->head + *offset;
     // note: everything will be sorted high-to-low
-    if (a->item == PROCPS_SLABNODE_NAME)
-        return strcoll(a->result.str, b->result.str);
-    if ( a->result.num > b->result.num ) return -1;
-    if ( a->result.num < b->result.num ) return +1;
+    switch (a->item) {
+        case PROCPS_SLABNODE_noop:
+        case PROCPS_SLABNODE_stack_end:
+            break;
+        case PROCPS_SLABNODE_NAME:
+            return strcoll(a->result.str, b->result.str);
+        case PROCPS_SLABNODE_SIZE:
+            if ( a->result.ul_int > b->result.ul_int ) return -1;
+            if ( a->result.ul_int < b->result.ul_int ) return +1;
+            break;
+        default:
+            if ( a->result.u_int > b->result.u_int ) return -1;
+            if ( a->result.u_int < b->result.u_int ) return +1;
+            break;
+    }
     return 0;
 }
 
 /*
- * procps_slabnode_chains_sort():
+ * procps_slabnode_stacks_sort():
  *
- * Sort chains anchored as 'heads' in the passed slabnode_chain pointers
+ * Sort stacks anchored as 'heads' in the passed slabnode_stack pointers
  * array based on the designated sort enumerator.
  *
  * Returns those same addresses sorted.
  *
- * Note: all of the chains must be homogeneous (of equal length and content).
+ * Note: all of the stacks must be homogeneous (of equal length and content).
  */
-PROCPS_EXPORT struct slabnode_chain **procps_slabnode_chains_sort (
+PROCPS_EXPORT struct slabnode_stack **procps_slabnode_stacks_sort (
         struct procps_slabinfo *info,
-        struct slabnode_chain **chains,
-        int numchained,
+        struct slabnode_stack **stacks,
+        int numstacked,
         enum slabnode_item sort)
 {
  #define QSORT_r  int (*)(const void *, const void *, void *)
-    struct slabnode_result *p = chains[0]->head;
+    struct slab_result *p = stacks[0]->head;
     int offset = 0;;
 
-    if (info == NULL || chains == NULL)
+    if (info == NULL || stacks == NULL)
         return NULL;
     if (sort < 0  || sort > PROCPS_SLABNODE_noop)
         return NULL;
-    if (numchained > info->chained->depth)
+    if (numstacked > info->stacked->depth)
         return NULL;
-    if (numchained < 2)
-        return chains;
+    if (numstacked < 2)
+        return stacks;
 
-    if (numchained > info->chained->inuse)
-        numchained = info->chained->inuse;
+    if (numstacked > info->stacked->inuse)
+        numstacked = info->stacked->inuse;
 
     for (;;) {
         if (p->item == sort)
             break;
         ++offset;
-        if (!(p = p->next))
+        if (p->item == PROCPS_SLABNODE_stack_end)
             return NULL;
+        ++p;
     }
-    qsort_r(chains, numchained, sizeof(void *), (QSORT_r)chains_sort, &offset);
-    return chains;
+    qsort_r(stacks, numstacked, sizeof(void *), (QSORT_r)stacks_sort, &offset);
+    return stacks;
  #undef QSORT_r
 }
index 8e2b6a0da424848b2beac3b3ad77142742d6d255..a41460c0715a57ea63581851e9eba15e320c7715 100644 (file)
 __BEGIN_DECLS
 
 enum slabs_item {
-    PROCPS_SLABS_OBJS,
-    PROCPS_SLABS_AOBJS,
-    PROCPS_SLABS_PAGES,
-    PROCPS_SLABS_SLABS,
-    PROCPS_SLABS_ASLABS,
-    PROCPS_SLABS_CACHES,
-    PROCPS_SLABS_ACACHES,
-    PROCPS_SLABS_SIZE_AVG,
-    PROCPS_SLABS_SIZE_MIN,
-    PROCPS_SLABS_SIZE_MAX,
-    PROCPS_SLABS_SIZE_TOTAL,
-    PROCPS_SLABS_SIZE_ACTIVE,
-    PROCPS_SLABS_noop
+    PROCPS_SLABS_OBJS,                 // u_int
+    PROCPS_SLABS_AOBJS,                // u_int
+    PROCPS_SLABS_PAGES,                // u_int
+    PROCPS_SLABS_SLABS,                // u_int
+    PROCPS_SLABS_ASLABS,               // u_int
+    PROCPS_SLABS_CACHES,               // u_int
+    PROCPS_SLABS_ACACHES,              // u_int
+    PROCPS_SLABS_SIZE_AVG,             // u_int
+    PROCPS_SLABS_SIZE_MIN,             // u_int
+    PROCPS_SLABS_SIZE_MAX,             // u_int
+    PROCPS_SLABS_SIZE_TOTAL,           // ul_int
+    PROCPS_SLABS_SIZE_ACTIVE,          // ul_int
+    PROCPS_SLABS_noop,                 // n/a
+    PROCPS_SLABS_stack_end             // n/a
 };
 
 enum slabnode_item {
-    PROCPS_SLABNODE_SIZE,
-    PROCPS_SLABNODE_OBJS,
-    PROCPS_SLABNODE_AOBJS,
-    PROCPS_SLABNODE_OBJ_SIZE,
-    PROCPS_SLABNODE_OBJS_PER_SLAB,
-    PROCPS_SLABNODE_PAGES_PER_SLAB,
-    PROCPS_SLABNODE_SLABS,
-    PROCPS_SLABNODE_ASLABS,
-    PROCPS_SLABNODE_USE,
-    PROCPS_SLABNODE_NAME,
-    PROCPS_SLABNODE_noop
+    PROCPS_SLABNODE_SIZE,              // ul_int
+    PROCPS_SLABNODE_OBJS,              // u_int
+    PROCPS_SLABNODE_AOBJS,             // u_int
+    PROCPS_SLABNODE_OBJ_SIZE,          // u_int
+    PROCPS_SLABNODE_OBJS_PER_SLAB,     // u_int
+    PROCPS_SLABNODE_PAGES_PER_SLAB,    // u_int
+    PROCPS_SLABNODE_SLABS,             // u_int
+    PROCPS_SLABNODE_ASLABS,            // u_int
+    PROCPS_SLABNODE_USE,               // u_int
+    PROCPS_SLABNODE_NAME,              // str
+    PROCPS_SLABNODE_noop,              // n/a
+    PROCPS_SLABNODE_stack_end          // n/a
 };
 
 struct procps_slabinfo;
 
-struct slabs_result {
-    enum slabs_item item;
-    unsigned long result;
-    struct slabs_result *next;
+struct slabnode_stack {
+    struct slab_result *head;
 };
 
-struct slabnode_chain {
-    struct slabnode_result *head;
-};
-
-struct slabnode_result {
-    enum slabnode_item item;
+struct slab_result {
+    int item;
     union {
-        unsigned long num;
+        unsigned int u_int;
+        unsigned long ul_int;
         char *str;
     } result;
-    struct slabnode_result *next;
 };
 
 int procps_slabinfo_new (struct procps_slabinfo **info);
@@ -85,11 +81,11 @@ unsigned long procps_slabs_get (
     struct procps_slabinfo *info,
     enum slabs_item item);
 
-int procps_slabs_getchain (
+int procps_slabs_getstack (
     struct procps_slabinfo *info,
-    struct slabs_result *these);
+    struct slab_result *these);
 
-int procps_slabnode_count (const struct procps_slabinfo *info);
+int procps_slabnode_count (struct procps_slabinfo *info);
 
 const char *procps_slabnode_getname (
     struct procps_slabinfo *info,
@@ -100,37 +96,37 @@ unsigned long procps_slabnode_get (
     enum slabnode_item item,
     int nodeid);
 
-int procps_slabnode_getchain (
+int procps_slabnode_getstack (
     struct procps_slabinfo *info,
-    struct slabnode_result *these,
+    struct slab_result *these,
     int nodeid);
 
-int procps_slabnode_chain_fill (
+int procps_slabnode_stack_fill (
     struct procps_slabinfo *info,
-    struct slabnode_chain *chain,
+    struct slabnode_stack *stack,
     int nodeid);
 
-int procps_slabnode_chains_fill (
+int procps_slabnode_stacks_fill (
     struct procps_slabinfo *info,
-    struct slabnode_chain **chains,
-    int maxchains);
+    struct slabnode_stack **stacks,
+    int maxstacks);
 
-struct slabnode_chain *procps_slabnode_chain_alloc (
+struct slabnode_stack *procps_slabnode_stack_alloc (
     struct procps_slabinfo *info,
     int maxitems,
     enum slabnode_item *items);
 
-struct slabnode_chain **procps_slabnode_chains_alloc (
+struct slabnode_stack **procps_slabnode_stacks_alloc (
     struct procps_slabinfo *info,
-    int maxchains,
-    int chain_extra,
+    int maxstacks,
+    int stack_extra,
     int maxitems,
     enum slabnode_item *items);
 
-struct slabnode_chain **procps_slabnode_chains_sort (
+struct slabnode_stack **procps_slabnode_stacks_sort (
     struct procps_slabinfo *info,
-    struct slabnode_chain **chains,
-    int numchained,
+    struct slabnode_stack **stacks,
+    int numstacked,
     enum slabnode_item sort);
 
 __END_DECLS
index f197d44720b8b3c31744b0ec891c9df8f68293cc..36d7c5367634329dae6d0e1221ba3c0e8ce43085 100644 (file)
--- a/slabtop.c
+++ b/slabtop.c
@@ -60,10 +60,10 @@ enum slabnode_item Node_items[] = {
     PROCPS_SLABNODE_OBJS,     PROCPS_SLABNODE_AOBJS, PROCPS_SLABNODE_USE,
     PROCPS_SLABNODE_OBJ_SIZE, PROCPS_SLABNODE_SLABS, PROCPS_SLABNODE_OBJS_PER_SLAB,
     PROCPS_SLABNODE_SIZE,     PROCPS_SLABNODE_NAME,
-    /* last 2 are sortable but are not displayable,
+    /* next 2 are sortable but are not displayable,
        thus they need not be represented in the Relative_enums */
-    PROCPS_SLABNODE_PAGES_PER_SLAB,
-    PROCPS_SLABNODE_ASLABS };
+    PROCPS_SLABNODE_PAGES_PER_SLAB, PROCPS_SLABNODE_ASLABS,
+    PROCPS_SLABNODE_stack_end };
 
 enum Relative_enums {
     my_OBJS,  my_AOBJS, my_USE,  my_OSIZE,
@@ -195,61 +195,60 @@ static void parse_opts (int argc, char **argv)
 
 static void print_summary (void)
 {
- #define STAT_VAL(e) (int)stats[e].result
     enum slabs_enums {
         stat_AOBJS,   stat_OBJS,   stat_ASLABS, stat_SLABS,
         stat_ACACHES, stat_CACHES, stat_ACTIVE, stat_TOTAL,
-        stat_MIN,     stat_AVG,    stat_MAX,
+        stat_MIN,     stat_AVG,    stat_MAX
     };
-    static struct slabs_result stats[] = {
-        { PROCPS_SLABS_AOBJS,        0, &stats[1] },
-        { PROCPS_SLABS_OBJS,         0, &stats[2] },
-        { PROCPS_SLABS_ASLABS,       0, &stats[3] },
-        { PROCPS_SLABS_SLABS,        0, &stats[4] },
-        { PROCPS_SLABS_ACACHES,      0, &stats[5] },
-        { PROCPS_SLABS_CACHES,       0, &stats[6] },
-        { PROCPS_SLABS_SIZE_ACTIVE,  0, &stats[7] },
-        { PROCPS_SLABS_SIZE_TOTAL,   0, &stats[8] },
-        { PROCPS_SLABS_SIZE_MIN,     0, &stats[9] },
-        { PROCPS_SLABS_SIZE_AVG,     0, &stats[10] },
-        { PROCPS_SLABS_SIZE_MAX,     0, NULL },
+    static struct slab_result stats[] = {
+        { PROCPS_SLABS_AOBJS,       0 },
+        { PROCPS_SLABS_OBJS,        0 },
+        { PROCPS_SLABS_ASLABS,      0 },
+        { PROCPS_SLABS_SLABS,       0 },
+        { PROCPS_SLABS_ACACHES,     0 },
+        { PROCPS_SLABS_CACHES,      0 },
+        { PROCPS_SLABS_SIZE_ACTIVE, 0 },
+        { PROCPS_SLABS_SIZE_TOTAL,  0 },
+        { PROCPS_SLABS_SIZE_MIN,    0 },
+        { PROCPS_SLABS_SIZE_AVG,    0 },
+        { PROCPS_SLABS_SIZE_MAX,    0 },
+        { PROCPS_SLABS_stack_end,   0 }
     };
 
-    if (procps_slabs_getchain(Slab_info, stats) < 0) \
+    if (procps_slabs_getstack(Slab_info, stats) < 0) \
         xerrx(EXIT_FAILURE, _("Error getting slab summary results"));
 
-    PRINT_line(" %-35s: %d / %d (%.1f%%)\n"
+    PRINT_line(" %-35s: %u / %u (%.1f%%)\n"
                , /* Translation Hint: Next five strings must not
                   * exceed a length of 35 characters.  */
                  /* xgettext:no-c-format */
                  _("Active / Total Objects (% used)")
-               , STAT_VAL(stat_AOBJS)
-               , STAT_VAL(stat_OBJS)
-               , 100.0 * STAT_VAL(stat_AOBJS) / STAT_VAL(stat_OBJS));
-    PRINT_line(" %-35s: %d / %d (%.1f%%)\n"
+               , stats[stat_AOBJS].result.u_int
+               , stats[stat_OBJS ].result.u_int
+               , 100.0 * stats[stat_AOBJS].result.u_int / stats[stat_OBJS].result.u_int);
+    PRINT_line(" %-35s: %u / %u (%.1f%%)\n"
                , /* xgettext:no-c-format */
                  _("Active / Total Slabs (% used)")
-               , STAT_VAL(stat_ASLABS)
-               , STAT_VAL(stat_SLABS)
-               , 100.0 * STAT_VAL(stat_ASLABS) / STAT_VAL(stat_SLABS));
-    PRINT_line(" %-35s: %d / %d (%.1f%%)\n"
+               , stats[stat_ASLABS].result.u_int
+               , stats[stat_SLABS  ].result.u_int
+               , 100.0 * stats[stat_ASLABS].result.u_int / stats[stat_SLABS].result.u_int);
+    PRINT_line(" %-35s: %u / %u (%.1f%%)\n"
                , /* xgettext:no-c-format */
                  _("Active / Total Caches (% used)")
-               , STAT_VAL(stat_ACACHES)
-               , STAT_VAL(stat_CACHES)
-               , 100.0 * STAT_VAL(stat_ACACHES) / STAT_VAL(stat_CACHES));
+               , stats[stat_ACACHES].result.u_int
+               , stats[stat_CACHES ].result.u_int
+               , 100.0 * stats[stat_ACACHES].result.u_int / stats[stat_CACHES].result.u_int);
     PRINT_line(" %-35s: %.2fK / %.2fK (%.1f%%)\n"
                , /* xgettext:no-c-format */
                  _("Active / Total Size (% used)")
-               , STAT_VAL(stat_ACTIVE) / 1024.0
-               , STAT_VAL(stat_TOTAL) / 1024.0
-               , 100.0 * STAT_VAL(stat_ACTIVE) / STAT_VAL(stat_TOTAL));
+               , stats[stat_ACTIVE].result.ul_int / 1024.0
+               , stats[stat_TOTAL ].result.ul_int / 1024.0
+               , 100.0 * stats[stat_ACTIVE].result.ul_int / stats[stat_TOTAL].result.ul_int);
     PRINT_line(" %-35s: %.2fK / %.2fK / %.2fK\n\n"
                , _("Minimum / Average / Maximum Object")
-               , STAT_VAL(stat_MIN) / 1024.0
-               , STAT_VAL(stat_AVG) / 1024.0
-               , STAT_VAL(stat_MAX) / 1024.0);
- #undef STAT_VAL
+               , stats[stat_MIN].result.u_int / 1024.0
+               , stats[stat_AVG].result.u_int / 1024.0
+               , stats[stat_MAX].result.u_int / 1024.0);
 }
 
 static void print_headings (void)
@@ -259,21 +258,19 @@ static void print_headings (void)
     PRINT_line("%-78s\n", _("  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME"));
 }
 
-static void print_details (struct slabnode_chain *chain)
+static void print_details (struct slabnode_stack *stack)
 {
- #define my_NUM(c,e) (unsigned)c->head[e].result.num
- #define my_STR(c,e) c->head[e].result.str
-
-    PRINT_line("%6u %6u %3u%% %7.2fK %6u %8u %9uK %-23s\n"
-        , my_NUM(chain, my_OBJS),  my_NUM(chain, my_AOBJS)
-        , my_NUM(chain, my_USE),   my_NUM(chain, my_OSIZE) / 1024.0
-        , my_NUM(chain, my_SLABS), my_NUM(chain, my_OPS)
-        , my_NUM(chain, my_SIZE) / 1024
-        , my_STR(chain, my_NAME));
+    PRINT_line("%6u %6u %3u%% %7.2fK %6u %8u %9luK %-23s\n"
+        , stack->head[my_OBJS ].result.u_int
+        , stack->head[my_AOBJS].result.u_int
+        , stack->head[my_USE  ].result.u_int
+        , stack->head[my_OSIZE].result.u_int / 1024.0
+        , stack->head[my_SLABS].result.u_int
+        , stack->head[my_OPS  ].result.u_int
+        , stack->head[my_SIZE ].result.ul_int / 1024
+        , stack->head[my_NAME ].result.str);
 
     return;
- #undef my_NUM
- #undef my_STR
 }
 
 
@@ -281,7 +278,7 @@ int main(int argc, char *argv[])
 {
     int is_tty, nr_slabs, rc = EXIT_SUCCESS;
     unsigned short old_rows;
-    struct slabnode_chain **v;
+    struct slabnode_stack **v;
 
 #ifdef HAVE_PROGRAM_INVOCATION_NAME
     program_invocation_name = program_invocation_short_name;
@@ -296,7 +293,7 @@ int main(int argc, char *argv[])
     if (procps_slabinfo_new(&Slab_info) < 0)
         xerrx(EXIT_FAILURE, _("Unable to create slabinfo structure"));
 
-    if (!(v = procps_slabnode_chains_alloc(Slab_info, CHAINS_ALLOC, 0, MAX_ITEMS, Node_items)))
+    if (!(v = procps_slabnode_stacks_alloc(Slab_info, CHAINS_ALLOC, 0, MAX_ITEMS, Node_items)))
         xerrx(EXIT_FAILURE, _("Unable to allocate slabinfo nodes"));
 
     if (!Run_once) {
@@ -317,12 +314,12 @@ int main(int argc, char *argv[])
         int i;
 
         // this next guy also performs the procps_slabnode_read() call
-        if ((nr_slabs = procps_slabnode_chains_fill(Slab_info, v, CHAINS_ALLOC)) < 0) {
+        if ((nr_slabs = procps_slabnode_stacks_fill(Slab_info, v, CHAINS_ALLOC)) < 0) {
             xwarn(_("Unable to get slabinfo node data"));
             rc = EXIT_FAILURE;
             break;
         }
-        if (!(v = procps_slabnode_chains_sort(Slab_info, v, nr_slabs, Sort_item))) {
+        if (!(v = procps_slabnode_stacks_sort(Slab_info, v, nr_slabs, Sort_item))) {
             xwarn(_("Unable to sort slab nodes"));
             rc = EXIT_FAILURE;
             break;
index 57b27617a09f8b5444c2aac7cc3bdce35ca9f9ff..919076e67ddc35741ade7283677090b7b4e496b5 100644 (file)
--- a/vmstat.c
+++ b/vmstat.c
@@ -612,22 +612,19 @@ static void slabformat (void)
 {
  #define CHAINS_ALLOC  150
  #define MAX_ITEMS (int)(sizeof(node_items) / sizeof(node_items[0]))
- #define SLAB_NUM(c,e) (unsigned)c->head[e].result.num
- #define SLAB_STR(c,e) c->head[e].result.str
     struct procps_slabinfo *slab_info;
-    struct slabnode_chain **v;
+    struct slabnode_stack **v, *p;
     int i, j, nr_slabs;
-    const char format[] = "%-24.24s %6u %6u %6u %6u\n";
     enum slabnode_item node_items[] = {
         PROCPS_SLABNODE_AOBJS,    PROCPS_SLABNODE_OBJS,
         PROCPS_SLABNODE_OBJ_SIZE, PROCPS_SLABNODE_OBJS_PER_SLAB,
-        PROCPS_SLABNODE_NAME };
+        PROCPS_SLABNODE_NAME,     PROCPS_SLABNODE_stack_end };
     enum rel_enums {
         slab_AOBJS, slab_OBJS, slab_OSIZE, slab_OPS, slab_NAME };
 
     if (procps_slabinfo_new(&slab_info) < 0)
         xerrx(EXIT_FAILURE, _("Unable to create slabinfo structure"));
-    if (!(v = procps_slabnode_chains_alloc(slab_info, CHAINS_ALLOC, 0, MAX_ITEMS, node_items)))
+    if (!(v = procps_slabnode_stacks_alloc(slab_info, CHAINS_ALLOC, 0, MAX_ITEMS, node_items)))
         xerrx(EXIT_FAILURE, _("Unable to allocate slabinfo nodes"));
 
     if (!moreheaders)
@@ -635,18 +632,21 @@ static void slabformat (void)
 
     for (i = 0; infinite_updates || i < num_updates; i++) {
         // this next guy also performs the procps_slabnode_read() call
-        if ((nr_slabs = procps_slabnode_chains_fill(slab_info, v, CHAINS_ALLOC)) < 0)
+        if ((nr_slabs = procps_slabnode_stacks_fill(slab_info, v, CHAINS_ALLOC)) < 0)
             xerrx(EXIT_FAILURE, _("Unable to get slabinfo node data, requires root permission"));
-        if (!(v = procps_slabnode_chains_sort(slab_info, v, nr_slabs, PROCPS_SLABNODE_NAME)))
+        if (!(v = procps_slabnode_stacks_sort(slab_info, v, nr_slabs, PROCPS_SLABNODE_NAME)))
             xerrx(EXIT_FAILURE, _("Unable to sort slab nodes"));
 
         for (j = 0; j < nr_slabs; j++) {
+            p = v[j];
             if (moreheaders && ((j % height) == 0))
                 slabheader();
-            printf(format,
-                   SLAB_STR(v[j], slab_NAME),
-                   SLAB_NUM(v[j], slab_AOBJS), SLAB_NUM(v[j], slab_OBJS),
-                   SLAB_NUM(v[j], slab_OSIZE), SLAB_NUM(v[j], slab_OPS));
+            printf("%-24.24s %6u %6u %6u %6u\n",
+                p->head[slab_NAME ].result.str,
+                p->head[slab_AOBJS].result.u_int,
+                p->head[slab_OBJS ].result.u_int,
+                p->head[slab_OSIZE].result.u_int,
+                p->head[slab_OPS  ].result.u_int);
         }
         if (infinite_updates || i+1 < num_updates)
             sleep(sleep_time);
@@ -654,8 +654,6 @@ static void slabformat (void)
     procps_slabinfo_unref(&slab_info);
  #undef CHAINS_ALLOC
  #undef MAX_ITEMS
- #undef SLAB_NUM
- #undef SLAB_STR
 }
 
 static void disksum_format(void)