sorted threads might work
This commit is contained in:
parent
e180e4875f
commit
7dfe80961a
@ -558,6 +558,7 @@ static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restric
|
|||||||
static char sbuf[1024]; // buffer for stat,statm
|
static char sbuf[1024]; // buffer for stat,statm
|
||||||
unsigned flags = PT->flags;
|
unsigned flags = PT->flags;
|
||||||
|
|
||||||
|
//printf("hhh\n");
|
||||||
if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */
|
if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */
|
||||||
goto next_task;
|
goto next_task;
|
||||||
|
|
||||||
@ -567,6 +568,7 @@ static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restric
|
|||||||
t->euid = sb.st_uid; /* need a way to get real uid */
|
t->euid = sb.st_uid; /* need a way to get real uid */
|
||||||
t->egid = sb.st_gid; /* need a way to get real gid */
|
t->egid = sb.st_gid; /* need a way to get real gid */
|
||||||
|
|
||||||
|
//printf("iii\n");
|
||||||
if (flags & PROC_FILLSTAT) { /* read, parse /proc/#/stat */
|
if (flags & PROC_FILLSTAT) { /* read, parse /proc/#/stat */
|
||||||
if (unlikely( file2str(path, "stat", sbuf, sizeof sbuf) == -1 ))
|
if (unlikely( file2str(path, "stat", sbuf, sizeof sbuf) == -1 ))
|
||||||
goto next_task; /* error reading /proc/#/stat */
|
goto next_task; /* error reading /proc/#/stat */
|
||||||
@ -659,12 +661,15 @@ static int simple_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p)
|
|||||||
// Return non-zero on success.
|
// Return non-zero on success.
|
||||||
static int simple_nexttid(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict const t, char *restrict const path) {
|
static int simple_nexttid(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict const t, char *restrict const path) {
|
||||||
static struct direct *ent; /* dirent handle */
|
static struct direct *ent; /* dirent handle */
|
||||||
(void)p;
|
if(PT->taskdir_user != p->tgid){
|
||||||
if(!PT->taskdir){
|
if(PT->taskdir){
|
||||||
|
closedir(PT->taskdir);
|
||||||
|
}
|
||||||
// use "path" as some tmp space
|
// use "path" as some tmp space
|
||||||
snprintf(path, PROCPATHLEN, "%s/task", PT->path);
|
snprintf(path, PROCPATHLEN, "%s/task", PT->path);
|
||||||
PT->taskdir = opendir(path);
|
PT->taskdir = opendir(path);
|
||||||
if(!PT->taskdir) return 0;
|
if(!PT->taskdir) return 0;
|
||||||
|
PT->taskdir_user = p->tgid;
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ent = readdir(PT->taskdir);
|
ent = readdir(PT->taskdir);
|
||||||
@ -761,10 +766,11 @@ proc_t* readproc(PROCTAB *restrict const PT, proc_t *restrict p) {
|
|||||||
proc_t *saved_p;
|
proc_t *saved_p;
|
||||||
|
|
||||||
if (PT->did_fake) PT->did_fake=0;
|
if (PT->did_fake) PT->did_fake=0;
|
||||||
if (PT->taskdir) {
|
// if (PT->taskdir) {
|
||||||
closedir(PT->taskdir);
|
// closedir(PT->taskdir);
|
||||||
PT->taskdir = NULL;
|
// PT->taskdir = NULL;
|
||||||
}
|
// PT->taskdir_user = -1;
|
||||||
|
// }
|
||||||
|
|
||||||
saved_p = p;
|
saved_p = p;
|
||||||
if(!p) p = xcalloc(p, sizeof *p); /* passed buf or alloced mem */
|
if(!p) p = xcalloc(p, sizeof *p); /* passed buf or alloced mem */
|
||||||
@ -868,6 +874,7 @@ PROCTAB* openproc(int flags, ...) {
|
|||||||
did_stat = 1;
|
did_stat = 1;
|
||||||
}
|
}
|
||||||
PT->taskdir = NULL;
|
PT->taskdir = NULL;
|
||||||
|
PT->taskdir_user = -1;
|
||||||
PT->taskfinder = simple_nexttid;
|
PT->taskfinder = simple_nexttid;
|
||||||
PT->taskreader = simple_readtask;
|
PT->taskreader = simple_readtask;
|
||||||
|
|
||||||
@ -910,6 +917,7 @@ void closeproc(PROCTAB* PT) {
|
|||||||
if (PT){
|
if (PT){
|
||||||
if (PT->procfs) closedir(PT->procfs);
|
if (PT->procfs) closedir(PT->procfs);
|
||||||
if (PT->taskdir) closedir(PT->taskdir);
|
if (PT->taskdir) closedir(PT->taskdir);
|
||||||
|
memset(PT,'#',sizeof(PROCTAB));
|
||||||
free(PT);
|
free(PT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -979,37 +987,21 @@ proc_t** readproctab(int flags, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try again, this time with threads and selection.
|
// Try again, this time with threads and selection.
|
||||||
proc_data_t *readproctab2(int(*want_proc)(proc_t *buf), int(*want_task)(proc_t *buf), int flags, ...) {
|
proc_data_t *readproctab2(int(*want_proc)(proc_t *buf), int(*want_task)(proc_t *buf), PROCTAB *restrict const PT) {
|
||||||
PROCTAB* PT = NULL;
|
|
||||||
proc_t** ptab = NULL;
|
proc_t** ptab = NULL;
|
||||||
proc_t** ttab = NULL;
|
|
||||||
proc_t* data = NULL;
|
|
||||||
unsigned n_alloc = 0;
|
|
||||||
unsigned n_used = 0;
|
|
||||||
unsigned n_proc_alloc = 0;
|
unsigned n_proc_alloc = 0;
|
||||||
unsigned n_proc = 0;
|
unsigned n_proc = 0;
|
||||||
unsigned n_task = 0;
|
|
||||||
|
proc_t** ttab = NULL;
|
||||||
unsigned n_task_alloc = 0;
|
unsigned n_task_alloc = 0;
|
||||||
va_list ap;
|
unsigned n_task = 0;
|
||||||
|
|
||||||
|
proc_t* data = NULL;
|
||||||
|
unsigned n_alloc = 0;
|
||||||
|
unsigned long n_used = 0;
|
||||||
|
|
||||||
proc_data_t *pd;
|
proc_data_t *pd;
|
||||||
|
|
||||||
va_start(ap, flags);
|
|
||||||
if (flags & PROC_UID) {
|
|
||||||
// temporary variables ensure that va_arg() instances
|
|
||||||
// are called in the right order
|
|
||||||
uid_t* u;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
u = va_arg(ap, uid_t*);
|
|
||||||
i = va_arg(ap, int);
|
|
||||||
PT = openproc(flags, u, i);
|
|
||||||
}
|
|
||||||
else if (flags & PROC_PID)
|
|
||||||
PT = openproc(flags, va_arg(ap, void*));
|
|
||||||
else
|
|
||||||
PT = openproc(flags);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
proc_t *tmp;
|
proc_t *tmp;
|
||||||
if(n_alloc == n_used){
|
if(n_alloc == n_used){
|
||||||
@ -1027,8 +1019,7 @@ proc_data_t *readproctab2(int(*want_proc)(proc_t *buf), int(*want_task)(proc_t *
|
|||||||
tmp = readproc_direct(PT, data+n_used);
|
tmp = readproc_direct(PT, data+n_used);
|
||||||
if(!tmp) break;
|
if(!tmp) break;
|
||||||
if(!want_proc(tmp)) continue;
|
if(!want_proc(tmp)) continue;
|
||||||
ptab[n_proc++] = tmp;
|
ptab[n_proc++] = (proc_t*)(n_used++);
|
||||||
n_used++;
|
|
||||||
if(!( PT->flags & PROC_LOOSE_TASKS )) continue;
|
if(!( PT->flags & PROC_LOOSE_TASKS )) continue;
|
||||||
for(;;){
|
for(;;){
|
||||||
proc_t *t;
|
proc_t *t;
|
||||||
@ -1047,25 +1038,25 @@ proc_data_t *readproctab2(int(*want_proc)(proc_t *buf), int(*want_task)(proc_t *
|
|||||||
t = readtask_direct(PT, tmp, data+n_used);
|
t = readtask_direct(PT, tmp, data+n_used);
|
||||||
if(!t) break;
|
if(!t) break;
|
||||||
if(!want_task(t)) continue;
|
if(!want_task(t)) continue;
|
||||||
ttab[n_task++] = t;
|
ttab[n_task++] = (proc_t*)(n_used++);
|
||||||
n_used++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
closeproc(PT);
|
|
||||||
|
|
||||||
pd = malloc(sizeof(proc_data_t));
|
pd = malloc(sizeof(proc_data_t));
|
||||||
pd->proc = ptab;
|
pd->proc = ptab;
|
||||||
pd->task = ttab;
|
pd->task = ttab;
|
||||||
pd->nproc = n_proc;
|
pd->nproc = n_proc;
|
||||||
pd->ntask = n_task;
|
pd->ntask = n_task;
|
||||||
if(flags & PROC_LOOSE_TASKS){
|
if(PT->flags & PROC_LOOSE_TASKS){
|
||||||
pd->tab = ttab;
|
pd->tab = ttab;
|
||||||
pd->n = n_task;
|
pd->n = n_task;
|
||||||
}else{
|
}else{
|
||||||
pd->tab = ptab;
|
pd->tab = ptab;
|
||||||
pd->n = n_proc;
|
pd->n = n_proc;
|
||||||
}
|
}
|
||||||
|
// change array indexes to pointers
|
||||||
|
while(n_proc--) ptab[n_proc] = data+(long)(ptab[n_proc]);
|
||||||
|
while(n_task--) ttab[n_task] = data+(long)(ttab[n_task]);
|
||||||
|
|
||||||
return pd;
|
return pd;
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,10 @@ typedef struct proc_t {
|
|||||||
|
|
||||||
typedef struct PROCTAB {
|
typedef struct PROCTAB {
|
||||||
DIR* procfs;
|
DIR* procfs;
|
||||||
|
// char deBug0[64];
|
||||||
DIR* taskdir; // for threads
|
DIR* taskdir; // for threads
|
||||||
|
// char deBug1[64];
|
||||||
|
pid_t taskdir_user; // for threads
|
||||||
int did_fake; // used when taskdir is missing
|
int did_fake; // used when taskdir is missing
|
||||||
int(*finder)(struct PROCTAB *restrict const, proc_t *restrict const);
|
int(*finder)(struct PROCTAB *restrict const, proc_t *restrict const);
|
||||||
proc_t*(*reader)(struct PROCTAB *restrict const, proc_t *restrict const);
|
proc_t*(*reader)(struct PROCTAB *restrict const, proc_t *restrict const);
|
||||||
@ -181,7 +184,7 @@ typedef struct proc_data_t {
|
|||||||
int ntask;
|
int ntask;
|
||||||
} proc_data_t;
|
} proc_data_t;
|
||||||
|
|
||||||
extern proc_data_t *readproctab2(int(*want_proc)(proc_t *buf), int(*want_task)(proc_t *buf), int flags, ... /* same as openproc */ );
|
extern proc_data_t *readproctab2(int(*want_proc)(proc_t *buf), int(*want_task)(proc_t *buf), PROCTAB *restrict const PT);
|
||||||
|
|
||||||
// Convenient wrapper around openproc and readproc to slurp in the whole process
|
// Convenient wrapper around openproc and readproc to slurp in the whole process
|
||||||
// table subset satisfying the constraints of flags and the optional PID list.
|
// table subset satisfying the constraints of flags and the optional PID list.
|
||||||
|
26
ps/display.c
26
ps/display.c
@ -302,11 +302,13 @@ static void lists_and_needs(void){
|
|||||||
|
|
||||||
/***** fill in %CPU; not in libproc because of include_dead_children */
|
/***** fill in %CPU; not in libproc because of include_dead_children */
|
||||||
/* Note: for sorting, not display, so 0..0x7fffffff would be OK */
|
/* Note: for sorting, not display, so 0..0x7fffffff would be OK */
|
||||||
static void fill_pcpu(proc_t *buf){
|
static int want_this_proc_pcpu(proc_t *buf){
|
||||||
unsigned long long used_jiffies;
|
unsigned long long used_jiffies;
|
||||||
unsigned long pcpu = 0;
|
unsigned long pcpu = 0;
|
||||||
unsigned long long avail_jiffies;
|
unsigned long long avail_jiffies;
|
||||||
|
|
||||||
|
if(!want_this_proc(buf)) return 0;
|
||||||
|
|
||||||
used_jiffies = buf->utime + buf->stime;
|
used_jiffies = buf->utime + buf->stime;
|
||||||
if(include_dead_children) used_jiffies += (buf->cutime + buf->cstime);
|
if(include_dead_children) used_jiffies += (buf->cutime + buf->cstime);
|
||||||
|
|
||||||
@ -314,6 +316,8 @@ static void fill_pcpu(proc_t *buf){
|
|||||||
if(avail_jiffies) pcpu = (used_jiffies << 24) / avail_jiffies;
|
if(avail_jiffies) pcpu = (used_jiffies << 24) / avail_jiffies;
|
||||||
|
|
||||||
buf->pcpu = pcpu; // fits in an int, summing children on 128 CPUs
|
buf->pcpu = pcpu; // fits in an int, summing children on 128 CPUs
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** just display */
|
/***** just display */
|
||||||
@ -469,6 +473,11 @@ not_root:
|
|||||||
/* don't free the array because it takes time and ps will exit anyway */
|
/* don't free the array because it takes time and ps will exit anyway */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int want_this_proc_nop(proc_t *dummy){
|
||||||
|
(void)dummy;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/***** sorted or forest */
|
/***** sorted or forest */
|
||||||
static void fancy_spew(void){
|
static void fancy_spew(void){
|
||||||
proc_t *retbuf = NULL;
|
proc_t *retbuf = NULL;
|
||||||
@ -480,23 +489,27 @@ static void fancy_spew(void){
|
|||||||
fprintf(stderr, "can't have threads with sorting or forest output\n");
|
fprintf(stderr, "can't have threads with sorting or forest output\n");
|
||||||
exit(49);
|
exit(49);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
ptp = openproc(needs_for_format | needs_for_sort | needs_for_select | needs_for_threads);
|
ptp = openproc(needs_for_format | needs_for_sort | needs_for_select | needs_for_threads);
|
||||||
if(!ptp) {
|
if(!ptp) {
|
||||||
fprintf(stderr, "Error: can not access /proc.\n");
|
fprintf(stderr, "Error: can not access /proc.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
while((retbuf = readproc(ptp,retbuf))){
|
while((retbuf = readproc(ptp,retbuf))){
|
||||||
if(want_this_proc(retbuf)){
|
if(want_this_proc_pcpu(retbuf)){
|
||||||
fill_pcpu(retbuf); // in case we might sort by %cpu
|
// fill_pcpu(retbuf); // in case we might sort by %cpu
|
||||||
processes[n++] = retbuf;
|
processes[n++] = retbuf;
|
||||||
retbuf = NULL; // NULL asks readproc to allocate
|
retbuf = NULL; // NULL asks readproc to allocate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(retbuf) free(retbuf);
|
if(retbuf) free(retbuf);
|
||||||
closeproc(ptp);
|
|
||||||
#else
|
#else
|
||||||
// FIXME: need pcpu
|
if(thread_flags & TF_loose_tasks){
|
||||||
pd = readproctab2(want_this_proc, want_this_proc, needs_for_format | needs_for_sort | needs_for_select | needs_for_threads);
|
pd = readproctab2(want_this_proc_nop, want_this_proc_pcpu, ptp);
|
||||||
|
}else{
|
||||||
|
pd = readproctab2(want_this_proc_pcpu, (void*)0xdeadbeaful, ptp);
|
||||||
|
}
|
||||||
n = pd->n;
|
n = pd->n;
|
||||||
processes = pd->tab;
|
processes = pd->tab;
|
||||||
#endif
|
#endif
|
||||||
@ -505,6 +518,7 @@ static void fancy_spew(void){
|
|||||||
qsort(processes, n, sizeof(proc_t*), compare_two_procs);
|
qsort(processes, n, sizeof(proc_t*), compare_two_procs);
|
||||||
if(forest_type) show_forest(n);
|
if(forest_type) show_forest(n);
|
||||||
else show_proc_array(ptp,n);
|
else show_proc_array(ptp,n);
|
||||||
|
closeproc(ptp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -800,11 +800,11 @@ const char *process_sf_options(int localbroken){
|
|||||||
// If nothing else, try to use $PS_FORMAT before the default.
|
// If nothing else, try to use $PS_FORMAT before the default.
|
||||||
if(!format_flags && !format_modifiers && !format_list){
|
if(!format_flags && !format_modifiers && !format_list){
|
||||||
char *tmp;
|
char *tmp;
|
||||||
if(thread_flags&TF_must_use) return "Tell procps-feedback@sf.net what you want. (-L/-T, -m/m/H, and $PS_FORMAT)";
|
|
||||||
tmp = getenv("PS_FORMAT"); /* user override kills default */
|
tmp = getenv("PS_FORMAT"); /* user override kills default */
|
||||||
if(tmp && *tmp){
|
if(tmp && *tmp){
|
||||||
const char *err;
|
const char *err;
|
||||||
sf_node sfn;
|
sf_node sfn;
|
||||||
|
if(thread_flags&TF_must_use) return "Tell procps-feedback@sf.net what you want. (-L/-T, -m/m/H, and $PS_FORMAT)";
|
||||||
sfn.sf = tmp;
|
sfn.sf = tmp;
|
||||||
sfn.f_cooked = NULL;
|
sfn.f_cooked = NULL;
|
||||||
err = format_parse(&sfn);
|
err = format_parse(&sfn);
|
||||||
|
Loading…
Reference in New Issue
Block a user