library: standardize portions of interface, <PIDS> api
This represents a rather major interface redesign. The following highlights most of the changes/enhancements. . The 'read' interface (employed by pgrep & pidof) saw the biggest change. The 'open', 'next' and 'shut' guys all went bye-bye, replaced by a single 'get' function. . The items specified at 'new' time no longer serve as the maximum. In fact, items & numitems are now treated as optional, should callers prefer to wait until later when the 'reset' function would then become mandatory. . Even at 'reset' time, the stacks are not tied to any sort of maximum. They will grow dynamically as needed. . The order of some parameters was changed to parallel that found in our other APIs. Specifically, when items & numitems are needed they're specified in that order. . A user will no longer be prevented from concurrently employing any accessor functions. In other words, that 'get' (old 'read') won't preclude 'reap' and 'select'. . A duplicate enumerator was found dealing with locked resident pages. So, the name VM_LOCK was eliminated in favor of VM_RSS_LOCKED, which is way more descriptive. . The struct address returned to callers following any reap() or select() is now more sharable as pids_fetch. . Some input parameter names were changed to make them more descriptive of the intended purpose/requirements. ------------------------------------------------------ Internally, there were numerous implementation changes made that did not directly impact any potential users. . That #define FPRINT_STACKS was eliminated along with the associated supporting function and its invocation. . Addresses returned following 'reap' or 'select' will now be NULL delimited, so one has the option of stacks access via the total count or this new NULL fencepost. . Input params were simplified and generalized in both oldproc_open() & close() to enable more than 1 PROCTAB to be open simultaneously, which was required for get. . The PROCPS_PIDS_logical_end enum was relocated after the Item_table making the need to keep it synchronized more apparent (if the table expands it's right there). . The 'Public function' section of the source file was subdivided into 1) the three basic required functions; and 2) functions that can sometimes vary between APIs. Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
parent
bfb7361980
commit
9ebadc1438
@ -25,15 +25,13 @@ global:
|
|||||||
procps_ns_read_pid;
|
procps_ns_read_pid;
|
||||||
procps_pid_length;
|
procps_pid_length;
|
||||||
procps_pids_new;
|
procps_pids_new;
|
||||||
procps_pids_read_next;
|
|
||||||
procps_pids_read_open;
|
|
||||||
procps_pids_read_shut;
|
|
||||||
procps_pids_reap;
|
|
||||||
procps_pids_ref;
|
procps_pids_ref;
|
||||||
|
procps_pids_unref;
|
||||||
|
procps_pids_get;
|
||||||
|
procps_pids_reap;
|
||||||
procps_pids_reset;
|
procps_pids_reset;
|
||||||
procps_pids_select;
|
procps_pids_select;
|
||||||
procps_pids_sort;
|
procps_pids_sort;
|
||||||
procps_pids_unref;
|
|
||||||
procps_slabinfo_new;
|
procps_slabinfo_new;
|
||||||
procps_slabinfo_read;
|
procps_slabinfo_read;
|
||||||
procps_slabinfo_ref;
|
procps_slabinfo_ref;
|
||||||
|
664
proc/pids.c
664
proc/pids.c
@ -45,16 +45,10 @@
|
|||||||
#include "wchan.h" // ( maybe just temporary? )
|
#include "wchan.h" // ( maybe just temporary? )
|
||||||
|
|
||||||
//#define UNREF_RPTHASH // report on hashing, at uref time
|
//#define UNREF_RPTHASH // report on hashing, at uref time
|
||||||
//#define FPRINT_STACKS // enable fprint_stacks output
|
|
||||||
|
|
||||||
#define FILL_ID_MAX 255 // upper limit for pid/uid fills
|
#define FILL_ID_MAX 255 // upper limit for pid/uid fills
|
||||||
#define MEMORY_INCR 128 // amt by which allocations grow
|
#define MEMORY_INCR 128 // amt by which allocations grow
|
||||||
|
|
||||||
#define READS_BEGUN (info->read) // a read is in progress
|
|
||||||
|
|
||||||
// next MUST be kept in sync with highest value enum
|
|
||||||
enum pids_item PROCPS_PIDS_logical_end = PROCPS_PIDS_WCHAN_NAME + 1;
|
|
||||||
|
|
||||||
// these represent the proc_t fields whose storage cannot be managed
|
// these represent the proc_t fields whose storage cannot be managed
|
||||||
// optimally if they are ever referenced more than once in any stack
|
// optimally if they are ever referenced more than once in any stack
|
||||||
enum rel_ref {
|
enum rel_ref {
|
||||||
@ -66,17 +60,16 @@ enum rel_ref {
|
|||||||
|
|
||||||
struct stacks_extent {
|
struct stacks_extent {
|
||||||
struct pids_stack **stacks;
|
struct pids_stack **stacks;
|
||||||
int ext_numitems; // includes 'logical_end' delimiter
|
|
||||||
int ext_numstacks;
|
int ext_numstacks;
|
||||||
struct stacks_extent *next;
|
struct stacks_extent *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fetch_support {
|
struct fetch_support {
|
||||||
struct pids_stack **anchor; // reapable/fillable (consolidated extents)
|
struct pids_stack **anchor; // reap/select consolidated extents
|
||||||
int n_alloc; // number of above pointers allocated
|
int n_alloc; // number of above pointers allocated
|
||||||
int n_inuse; // number of above pointers occupied
|
int n_inuse; // number of above pointers occupied
|
||||||
int n_alloc_save; // last known summary.stacks allocation
|
int n_alloc_save; // last known summary.stacks allocation
|
||||||
struct pids_reap summary; // counts + stacks for return to caller
|
struct pids_fetch summary; // counts + stacks for return to caller
|
||||||
};
|
};
|
||||||
|
|
||||||
struct procps_pidsinfo {
|
struct procps_pidsinfo {
|
||||||
@ -86,19 +79,20 @@ struct procps_pidsinfo {
|
|||||||
enum pids_item *items; // includes 'logical_end' delimiter
|
enum pids_item *items; // includes 'logical_end' delimiter
|
||||||
struct stacks_extent *extents; // anchor for all resettable extents
|
struct stacks_extent *extents; // anchor for all resettable extents
|
||||||
struct stacks_extent *otherexts; // anchor for single stack invariant extents
|
struct stacks_extent *otherexts; // anchor for single stack invariant extents
|
||||||
struct fetch_support reap; // support for procps_pids_reap
|
struct fetch_support fetch; // support for procps_pids_reap & select
|
||||||
struct fetch_support select; // support for procps_pids_select
|
|
||||||
int history_yes; // need historical data
|
int history_yes; // need historical data
|
||||||
struct history_info *hist; // pointer to historical support data
|
struct history_info *hist; // pointer to historical support data
|
||||||
int dirty_stacks; // extents need dynamic storage clean
|
int dirty_stacks; // extents need dynamic storage clean
|
||||||
struct stacks_extent *read; // an extent used for active reads
|
|
||||||
proc_t*(*read_something)(PROCTAB*, proc_t*); // readproc/readeither via which
|
proc_t*(*read_something)(PROCTAB*, proc_t*); // readproc/readeither via which
|
||||||
unsigned pgs2k_shift; // to convert some proc vaules
|
unsigned pgs2k_shift; // to convert some proc vaules
|
||||||
unsigned flags; // the old library PROC_FILL flagss
|
unsigned oldflags; // the old library PROC_FILL flagss
|
||||||
PROCTAB *PT; // the old library essential interface
|
PROCTAB *PT; // the old library essential interface
|
||||||
unsigned long hertz; // for TIME_ALL & TIME_ELAPSED calculations
|
unsigned long hertz; // for TIME_ALL & TIME_ELAPSED calculations
|
||||||
unsigned long long boot_seconds; // for TIME_ELAPSED calculation
|
unsigned long long boot_seconds; // for TIME_ELAPSED calculation
|
||||||
int ref_counts[MAXIMUM_ref]; // ref counts for special string fields
|
int ref_counts[MAXIMUM_ref]; // ref counts for special string fields
|
||||||
|
PROCTAB *get_PT; // old library interface for active 'get'
|
||||||
|
struct stacks_extent *get_ext; // an extent used for active 'get'
|
||||||
|
enum pids_fetch_type get_type; // last known type of 'get' request
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -242,7 +236,6 @@ setDECL(TTY_NUMBER) { char buf[64]; (void)I; dev_to_tty(buf, sizeof(buf), P->t
|
|||||||
REG_set(VM_DATA, ul_int, vm_data)
|
REG_set(VM_DATA, ul_int, vm_data)
|
||||||
REG_set(VM_EXE, ul_int, vm_exe)
|
REG_set(VM_EXE, ul_int, vm_exe)
|
||||||
REG_set(VM_LIB, ul_int, vm_lib)
|
REG_set(VM_LIB, ul_int, vm_lib)
|
||||||
REG_set(VM_LOCK, ul_int, vm_lock)
|
|
||||||
REG_set(VM_RSS, ul_int, vm_rss)
|
REG_set(VM_RSS, ul_int, vm_rss)
|
||||||
REG_set(VM_RSS_ANON, ul_int, vm_rss_anon)
|
REG_set(VM_RSS_ANON, ul_int, vm_rss_anon)
|
||||||
REG_set(VM_RSS_FILE, ul_int, vm_rss_file)
|
REG_set(VM_RSS_FILE, ul_int, vm_rss_file)
|
||||||
@ -495,7 +488,6 @@ static struct {
|
|||||||
{ RS(VM_DATA), f_status, NULL, QS(ul_int), 0, -1 },
|
{ RS(VM_DATA), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
{ RS(VM_EXE), f_status, NULL, QS(ul_int), 0, -1 },
|
{ RS(VM_EXE), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
{ RS(VM_LIB), f_status, NULL, QS(ul_int), 0, -1 },
|
{ RS(VM_LIB), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
{ RS(VM_LOCK), f_status, NULL, QS(ul_int), 0, -1 },
|
|
||||||
{ RS(VM_RSS), f_status, NULL, QS(ul_int), 0, -1 },
|
{ RS(VM_RSS), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
{ RS(VM_RSS_ANON), f_status, NULL, QS(ul_int), 0, -1 },
|
{ RS(VM_RSS_ANON), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
{ RS(VM_RSS_FILE), f_status, NULL, QS(ul_int), 0, -1 },
|
{ RS(VM_RSS_FILE), f_status, NULL, QS(ul_int), 0, -1 },
|
||||||
@ -512,6 +504,9 @@ static struct {
|
|||||||
{ NULL, 0, NULL, NULL, 0, -1 }
|
{ NULL, 0, NULL, NULL, 0, -1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// next MUST be kept in sync with highest value enum
|
||||||
|
enum pids_item PROCPS_PIDS_logical_end = PROCPS_PIDS_WCHAN_NAME + 1;
|
||||||
|
|
||||||
#undef RS
|
#undef RS
|
||||||
#undef FF
|
#undef FF
|
||||||
#undef QS
|
#undef QS
|
||||||
@ -776,19 +771,17 @@ static inline void assign_results (
|
|||||||
|
|
||||||
|
|
||||||
static inline void cleanup_stack (
|
static inline void cleanup_stack (
|
||||||
struct pids_result *p,
|
struct pids_result *this)
|
||||||
int depth)
|
|
||||||
{
|
{
|
||||||
int i;
|
for (;;) {
|
||||||
|
enum pids_item item = this->item;
|
||||||
for (i = 0; i < depth; i++) {
|
if (item >= PROCPS_PIDS_logical_end)
|
||||||
if (p->item >= PROCPS_PIDS_logical_end)
|
|
||||||
break;
|
break;
|
||||||
if (Item_table[p->item].freefunc)
|
if (Item_table[item].freefunc)
|
||||||
Item_table[p->item].freefunc(p);
|
Item_table[item].freefunc(this);
|
||||||
if (p->item > PROCPS_PIDS_noop)
|
if (item > PROCPS_PIDS_noop)
|
||||||
p->result.ull_int = 0;
|
this->result.ull_int = 0;
|
||||||
++p;
|
++this;
|
||||||
}
|
}
|
||||||
} // end: cleanup_stack
|
} // end: cleanup_stack
|
||||||
|
|
||||||
@ -801,7 +794,7 @@ static inline void cleanup_stacks_all (
|
|||||||
|
|
||||||
while (ext) {
|
while (ext) {
|
||||||
for (i = 0; ext->stacks[i]; i++)
|
for (i = 0; ext->stacks[i]; i++)
|
||||||
cleanup_stack(ext->stacks[i]->head, info->maxitems);
|
cleanup_stack(ext->stacks[i]->head);
|
||||||
ext = ext->next;
|
ext = ext->next;
|
||||||
};
|
};
|
||||||
info->dirty_stacks = 0;
|
info->dirty_stacks = 0;
|
||||||
@ -835,52 +828,18 @@ static struct stacks_extent *extent_cut (
|
|||||||
} // end: extent_cut
|
} // end: extent_cut
|
||||||
|
|
||||||
|
|
||||||
static int extent_free (
|
static void extents_free_all (
|
||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info)
|
||||||
struct stacks_extent *ext)
|
|
||||||
{
|
{
|
||||||
if (extent_cut(info, ext)) {
|
struct stacks_extent *ext = info->extents;
|
||||||
|
|
||||||
|
while (ext) {
|
||||||
|
info->extents = ext->next;
|
||||||
free(ext);
|
free(ext);
|
||||||
return 0;
|
ext = info->extents;
|
||||||
}
|
};
|
||||||
return -1;
|
info->dirty_stacks = 0;
|
||||||
} // end: extent_free
|
} // end: extents_free_all
|
||||||
|
|
||||||
|
|
||||||
#ifdef FPRINT_STACKS
|
|
||||||
static void fprint_stacks (
|
|
||||||
void *stacks,
|
|
||||||
const char *who)
|
|
||||||
{
|
|
||||||
#include <stdio.h>
|
|
||||||
static int once = 0;
|
|
||||||
struct stacks_extent *ext = stacks;
|
|
||||||
int i, t, x, n = 0;
|
|
||||||
|
|
||||||
fprintf(stderr, " %s: called by '%s'\n", __func__, who);
|
|
||||||
fprintf(stderr, " %s: ext_numitems = %d, ext_numstacks = %d, extents = %p, next = %p\n", __func__, ext->ext_numitems, ext->ext_numstacks, ext, ext->next);
|
|
||||||
fprintf(stderr, " %s: stacks_extent results excluding the end-of-stack element ...\n", __func__);
|
|
||||||
for (x = 0; NULL != ext->stacks[x]; x++) {
|
|
||||||
struct pids_stack *h = ext->stacks[x];
|
|
||||||
struct pids_result *r = h->head;
|
|
||||||
fprintf(stderr, " %s: v[%03d] = %p, h = %p", __func__, x, h, r);
|
|
||||||
for (i = 0; r->item < PROCPS_PIDS_logical_end; i++, r++)
|
|
||||||
;
|
|
||||||
t = i + 1;
|
|
||||||
fprintf(stderr, " - found %d elements for stack %d\n", i, n);
|
|
||||||
++n;
|
|
||||||
}
|
|
||||||
if (!once) {
|
|
||||||
fprintf(stderr, " %s: found %d total stack(s), each %d bytes (including eos)\n", __func__, x, (int)(sizeof(struct pids_stack) + (sizeof(struct pids_result) * t)));
|
|
||||||
fprintf(stderr, " %s: sizeof(struct pids_stack) = %d\n", __func__, (int)sizeof(struct pids_stack));
|
|
||||||
fprintf(stderr, " %s: sizeof(struct pids_result) = %d\n", __func__, (int)sizeof(struct pids_result));
|
|
||||||
fprintf(stderr, " %s: sizeof(struct stacks_extent) = %d\n", __func__, (int)sizeof(struct stacks_extent));
|
|
||||||
once = 1;
|
|
||||||
}
|
|
||||||
fputc('\n', stderr);
|
|
||||||
return;
|
|
||||||
} // end: fprint_stacks
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static inline struct pids_result *itemize_stack (
|
static inline struct pids_result *itemize_stack (
|
||||||
@ -900,8 +859,23 @@ static inline struct pids_result *itemize_stack (
|
|||||||
} // end: itemize_stack
|
} // end: itemize_stack
|
||||||
|
|
||||||
|
|
||||||
|
static void itemize_stacks_all (
|
||||||
|
struct procps_pidsinfo *info)
|
||||||
|
{
|
||||||
|
struct stacks_extent *ext = info->extents;
|
||||||
|
|
||||||
|
while (ext) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; ext->stacks[i]; i++)
|
||||||
|
itemize_stack(ext->stacks[i]->head, info->curitems, info->items);
|
||||||
|
ext = ext->next;
|
||||||
|
};
|
||||||
|
info->dirty_stacks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline int items_check_failed (
|
static inline int items_check_failed (
|
||||||
int maxitems,
|
int numitems,
|
||||||
enum pids_item *items)
|
enum pids_item *items)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -914,10 +888,10 @@ static inline int items_check_failed (
|
|||||||
* if (procps_pids_new(&info, 3, PROCPS_PIDS_noop) < 0)
|
* if (procps_pids_new(&info, 3, PROCPS_PIDS_noop) < 0)
|
||||||
* ^~~~~~~~~~~~~~~~
|
* ^~~~~~~~~~~~~~~~
|
||||||
*/
|
*/
|
||||||
if (maxitems < 1
|
if (numitems < 1
|
||||||
|| (void *)items < (void *)0x8000) // twice as big as our largest enum
|
|| (void *)items < (void *)0x8000) // twice as big as our largest enum
|
||||||
return -1;
|
return -1;
|
||||||
for (i = 0; i < maxitems; i++) {
|
for (i = 0; i < numitems; i++) {
|
||||||
// a pids_item is currently unsigned, but we'll protect our future
|
// a pids_item is currently unsigned, but we'll protect our future
|
||||||
if (items[i] < 0)
|
if (items[i] < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -936,37 +910,36 @@ static inline void libflags_set (
|
|||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
memset (info->ref_counts, 0, sizeof(info->ref_counts));
|
memset (info->ref_counts, 0, sizeof(info->ref_counts));
|
||||||
info->flags = info->history_yes = 0;
|
info->oldflags = info->history_yes = 0;
|
||||||
for (i = 0; i < info->curitems; i++) {
|
for (i = 0; i < info->curitems; i++) {
|
||||||
if (((e = info->items[i])) >= PROCPS_PIDS_logical_end)
|
if (((e = info->items[i])) >= PROCPS_PIDS_logical_end)
|
||||||
break;
|
break;
|
||||||
info->flags |= Item_table[e].oldflags;
|
info->oldflags |= Item_table[e].oldflags;
|
||||||
info->history_yes |= Item_table[e].needhist;
|
info->history_yes |= Item_table[e].needhist;
|
||||||
n = Item_table[e].refcount;
|
n = Item_table[e].refcount;
|
||||||
if (n > -1) ++info->ref_counts[n];
|
if (n > -1) ++info->ref_counts[n];
|
||||||
}
|
}
|
||||||
if (info->flags & f_either) {
|
if (info->oldflags & f_either) {
|
||||||
if (!(info->flags & f_stat))
|
if (!(info->oldflags & f_stat))
|
||||||
info->flags |= f_status;
|
info->oldflags |= f_status;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} // end: libflags_set
|
} // end: libflags_set
|
||||||
|
|
||||||
|
|
||||||
static inline void oldproc_close (
|
static inline void oldproc_close (
|
||||||
struct procps_pidsinfo *info)
|
PROCTAB **this)
|
||||||
{
|
{
|
||||||
if (info->PT != NULL) {
|
if (*this != NULL) {
|
||||||
closeproc(info->PT);
|
closeproc(*this);
|
||||||
info->PT = NULL;
|
*this = NULL;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
} // end: oldproc_close
|
} // end: oldproc_close
|
||||||
|
|
||||||
|
|
||||||
static inline int oldproc_open (
|
static inline int oldproc_open (
|
||||||
struct procps_pidsinfo *info,
|
PROCTAB **this,
|
||||||
unsigned supp_flgs,
|
unsigned flags,
|
||||||
...)
|
...)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -974,12 +947,12 @@ static inline int oldproc_open (
|
|||||||
int *ids;
|
int *ids;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
if (info->PT == NULL) {
|
if (*this == NULL) {
|
||||||
va_start(vl, supp_flgs);
|
va_start(vl, flags);
|
||||||
ids = va_arg(vl, int*);
|
ids = va_arg(vl, int*);
|
||||||
if (info->flags & PROC_UID) num = va_arg(vl, int);
|
if (flags & PROC_UID) num = va_arg(vl, int);
|
||||||
va_end(vl);
|
va_end(vl);
|
||||||
if (NULL == (info->PT = openproc(info->flags | supp_flgs, ids, num)))
|
if (NULL == (*this = openproc(flags, ids, num)))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1044,27 +1017,27 @@ static struct stacks_extent *stacks_alloc (
|
|||||||
if (maxstacks < 1)
|
if (maxstacks < 1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
vect_size = sizeof(void *) * maxstacks; // address vectors themselves
|
vect_size = sizeof(void *) * maxstacks; // size of the addr vectors |
|
||||||
vect_size += sizeof(void *); // plus NULL delimiter
|
vect_size += sizeof(void *); // plus NULL addr delimiter |
|
||||||
head_size = sizeof(struct pids_stack); // a head struct
|
head_size = sizeof(struct pids_stack); // size of that head struct |
|
||||||
list_size = sizeof(struct pids_result) * info->maxitems; // a results stack
|
list_size = sizeof(struct pids_result) * info->maxitems; // any single results stack |
|
||||||
blob_size = sizeof(struct stacks_extent); // the extent anchor itself
|
blob_size = sizeof(struct stacks_extent); // the extent anchor itself |
|
||||||
blob_size += vect_size; // all vectors + delim
|
blob_size += vect_size; // plus room for addr vects |
|
||||||
blob_size += head_size * maxstacks; // all head structs
|
blob_size += head_size * maxstacks; // plus room for head thing |
|
||||||
blob_size += list_size * maxstacks; // all results stacks
|
blob_size += list_size * maxstacks; // plus room for our stacks |
|
||||||
|
|
||||||
/* note: all memory is allocated in a single blob, facilitating a later free().
|
/* note: all of our memory is allocated in a single blob, facilitating a later free(). |
|
||||||
as a minimum, it's important that the result structures themselves always be
|
as a minimum, it is important that the result structures themselves always be |
|
||||||
contiguous for each stack since they're accessed through relative position). */
|
contiguous for every stack since they are accessed through relative position. | */
|
||||||
if (NULL == (p_blob = calloc(1, blob_size)))
|
if (NULL == (p_blob = calloc(1, blob_size)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
p_blob->next = info->extents;
|
p_blob->next = info->extents; // push this extent onto... |
|
||||||
info->extents = p_blob;
|
info->extents = p_blob; // ...some existing extents |
|
||||||
p_blob->stacks = (void *)p_blob + sizeof(struct stacks_extent);
|
p_vect = (void *)p_blob + sizeof(struct stacks_extent); // prime our vector pointer |
|
||||||
p_vect = p_blob->stacks;
|
p_blob->stacks = p_vect; // set actual vectors start |
|
||||||
v_head = (void *)p_vect + vect_size;
|
v_head = (void *)p_vect + vect_size; // prime head pointer start |
|
||||||
v_list = v_head + (head_size * maxstacks);
|
v_list = v_head + (head_size * maxstacks); // prime our stacks pointer |
|
||||||
|
|
||||||
for (i = 0; i < maxstacks; i++) {
|
for (i = 0; i < maxstacks; i++) {
|
||||||
p_head = (struct pids_stack *)v_head;
|
p_head = (struct pids_stack *)v_head;
|
||||||
@ -1073,89 +1046,187 @@ static struct stacks_extent *stacks_alloc (
|
|||||||
v_list += list_size;
|
v_list += list_size;
|
||||||
v_head += head_size;
|
v_head += head_size;
|
||||||
}
|
}
|
||||||
p_blob->ext_numitems = info->maxitems;
|
|
||||||
p_blob->ext_numstacks = maxstacks;
|
p_blob->ext_numstacks = maxstacks;
|
||||||
#ifdef FPRINT_STACKS
|
|
||||||
fprint_stacks(p_blob, __func__);
|
|
||||||
#endif
|
|
||||||
return p_blob;
|
return p_blob;
|
||||||
} // end: stacks_alloc
|
} // end: stacks_alloc
|
||||||
|
|
||||||
|
|
||||||
static int stacks_dealloc (
|
|
||||||
struct procps_pidsinfo *info,
|
|
||||||
struct stacks_extent **these)
|
|
||||||
{
|
|
||||||
struct stacks_extent *ext;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (info == NULL || these == NULL)
|
|
||||||
return -EINVAL;
|
|
||||||
if ((*these)->stacks == NULL || (*these)->stacks[0] == NULL)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
ext = *these;
|
|
||||||
rc = extent_free(info, ext);
|
|
||||||
*these = NULL;
|
|
||||||
return rc;
|
|
||||||
} // end: stacks_dealloc
|
|
||||||
|
|
||||||
|
|
||||||
static int stacks_fetch (
|
static int stacks_fetch (
|
||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info)
|
||||||
struct fetch_support *this)
|
|
||||||
{
|
{
|
||||||
#define n_alloc this->n_alloc
|
#define n_alloc info->fetch.n_alloc
|
||||||
#define n_inuse this->n_inuse
|
#define n_inuse info->fetch.n_inuse
|
||||||
|
#define n_saved info->fetch.n_alloc_save
|
||||||
static proc_t task; // static for initial zeroes + later dynamic free(s)
|
static proc_t task; // static for initial zeroes + later dynamic free(s)
|
||||||
struct stacks_extent *ext;
|
struct stacks_extent *ext;
|
||||||
|
|
||||||
if (info == NULL || this == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// initialize stuff -----------------------------------
|
// initialize stuff -----------------------------------
|
||||||
if (!this->anchor) {
|
if (!info->fetch.anchor) {
|
||||||
if ((!(this->anchor = calloc(sizeof(void *), MEMORY_INCR)))
|
if (!(info->fetch.anchor = calloc(sizeof(void *), MEMORY_INCR)))
|
||||||
|| (!(this->summary.stacks = calloc(sizeof(void *), MEMORY_INCR)))
|
return -ENOMEM;
|
||||||
|| (!(ext = stacks_alloc(info, MEMORY_INCR))))
|
|
||||||
return -1;
|
|
||||||
memcpy(this->anchor, ext->stacks, sizeof(void *) * MEMORY_INCR);
|
|
||||||
n_alloc = MEMORY_INCR;
|
n_alloc = MEMORY_INCR;
|
||||||
}
|
}
|
||||||
if (info->dirty_stacks)
|
if (!info->extents) {
|
||||||
cleanup_stacks_all(info);
|
if (!(ext = stacks_alloc(info, n_alloc)))
|
||||||
|
return -ENOMEM;
|
||||||
|
memset(info->fetch.anchor, 0, sizeof(void *) * n_alloc);
|
||||||
|
memcpy(info->fetch.anchor, ext->stacks, sizeof(void *) * n_alloc);
|
||||||
|
itemize_stacks_all(info);
|
||||||
|
}
|
||||||
|
cleanup_stacks_all(info);
|
||||||
toggle_history(info);
|
toggle_history(info);
|
||||||
memset(&this->summary.counts, 0, sizeof(struct pids_counts));
|
memset(&info->fetch.summary.counts, 0, sizeof(struct pids_counts));
|
||||||
|
|
||||||
// iterate stuff --------------------------------------
|
// iterate stuff --------------------------------------
|
||||||
n_inuse = 0;
|
n_inuse = 0;
|
||||||
while (info->read_something(info->PT, &task)) {
|
while (info->read_something(info->PT, &task)) {
|
||||||
if (!(n_inuse < n_alloc)) {
|
if (!(n_inuse < n_alloc)) {
|
||||||
n_alloc += MEMORY_INCR;
|
n_alloc += MEMORY_INCR;
|
||||||
if ((!(this->anchor = realloc(this->anchor, sizeof(void *) * n_alloc)))
|
if ((!(info->fetch.anchor = realloc(info->fetch.anchor, sizeof(void *) * n_alloc)))
|
||||||
|| (!(ext = stacks_alloc(info, MEMORY_INCR))))
|
|| (!(ext = stacks_alloc(info, MEMORY_INCR))))
|
||||||
return -1;
|
return -1;
|
||||||
memcpy(this->anchor + n_inuse, ext->stacks, sizeof(void *) * MEMORY_INCR);
|
memcpy(info->fetch.anchor + n_inuse, ext->stacks, sizeof(void *) * MEMORY_INCR);
|
||||||
}
|
}
|
||||||
if (!proc_tally(info, &this->summary.counts, &task))
|
if (!proc_tally(info, &info->fetch.summary.counts, &task))
|
||||||
return -1;
|
return -1;
|
||||||
assign_results(info, this->anchor[n_inuse++], &task);
|
assign_results(info, info->fetch.anchor[n_inuse++], &task);
|
||||||
}
|
}
|
||||||
|
|
||||||
// finalize stuff -------------------------------------
|
// finalize stuff -------------------------------------
|
||||||
if (this->n_alloc_save != n_alloc
|
if (n_saved < n_alloc + 1) {
|
||||||
&& !(this->summary.stacks = realloc(this->summary.stacks, sizeof(void *) * n_alloc)))
|
n_saved = n_alloc + 1;
|
||||||
return -1;
|
if (!(info->fetch.summary.stacks = realloc(info->fetch.summary.stacks, sizeof(void *) * n_saved)))
|
||||||
memcpy(this->summary.stacks, this->anchor, sizeof(void *) * n_alloc);
|
return -1;
|
||||||
this->n_alloc_save = n_alloc;
|
}
|
||||||
|
memcpy(info->fetch.summary.stacks, info->fetch.anchor, sizeof(void *) * n_inuse);
|
||||||
|
info->fetch.summary.stacks[n_inuse] = NULL;
|
||||||
return n_inuse; // callers beware, this might be zero !
|
return n_inuse; // callers beware, this might be zero !
|
||||||
#undef n_alloc
|
#undef n_alloc
|
||||||
#undef n_inuse
|
#undef n_inuse
|
||||||
|
#undef n_saved
|
||||||
} // end: stacks_fetch
|
} // end: stacks_fetch
|
||||||
|
|
||||||
|
|
||||||
// ___ Public Functions |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
// ___ Public Functions |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||
|
|
||||||
|
// --- standard required functions --------------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
* procps_pids_new():
|
||||||
|
*
|
||||||
|
* @info: location of returned new structure
|
||||||
|
*
|
||||||
|
* Returns: 0 on success <0 on failure
|
||||||
|
*/
|
||||||
|
PROCPS_EXPORT int procps_pids_new (
|
||||||
|
struct procps_pidsinfo **info,
|
||||||
|
enum pids_item *items,
|
||||||
|
int numitems)
|
||||||
|
{
|
||||||
|
struct procps_pidsinfo *p;
|
||||||
|
double uptime_secs;
|
||||||
|
int pgsz;
|
||||||
|
|
||||||
|
if (info == NULL || *info != NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!(p = calloc(1, sizeof(struct procps_pidsinfo))))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* if we're without items or numitems, a later call to
|
||||||
|
procps_pids_reset() will become mandatory */
|
||||||
|
if (items && numitems) {
|
||||||
|
if (items_check_failed(numitems, items))
|
||||||
|
return -EINVAL;
|
||||||
|
// allow for our PROCPS_PIDS_logical_end
|
||||||
|
p->maxitems = numitems + 1;
|
||||||
|
if (!(p->items = calloc(p->maxitems, sizeof(enum pids_item))))
|
||||||
|
return -ENOMEM;
|
||||||
|
memcpy(p->items, items, sizeof(enum pids_item) * numitems);
|
||||||
|
p->items[numitems] = PROCPS_PIDS_logical_end;
|
||||||
|
p->curitems = p->maxitems;
|
||||||
|
libflags_set(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(p->hist = calloc(MEMORY_INCR, sizeof(struct history_info))))
|
||||||
|
return -ENOMEM;
|
||||||
|
config_history(p);
|
||||||
|
|
||||||
|
pgsz = getpagesize();
|
||||||
|
while (pgsz > 1024) { pgsz >>= 1; p->pgs2k_shift++; }
|
||||||
|
|
||||||
|
p->hertz = procps_hertz_get();
|
||||||
|
procps_uptime(&uptime_secs, NULL);
|
||||||
|
p->boot_seconds = uptime_secs;
|
||||||
|
|
||||||
|
p->refcount = 1;
|
||||||
|
*info = p;
|
||||||
|
return 0;
|
||||||
|
} // end: procps_pids_new
|
||||||
|
|
||||||
|
|
||||||
|
PROCPS_EXPORT int procps_pids_ref (
|
||||||
|
struct procps_pidsinfo *info)
|
||||||
|
{
|
||||||
|
if (info == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
info->refcount++;
|
||||||
|
return info->refcount;
|
||||||
|
} // end: procps_pids_ref
|
||||||
|
|
||||||
|
|
||||||
|
PROCPS_EXPORT int procps_pids_unref (
|
||||||
|
struct procps_pidsinfo **info)
|
||||||
|
{
|
||||||
|
if (info == NULL || *info == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
(*info)->refcount--;
|
||||||
|
if ((*info)->refcount == 0) {
|
||||||
|
#ifdef UNREF_RPTHASH
|
||||||
|
unref_rpthash(*info);
|
||||||
|
#endif
|
||||||
|
if ((*info)->extents) {
|
||||||
|
cleanup_stacks_all(*info);
|
||||||
|
do {
|
||||||
|
struct stacks_extent *p = (*info)->extents;
|
||||||
|
(*info)->extents = (*info)->extents->next;
|
||||||
|
free(p);
|
||||||
|
} while ((*info)->extents);
|
||||||
|
}
|
||||||
|
if ((*info)->otherexts) {
|
||||||
|
struct stacks_extent *nextext, *ext = (*info)->otherexts;
|
||||||
|
while (ext) {
|
||||||
|
nextext = ext->next;
|
||||||
|
cleanup_stack(ext->stacks[0]->head);
|
||||||
|
free(ext);
|
||||||
|
ext = nextext;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if ((*info)->fetch.anchor)
|
||||||
|
free((*info)->fetch.anchor);
|
||||||
|
if ((*info)->fetch.summary.stacks)
|
||||||
|
free((*info)->fetch.summary.stacks);
|
||||||
|
|
||||||
|
if ((*info)->items)
|
||||||
|
free((*info)->items);
|
||||||
|
if ((*info)->hist) {
|
||||||
|
free((*info)->hist->PHist_sav);
|
||||||
|
free((*info)->hist->PHist_new);
|
||||||
|
free((*info)->hist);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(*info);
|
||||||
|
*info = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (*info)->refcount;
|
||||||
|
} // end: procps_pids_unref
|
||||||
|
|
||||||
|
|
||||||
|
// --- variable interface functions -------------------------------------------
|
||||||
|
|
||||||
PROCPS_EXPORT struct pids_stack *fatal_proc_unmounted (
|
PROCPS_EXPORT struct pids_stack *fatal_proc_unmounted (
|
||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info,
|
||||||
int return_self)
|
int return_self)
|
||||||
@ -1182,106 +1253,46 @@ PROCPS_EXPORT struct pids_stack *fatal_proc_unmounted (
|
|||||||
} // end: fatal_proc_unmounted
|
} // end: fatal_proc_unmounted
|
||||||
|
|
||||||
|
|
||||||
/*
|
PROCPS_EXPORT struct pids_stack *procps_pids_get (
|
||||||
* procps_pids_new():
|
struct procps_pidsinfo *info,
|
||||||
*
|
enum pids_fetch_type which)
|
||||||
* @info: location of returned new structure
|
|
||||||
*
|
|
||||||
* Returns: 0 on success <0 on failure
|
|
||||||
*/
|
|
||||||
PROCPS_EXPORT int procps_pids_new (
|
|
||||||
struct procps_pidsinfo **info,
|
|
||||||
int maxitems,
|
|
||||||
enum pids_item *items)
|
|
||||||
{
|
|
||||||
struct procps_pidsinfo *p;
|
|
||||||
double uptime_secs;
|
|
||||||
int pgsz;
|
|
||||||
|
|
||||||
if (info == NULL || *info != NULL)
|
|
||||||
return -EINVAL;
|
|
||||||
if (items_check_failed(maxitems, items))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (!(p = calloc(1, sizeof(struct procps_pidsinfo))))
|
|
||||||
return -ENOMEM;
|
|
||||||
// allow for our PROCPS_PIDS_logical_end
|
|
||||||
if (!(p->items = calloc((maxitems + 1), sizeof(enum pids_item)))) {
|
|
||||||
free(p);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
if (!(p->hist = calloc((maxitems + 1), sizeof(struct history_info)))) {
|
|
||||||
free(p->items);
|
|
||||||
free(p);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(p->items, items, sizeof(enum pids_item) * maxitems);
|
|
||||||
p->items[maxitems] = PROCPS_PIDS_logical_end;
|
|
||||||
p->curitems = p->maxitems = maxitems + 1;
|
|
||||||
libflags_set(p);
|
|
||||||
|
|
||||||
pgsz = getpagesize();
|
|
||||||
while (pgsz > 1024) { pgsz >>= 1; p->pgs2k_shift++; }
|
|
||||||
|
|
||||||
config_history(p);
|
|
||||||
|
|
||||||
p->hertz = procps_hertz_get();
|
|
||||||
procps_uptime(&uptime_secs, NULL);
|
|
||||||
p->boot_seconds = uptime_secs;
|
|
||||||
|
|
||||||
p->refcount = 1;
|
|
||||||
*info = p;
|
|
||||||
return 0;
|
|
||||||
} // end: procps_pids_new
|
|
||||||
|
|
||||||
|
|
||||||
PROCPS_EXPORT struct pids_stack *procps_pids_read_next (
|
|
||||||
struct procps_pidsinfo *info)
|
|
||||||
{
|
{
|
||||||
static proc_t task; // static for initial zeroes + later dynamic free(s)
|
static proc_t task; // static for initial zeroes + later dynamic free(s)
|
||||||
|
|
||||||
if (info == NULL || ! READS_BEGUN)
|
if (info == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (info->dirty_stacks) {
|
if (!info->curitems)
|
||||||
cleanup_stack(info->read->stacks[0]->head, info->maxitems);
|
return NULL;
|
||||||
info->dirty_stacks = 0;
|
if (which != PROCPS_FETCH_TASKS_ONLY && which != PROCPS_FETCH_THREADS_TOO)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fresh_start:
|
||||||
|
if (!info->get_ext) {
|
||||||
|
if (!(info->get_ext = stacks_alloc(info, 1)))
|
||||||
|
return NULL;
|
||||||
|
if (!oldproc_open(&info->get_PT, info->oldflags))
|
||||||
|
return NULL;
|
||||||
|
info->get_type = which;
|
||||||
|
info->read_something = which ? readeither : readproc;
|
||||||
}
|
}
|
||||||
if (NULL == info->read_something(info->PT, &task))
|
|
||||||
|
if (info->get_type != which) {
|
||||||
|
oldproc_close(&info->get_PT);
|
||||||
|
cleanup_stack(info->get_ext->stacks[0]->head);
|
||||||
|
if (extent_cut(info, info->get_ext))
|
||||||
|
free(info->get_ext);
|
||||||
|
info->get_ext = NULL;
|
||||||
|
goto fresh_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_stack(info->get_ext->stacks[0]->head);
|
||||||
|
|
||||||
|
if (NULL == info->read_something(info->get_PT, &task))
|
||||||
return NULL;
|
return NULL;
|
||||||
assign_results(info, info->read->stacks[0], &task);
|
assign_results(info, info->get_ext->stacks[0], &task);
|
||||||
return info->read->stacks[0];
|
|
||||||
} // end: procps_pids_read_next
|
|
||||||
|
|
||||||
|
return info->get_ext->stacks[0];
|
||||||
PROCPS_EXPORT int procps_pids_read_open (
|
} // end: procps_pids_get
|
||||||
struct procps_pidsinfo *info,
|
|
||||||
enum pids_reap_type which)
|
|
||||||
{
|
|
||||||
if (info == NULL || READS_BEGUN)
|
|
||||||
return -EINVAL;
|
|
||||||
if (!info->maxitems && !info->curitems)
|
|
||||||
return -EINVAL;
|
|
||||||
if (which != PROCPS_REAP_TASKS_ONLY && which != PROCPS_REAP_THREADS_TOO)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (!(info->read = stacks_alloc(info, 1)))
|
|
||||||
return -ENOMEM;
|
|
||||||
if (!oldproc_open(info, 0))
|
|
||||||
return -1;
|
|
||||||
info->read_something = which ? readeither : readproc;
|
|
||||||
return 0;
|
|
||||||
} // end: procps_pids_read_open
|
|
||||||
|
|
||||||
|
|
||||||
PROCPS_EXPORT int procps_pids_read_shut (
|
|
||||||
struct procps_pidsinfo *info)
|
|
||||||
{
|
|
||||||
if (info == NULL || ! READS_BEGUN)
|
|
||||||
return -EINVAL;
|
|
||||||
oldproc_close(info);
|
|
||||||
return stacks_dealloc(info, &info->read);
|
|
||||||
} // end: procps_pids_read_shut
|
|
||||||
|
|
||||||
|
|
||||||
/* procps_pids_reap():
|
/* procps_pids_reap():
|
||||||
@ -1289,86 +1300,70 @@ PROCPS_EXPORT int procps_pids_read_shut (
|
|||||||
* Harvest all the available tasks/threads and provide the result
|
* Harvest all the available tasks/threads and provide the result
|
||||||
* stacks along with a summary of the information gathered.
|
* stacks along with a summary of the information gathered.
|
||||||
*
|
*
|
||||||
* Returns: pointer to a pids_reap struct on success, NULL on error.
|
* Returns: pointer to a pids_fetch struct on success, NULL on error.
|
||||||
*/
|
*/
|
||||||
PROCPS_EXPORT struct pids_reap *procps_pids_reap (
|
PROCPS_EXPORT struct pids_fetch *procps_pids_reap (
|
||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info,
|
||||||
enum pids_reap_type which)
|
enum pids_fetch_type which)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (info == NULL || READS_BEGUN)
|
if (info == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!info->maxitems && !info->curitems)
|
if (!info->curitems)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (which != PROCPS_REAP_TASKS_ONLY && which != PROCPS_REAP_THREADS_TOO)
|
if (which != PROCPS_FETCH_TASKS_ONLY && which != PROCPS_FETCH_THREADS_TOO)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!oldproc_open(info, 0))
|
if (!oldproc_open(&info->PT, info->oldflags))
|
||||||
return NULL;
|
return NULL;
|
||||||
info->read_something = which ? readeither : readproc;
|
info->read_something = which ? readeither : readproc;
|
||||||
|
|
||||||
rc = stacks_fetch(info, &info->reap);
|
rc = stacks_fetch(info);
|
||||||
|
|
||||||
oldproc_close(info);
|
oldproc_close(&info->PT);
|
||||||
// we better have found at least 1 pid
|
// we better have found at least 1 pid
|
||||||
return (rc > 0) ? &info->reap.summary : NULL;
|
return (rc > 0) ? &info->fetch.summary : NULL;
|
||||||
} // end: procps_pids_reap
|
} // end: procps_pids_reap
|
||||||
|
|
||||||
|
|
||||||
PROCPS_EXPORT int procps_pids_ref (
|
|
||||||
struct procps_pidsinfo *info)
|
|
||||||
{
|
|
||||||
if (info == NULL)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
info->refcount++;
|
|
||||||
return info->refcount;
|
|
||||||
} // end: procps_pids_ref
|
|
||||||
|
|
||||||
|
|
||||||
PROCPS_EXPORT int procps_pids_reset (
|
PROCPS_EXPORT int procps_pids_reset (
|
||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info,
|
||||||
int newmaxitems,
|
enum pids_item *newitems,
|
||||||
enum pids_item *newitems)
|
int newnumitems)
|
||||||
{
|
{
|
||||||
struct stacks_extent *ext;
|
if (info == NULL || newitems == NULL)
|
||||||
int i;
|
|
||||||
|
|
||||||
if (info == NULL)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
/* disallow (for now?) absolute increases in stacks size
|
if (items_check_failed(newnumitems, newitems))
|
||||||
( users must 'unref' and then 'new' to achieve that ) */
|
|
||||||
if (newmaxitems + 1 > info->maxitems)
|
|
||||||
return -EINVAL;
|
|
||||||
if (items_check_failed(newmaxitems, newitems))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* shame on this caller, they didn't change anything. and unless they have
|
/* shame on this caller, they didn't change anything. and unless they have
|
||||||
altered the depth of the stacks we're not gonna change anything either! */
|
altered the depth of the stacks we're not gonna change anything either! */
|
||||||
if (info->curitems == newmaxitems + 1
|
if (info->curitems == newnumitems + 1
|
||||||
&& !memcmp(info->items, newitems, sizeof(enum pids_item) * newmaxitems))
|
&& !memcmp(info->items, newitems, sizeof(enum pids_item) * newnumitems))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (info->maxitems < newnumitems + 1) {
|
||||||
|
if (info->dirty_stacks)
|
||||||
|
cleanup_stacks_all(info);
|
||||||
|
// allow for our PROCPS_PIDS_logical_end
|
||||||
|
info->maxitems = newnumitems + 1;
|
||||||
|
if (!(info->items = realloc(info->items, sizeof(enum pids_item) * info->maxitems)))
|
||||||
|
return -ENOMEM;
|
||||||
|
extents_free_all(info);
|
||||||
|
}
|
||||||
|
|
||||||
if (info->dirty_stacks)
|
if (info->dirty_stacks)
|
||||||
cleanup_stacks_all(info);
|
cleanup_stacks_all(info);
|
||||||
|
|
||||||
memcpy(info->items, newitems, sizeof(enum pids_item) * newmaxitems);
|
memcpy(info->items, newitems, sizeof(enum pids_item) * newnumitems);
|
||||||
info->items[newmaxitems] = PROCPS_PIDS_logical_end;
|
info->items[newnumitems] = PROCPS_PIDS_logical_end;
|
||||||
// account for above PROCPS_PIDS_logical_end
|
// account for above PROCPS_PIDS_logical_end
|
||||||
info->curitems = newmaxitems + 1;
|
info->curitems = newnumitems + 1;
|
||||||
|
|
||||||
ext = info->extents;
|
|
||||||
while (ext) {
|
|
||||||
for (i = 0; ext->stacks[i]; i++)
|
|
||||||
itemize_stack(ext->stacks[i]->head, info->curitems, info->items);
|
|
||||||
#ifdef FPRINT_STACKS
|
|
||||||
fprint_stacks(ext, __func__);
|
|
||||||
#endif
|
|
||||||
ext = ext->next;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
itemize_stacks_all(info);
|
||||||
libflags_set(info);
|
libflags_set(info);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} // end: procps_pids_reset
|
} // end: procps_pids_reset
|
||||||
|
|
||||||
@ -1378,37 +1373,37 @@ PROCPS_EXPORT int procps_pids_reset (
|
|||||||
* Harvest any processes matching the specified PID or UID and provide the
|
* Harvest any processes matching the specified PID or UID and provide the
|
||||||
* result stacks along with a summary of the information gathered.
|
* result stacks along with a summary of the information gathered.
|
||||||
*
|
*
|
||||||
* Returns: pointer to a pids_reap struct on success, NULL on error.
|
* Returns: pointer to a pids_fetch struct on success, NULL on error.
|
||||||
*/
|
*/
|
||||||
PROCPS_EXPORT struct pids_reap *procps_pids_select (
|
PROCPS_EXPORT struct pids_fetch *procps_pids_select (
|
||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info,
|
||||||
unsigned *these,
|
unsigned *these,
|
||||||
int maxthese,
|
int numthese,
|
||||||
enum pids_select_type which)
|
enum pids_select_type which)
|
||||||
{
|
{
|
||||||
unsigned ids[FILL_ID_MAX + 1];
|
unsigned ids[FILL_ID_MAX + 1];
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (info == NULL || these == NULL || READS_BEGUN)
|
if (info == NULL || these == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (maxthese < 1 || maxthese > FILL_ID_MAX)
|
if (numthese < 1 || numthese > FILL_ID_MAX)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (which != PROCPS_SELECT_PID && which != PROCPS_SELECT_UID)
|
if (which != PROCPS_SELECT_PID && which != PROCPS_SELECT_UID)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// this zero delimiter is really only needed with PROCPS_SELECT_PID
|
// this zero delimiter is really only needed with PROCPS_SELECT_PID
|
||||||
memcpy(ids, these, sizeof(unsigned) * maxthese);
|
memcpy(ids, these, sizeof(unsigned) * numthese);
|
||||||
ids[maxthese] = 0;
|
ids[numthese] = 0;
|
||||||
|
|
||||||
if (!oldproc_open(info, which, ids, maxthese))
|
if (!oldproc_open(&info->PT, (info->oldflags | which), ids, numthese))
|
||||||
return NULL;
|
return NULL;
|
||||||
info->read_something = readproc;
|
info->read_something = readproc;
|
||||||
|
|
||||||
rc = stacks_fetch(info, &info->select);
|
rc = stacks_fetch(info);
|
||||||
|
|
||||||
oldproc_close(info);
|
oldproc_close(&info->PT);
|
||||||
// no guarantee any pids/uids were found
|
// no guarantee any pids/uids were found
|
||||||
return (rc > -1) ? &info->select.summary : NULL;
|
return (rc > -1) ? &info->fetch.summary : NULL;
|
||||||
} // end: procps_pids_select
|
} // end: procps_pids_select
|
||||||
|
|
||||||
|
|
||||||
@ -1426,7 +1421,7 @@ PROCPS_EXPORT struct pids_stack **procps_pids_sort (
|
|||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info,
|
||||||
struct pids_stack *stacks[],
|
struct pids_stack *stacks[],
|
||||||
int numstacked,
|
int numstacked,
|
||||||
enum pids_item sort,
|
enum pids_item sortitem,
|
||||||
enum pids_sort_order order)
|
enum pids_sort_order order)
|
||||||
{
|
{
|
||||||
struct sort_parms parms;
|
struct sort_parms parms;
|
||||||
@ -1436,7 +1431,7 @@ PROCPS_EXPORT struct pids_stack **procps_pids_sort (
|
|||||||
if (info == NULL || stacks == NULL)
|
if (info == NULL || stacks == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
// a pids_item is currently unsigned, but we'll protect our future
|
// a pids_item is currently unsigned, but we'll protect our future
|
||||||
if (sort < 0 || sort >= PROCPS_PIDS_logical_end)
|
if (sortitem < 0 || sortitem >= PROCPS_PIDS_logical_end)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (order != PROCPS_SORT_ASCEND && order != PROCPS_SORT_DESCEND)
|
if (order != PROCPS_SORT_ASCEND && order != PROCPS_SORT_DESCEND)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1446,7 +1441,7 @@ PROCPS_EXPORT struct pids_stack **procps_pids_sort (
|
|||||||
offset = 0;
|
offset = 0;
|
||||||
p = stacks[0]->head;
|
p = stacks[0]->head;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (p->item == sort)
|
if (p->item == sortitem)
|
||||||
break;
|
break;
|
||||||
++offset;
|
++offset;
|
||||||
if (offset >= info->curitems)
|
if (offset >= info->curitems)
|
||||||
@ -1461,54 +1456,3 @@ PROCPS_EXPORT struct pids_stack **procps_pids_sort (
|
|||||||
qsort_r(stacks, numstacked, sizeof(void *), (QSR_t)Item_table[p->item].sortfunc, &parms);
|
qsort_r(stacks, numstacked, sizeof(void *), (QSR_t)Item_table[p->item].sortfunc, &parms);
|
||||||
return stacks;
|
return stacks;
|
||||||
} // end: procps_pids_sort
|
} // end: procps_pids_sort
|
||||||
|
|
||||||
|
|
||||||
PROCPS_EXPORT int procps_pids_unref (
|
|
||||||
struct procps_pidsinfo **info)
|
|
||||||
{
|
|
||||||
if (info == NULL || *info == NULL)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
(*info)->refcount--;
|
|
||||||
if ((*info)->refcount == 0) {
|
|
||||||
#ifdef UNREF_RPTHASH
|
|
||||||
unref_rpthash(*info);
|
|
||||||
#endif
|
|
||||||
if ((*info)->extents) {
|
|
||||||
cleanup_stacks_all(*info);
|
|
||||||
do {
|
|
||||||
struct stacks_extent *p = (*info)->extents;
|
|
||||||
(*info)->extents = (*info)->extents->next;
|
|
||||||
free(p);
|
|
||||||
} while ((*info)->extents);
|
|
||||||
}
|
|
||||||
if ((*info)->otherexts) {
|
|
||||||
struct stacks_extent *nextext, *ext = (*info)->otherexts;
|
|
||||||
while (ext) {
|
|
||||||
nextext = ext->next;
|
|
||||||
cleanup_stack(ext->stacks[0]->head, ext->ext_numitems);
|
|
||||||
free(ext);
|
|
||||||
ext = nextext;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if ((*info)->reap.anchor)
|
|
||||||
free((*info)->reap.anchor);
|
|
||||||
if ((*info)->reap.summary.stacks)
|
|
||||||
free((*info)->reap.summary.stacks);
|
|
||||||
if ((*info)->select.anchor)
|
|
||||||
free((*info)->select.anchor);
|
|
||||||
if ((*info)->select.summary.stacks)
|
|
||||||
free((*info)->select.summary.stacks);
|
|
||||||
if ((*info)->items)
|
|
||||||
free((*info)->items);
|
|
||||||
if ((*info)->hist) {
|
|
||||||
free((*info)->hist->PHist_sav);
|
|
||||||
free((*info)->hist->PHist_new);
|
|
||||||
free((*info)->hist);
|
|
||||||
}
|
|
||||||
free(*info);
|
|
||||||
*info = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (*info)->refcount;
|
|
||||||
} // end: procps_pids_unref
|
|
||||||
|
51
proc/pids.h
51
proc/pids.h
@ -133,7 +133,6 @@ enum pids_item {
|
|||||||
PROCPS_PIDS_VM_DATA, // ul_int
|
PROCPS_PIDS_VM_DATA, // ul_int
|
||||||
PROCPS_PIDS_VM_EXE, // ul_int
|
PROCPS_PIDS_VM_EXE, // ul_int
|
||||||
PROCPS_PIDS_VM_LIB, // ul_int
|
PROCPS_PIDS_VM_LIB, // ul_int
|
||||||
PROCPS_PIDS_VM_LOCK, // ul_int
|
|
||||||
PROCPS_PIDS_VM_RSS, // ul_int
|
PROCPS_PIDS_VM_RSS, // ul_int
|
||||||
PROCPS_PIDS_VM_RSS_ANON, // ul_int
|
PROCPS_PIDS_VM_RSS_ANON, // ul_int
|
||||||
PROCPS_PIDS_VM_RSS_FILE, // ul_int
|
PROCPS_PIDS_VM_RSS_FILE, // ul_int
|
||||||
@ -148,16 +147,16 @@ enum pids_item {
|
|||||||
PROCPS_PIDS_WCHAN_NAME, // str
|
PROCPS_PIDS_WCHAN_NAME, // str
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum pids_fetch_type {
|
||||||
|
PROCPS_FETCH_TASKS_ONLY,
|
||||||
|
PROCPS_FETCH_THREADS_TOO
|
||||||
|
};
|
||||||
|
|
||||||
enum pids_select_type {
|
enum pids_select_type {
|
||||||
PROCPS_SELECT_PID = 0x1000,
|
PROCPS_SELECT_PID = 0x1000,
|
||||||
PROCPS_SELECT_UID = 0x4000
|
PROCPS_SELECT_UID = 0x4000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum pids_reap_type {
|
|
||||||
PROCPS_REAP_TASKS_ONLY = 0,
|
|
||||||
PROCPS_REAP_THREADS_TOO = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum pids_sort_order {
|
enum pids_sort_order {
|
||||||
PROCPS_SORT_ASCEND = +1,
|
PROCPS_SORT_ASCEND = +1,
|
||||||
PROCPS_SORT_DESCEND = -1
|
PROCPS_SORT_DESCEND = -1
|
||||||
@ -189,7 +188,7 @@ struct pids_counts {
|
|||||||
int running, sleeping, stopped, zombied;
|
int running, sleeping, stopped, zombied;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pids_reap {
|
struct pids_fetch {
|
||||||
struct pids_stack **stacks;
|
struct pids_stack **stacks;
|
||||||
struct pids_counts counts;
|
struct pids_counts counts;
|
||||||
};
|
};
|
||||||
@ -199,52 +198,40 @@ struct pids_reap {
|
|||||||
stack -> head [ rel_enum ] . result . type
|
stack -> head [ rel_enum ] . result . type
|
||||||
|
|
||||||
|
|
||||||
|
int procps_pids_new (struct procps_pidsinfo **info, enum pids_item *items, int numitems);
|
||||||
|
int procps_pids_ref (struct procps_pidsinfo *info);
|
||||||
|
int procps_pids_unref (struct procps_pidsinfo **info);
|
||||||
|
|
||||||
struct pids_stack *fatal_proc_unmounted (
|
struct pids_stack *fatal_proc_unmounted (
|
||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info,
|
||||||
int return_self);
|
int return_self);
|
||||||
|
|
||||||
int procps_pids_new (
|
struct pids_stack *procps_pids_get (
|
||||||
struct procps_pidsinfo **info,
|
|
||||||
int maxitems,
|
|
||||||
enum pids_item *items);
|
|
||||||
|
|
||||||
struct pids_stack *procps_pids_read_next (
|
|
||||||
struct procps_pidsinfo *info);
|
|
||||||
|
|
||||||
int procps_pids_read_open (
|
|
||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info,
|
||||||
enum pids_reap_type which);
|
enum pids_fetch_type which);
|
||||||
|
|
||||||
int procps_pids_read_shut (
|
struct pids_fetch *procps_pids_reap (
|
||||||
struct procps_pidsinfo *info);
|
|
||||||
|
|
||||||
struct pids_reap *procps_pids_reap (
|
|
||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info,
|
||||||
enum pids_reap_type which);
|
enum pids_fetch_type which);
|
||||||
|
|
||||||
int procps_pids_ref (
|
|
||||||
struct procps_pidsinfo *info);
|
|
||||||
|
|
||||||
int procps_pids_reset (
|
int procps_pids_reset (
|
||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info,
|
||||||
int newmaxitems,
|
enum pids_item *newitems,
|
||||||
enum pids_item *newitems);
|
int newnumitems);
|
||||||
|
|
||||||
struct pids_reap *procps_pids_select (
|
struct pids_fetch *procps_pids_select (
|
||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info,
|
||||||
unsigned *these,
|
unsigned *these,
|
||||||
int maxthese,
|
int numthese,
|
||||||
enum pids_select_type which);
|
enum pids_select_type which);
|
||||||
|
|
||||||
struct pids_stack **procps_pids_sort (
|
struct pids_stack **procps_pids_sort (
|
||||||
struct procps_pidsinfo *info,
|
struct procps_pidsinfo *info,
|
||||||
struct pids_stack *stacks[],
|
struct pids_stack *stacks[],
|
||||||
int numstacked,
|
int numstacked,
|
||||||
enum pids_item sort,
|
enum pids_item sortitem,
|
||||||
enum pids_sort_order order);
|
enum pids_sort_order order);
|
||||||
|
|
||||||
int procps_pids_unref (
|
|
||||||
struct procps_pidsinfo **info);
|
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user