diff options
author | Jim Warner <james.warner@comcast.net> | 2023-05-03 00:00:00 -0500 |
---|---|---|
committer | Craig Small <csmall@dropbear.xyz> | 2023-05-07 09:43:44 +1000 |
commit | 1c9e65d785b8b8d82256f946d4feb2a1070ac02f (patch) | |
tree | 6b486fca4f27346e536bc7d601454521ca9b1929 | |
parent | 157612a5ed91d0e6485e56b20beced90c31202cf (diff) | |
download | procps-ng-1c9e65d785b8b8d82256f946d4feb2a1070ac02f.tar.gz |
library: improve the assign results function, pids api
Currently, all the newlib APIs handle the assigning of
results the same. Namely, they loop through the stacks
while checking for the hidden 'logical_end' fencepost.
Along the way, the Item_table was indexed to determine
which 'setsfunc' to call, passing suitable parameters.
The approach was quite robust since by testing against
the unsigned 'logical_end' enumerator this library was
immune from user result corruption. The worst that may
happen was early loop exit with some results unvalued.
However, there was a drawback to the current approach.
For every result structure in every stack, an index to
that Item_table had to be calculated for a 'setsfunc'.
For programs like top or ps that may involve thousands
of Item_table index recalculations for each iteration.
With this commit, in support of assign, we will now do
the needed Item_table calculations just one time under
the 'new' and 'reset' functions. Then, at assign time,
the only overhead is actually invoking the 'setsfunc'.
This makes us even more robust than we were before. No
longer will a corrupted results structure suffer early
assign exit leaving some unvalued. Rather, all results
are properly placed regardless of any user corruption.
[ those other interfaces will remain unchanged since ]
[ the depth of their stacks are modest and since the ]
[ assign guys weren't already passed an info pointer ]
Signed-off-by: Jim Warner <james.warner@comcast.net>
-rw-r--r-- | library/pids.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/library/pids.c b/library/pids.c index 3b9bf99..6ae94ad 100644 --- a/library/pids.c +++ b/library/pids.c @@ -75,6 +75,8 @@ struct fetch_support { struct pids_counts counts; // actual counts pointed to by 'results' }; +typedef void (*SET_t)(struct pids_info *, struct pids_result *, proc_t *); + struct pids_info { int refcount; int maxitems; // includes 'logical_end' delimiter @@ -96,6 +98,7 @@ struct pids_info { int seterr; // an ENOMEM encountered during assign proc_t get_proc; // the proc_t used by procps_pids_get proc_t fetch_proc; // the proc_t used by pids_stacks_fetch + SET_t *func_array; // extracted Item_table 'setsfunc' pointers }; @@ -403,7 +406,6 @@ srtDECL(noop) { // placed here so an 'f' prefix wouldn't make 'em first #define z_autogrp PROC_FILLAUTOGRP -typedef void (*SET_t)(struct pids_info *, struct pids_result *, proc_t *); typedef void (*FRE_t)(struct pids_result *); typedef int (*QSR_t)(const void *, const void *, void *); @@ -856,14 +858,13 @@ static inline int pids_assign_results ( proc_t *p) { struct pids_result *this = stack->head; + SET_t *that = &info->func_array[0]; info->seterr = 0; - for (;;) { - enum pids_item item = this->item; - if (item >= PIDS_logical_end) - break; - Item_table[item].setsfunc(info, this, p); + while (*that) { + (*that)(info, this, p); ++this; + ++that; } return !info->seterr; } // end: pids_assign_results @@ -1041,6 +1042,20 @@ static inline int pids_oldproc_open ( } // end: pids_oldproc_open +static int pids_prep_func_array ( + struct pids_info *info) +{ + int i; + + if (!(info->func_array = realloc(info->func_array, sizeof(SET_t) * info->maxitems))) + return 0; + for (i = 0; i < info->maxitems -1; i++) + info->func_array[i] = Item_table[info->items[i]].setsfunc; + info->func_array[i] = NULL; + return 1; +} // end: pids_prep_func_array + + static inline int pids_proc_tally ( struct pids_info *info, struct pids_counts *counts, @@ -1273,6 +1288,8 @@ PROCPS_EXPORT int procps_pids_new ( memcpy(p->items, items, sizeof(enum pids_item) * numitems); p->items[numitems] = PIDS_logical_end; pids_libflags_set(p); + if (!pids_prep_func_array(p)) + return -ENOMEM; } if (!(p->hist = calloc(1, sizeof(struct history_info))) @@ -1360,6 +1377,9 @@ PROCPS_EXPORT int procps_pids_unref ( if ((*info)->get_ext) pids_oldproc_close(&(*info)->get_PT); + if ((*info)->func_array) + free((*info)->func_array); + numa_uninit(); free(*info); @@ -1528,6 +1548,8 @@ PROCPS_EXPORT int procps_pids_reset ( // so we'll rely on pids_stacks_alloc() to itemize ... pids_itemize_stacks_all(info); pids_libflags_set(info); + if (!pids_prep_func_array(info)) + return -ENOMEM; return 0; } // end: procps_pids_reset |