ps thread support
This commit is contained in:
@@ -73,6 +73,10 @@
|
||||
|
||||
#define needs_for_select (PROC_FILLSTAT | PROC_FILLSTATUS)
|
||||
|
||||
/* thread_flags */
|
||||
#define TF_show_proc 0x0001 // show the summary line
|
||||
#define TF_show_task 0x0002 // show the per-thread lines
|
||||
|
||||
/* personality control flags */
|
||||
#define PER_BROKEN_o 0x0001
|
||||
#define PER_BSD_h 0x0002
|
||||
@@ -270,6 +274,7 @@ extern const char *sysv_f_format;
|
||||
extern const char *sysv_fl_format;
|
||||
extern const char *sysv_j_format;
|
||||
extern const char *sysv_l_format;
|
||||
extern unsigned thread_flags;
|
||||
extern int unix_f_option;
|
||||
extern int user_is_number;
|
||||
extern int wchan_is_number;
|
||||
|
||||
27
ps/display.c
27
ps/display.c
@@ -81,12 +81,12 @@ void hex_dump(void *vp){
|
||||
}
|
||||
}
|
||||
|
||||
static void show_pid(char *s, int n, sel_union *data){
|
||||
static void show_tgid(char *s, int n, sel_union *data){
|
||||
printf("%s ", s);
|
||||
while(--n){
|
||||
printf("%d,", data[n].pid);
|
||||
printf("%d,", data[n].tgid);
|
||||
}
|
||||
printf("%d\n", data[0].pid);
|
||||
printf("%d\n", data[0].tgid);
|
||||
}
|
||||
|
||||
static void show_uid(char *s, int n, sel_union *data){
|
||||
@@ -247,9 +247,18 @@ static void simple_spew(void){
|
||||
fprintf(stderr, "Error: can not access /proc.\n");
|
||||
exit(1);
|
||||
}
|
||||
if(!thread_flags) thread_flags=TF_show_proc;
|
||||
memset(&buf, '#', sizeof(proc_t));
|
||||
while(readproc(ptp,&buf)){
|
||||
if(want_this_proc(&buf)) show_one_proc(&buf);
|
||||
if(want_this_proc(&buf)){
|
||||
if(thread_flags & TF_show_proc) show_one_proc(&buf);
|
||||
if(thread_flags & TF_show_task){
|
||||
proc_t buf2;
|
||||
// must still have the process allocated
|
||||
while(readtask(ptp,&buf,&buf2)) show_one_proc(&buf2);
|
||||
// must not attempt to free cmdline and environ
|
||||
}
|
||||
}
|
||||
if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse
|
||||
if(buf.environ) free((void*)*buf.environ); // ought to reuse
|
||||
// memset(&buf, '#', sizeof(proc_t));
|
||||
@@ -331,7 +340,7 @@ static void show_tree(const int self, const int n, const int level, const int ha
|
||||
// if(processes[self]->environ) free((void*)*processes[self]->environ);
|
||||
for(;;){ /* look for children */
|
||||
if(i >= n) return; /* no children */
|
||||
if(processes[i]->ppid == processes[self]->pid) break;
|
||||
if(processes[i]->ppid == processes[self]->XXXID) break;
|
||||
i++;
|
||||
}
|
||||
if(level){
|
||||
@@ -344,7 +353,7 @@ static void show_tree(const int self, const int n, const int level, const int ha
|
||||
int self_pid;
|
||||
int more_children = 1;
|
||||
if(i >= n) break; /* over the edge */
|
||||
self_pid=processes[self]->pid;
|
||||
self_pid=processes[self]->XXXID;
|
||||
if(i+1 >= n)
|
||||
more_children = 0;
|
||||
else
|
||||
@@ -367,7 +376,7 @@ static void show_forest(const int n){
|
||||
while(i--){ /* cover whole array looking for trees */
|
||||
j = n;
|
||||
while(j--){ /* search for parent: if none, i is a tree! */
|
||||
if(processes[j]->pid == processes[i]->ppid) goto not_root;
|
||||
if(processes[j]->XXXID == processes[i]->ppid) goto not_root;
|
||||
}
|
||||
show_tree(i,n,0,0);
|
||||
not_root:
|
||||
@@ -381,6 +390,10 @@ static void fancy_spew(void){
|
||||
proc_t *retbuf = NULL;
|
||||
PROCTAB *restrict ptp;
|
||||
int n = 0; /* number of processes & index into array */
|
||||
if(thread_flags){
|
||||
fprintf(stderr, "can't have threads with sorting or forest output\n");
|
||||
exit(49);
|
||||
}
|
||||
ptp = openproc(needs_for_format | needs_for_sort | needs_for_select);
|
||||
if(!ptp) {
|
||||
fprintf(stderr, "Error: can not access /proc.\n");
|
||||
|
||||
@@ -73,6 +73,7 @@ const char *sysv_f_format = (const char *)0xdeadbeef;
|
||||
const char *sysv_fl_format = (const char *)0xdeadbeef;
|
||||
const char *sysv_j_format = (const char *)0xdeadbeef;
|
||||
const char *sysv_l_format = (const char *)0xdeadbeef;
|
||||
unsigned thread_flags = 0xffffffff;
|
||||
int unix_f_option = -1;
|
||||
int user_is_number = -1;
|
||||
int wchan_is_number = -1;
|
||||
@@ -343,6 +344,7 @@ void reset_global(void){
|
||||
selection_list = NULL;
|
||||
simple_select = 0;
|
||||
sort_list = NULL;
|
||||
thread_flags = 0;
|
||||
unix_f_option = 0;
|
||||
user_is_number = 0;
|
||||
wchan_is_number = 0;
|
||||
|
||||
23
ps/output.c
23
ps/output.c
@@ -201,7 +201,8 @@ CMP_INT(suid)
|
||||
CMP_INT(sgid)
|
||||
CMP_INT(fuid)
|
||||
CMP_INT(fgid)
|
||||
CMP_SMALL(pid)
|
||||
CMP_SMALL(tid)
|
||||
CMP_SMALL(tgid)
|
||||
CMP_SMALL(ppid)
|
||||
CMP_SMALL(pgrp)
|
||||
CMP_SMALL(session)
|
||||
@@ -457,7 +458,7 @@ static int pr_pgid(char *restrict const outbuf, const proc_t *restrict const pp)
|
||||
return snprintf(outbuf, COLWID, "%u", pp->pgrp);
|
||||
}
|
||||
static int pr_pid(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||
return snprintf(outbuf, COLWID, "%u", pp->pid);
|
||||
return snprintf(outbuf, COLWID, "%u", pp->tgid);
|
||||
}
|
||||
static int pr_ppid(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||
return snprintf(outbuf, COLWID, "%u", pp->ppid);
|
||||
@@ -561,20 +562,20 @@ static int pr_wchan(char *restrict const outbuf, const proc_t *restrict const pp
|
||||
*/
|
||||
if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "%s", "-");
|
||||
if(wchan_is_number) return snprintf(outbuf, COLWID, "%x", (unsigned)(pp->wchan) & 0xffffffu);
|
||||
return snprintf(outbuf, COLWID, "%s", wchan(pp->wchan, pp->pid));
|
||||
return snprintf(outbuf, COLWID, "%s", wchan(pp->wchan, pp->XXXID));
|
||||
}
|
||||
|
||||
/* Terrible trunctuation, like BSD crap uses: I999 J999 K999 */
|
||||
/* FIXME: disambiguate /dev/tty69 and /dev/pts/69. */
|
||||
static int pr_tty4(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||
/* snprintf(outbuf, COLWID, "%02x:%02x", pp->tty>>8, pp->tty&0xff); */
|
||||
return dev_to_tty(outbuf, 4, pp->tty, pp->pid, ABBREV_DEV|ABBREV_TTY|ABBREV_PTS);
|
||||
return dev_to_tty(outbuf, 4, pp->tty, pp->XXXID, ABBREV_DEV|ABBREV_TTY|ABBREV_PTS);
|
||||
}
|
||||
|
||||
/* Unix98: format is unspecified, but must match that used by who(1). */
|
||||
static int pr_tty8(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||
/* snprintf(outbuf, COLWID, "%02x:%02x", pp->tty>>8, pp->tty&0xff); */
|
||||
return dev_to_tty(outbuf, PAGE_SIZE-1, pp->tty, pp->pid, ABBREV_DEV);
|
||||
return dev_to_tty(outbuf, PAGE_SIZE-1, pp->tty, pp->XXXID, ABBREV_DEV);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -767,7 +768,7 @@ static int pr_wname(char *restrict const outbuf, const proc_t *restrict const pp
|
||||
* more than one thread waiting in the kernel.
|
||||
*/
|
||||
if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "%s", "-");
|
||||
return snprintf(outbuf, COLWID, "%s", wchan(pp->wchan, pp->pid));
|
||||
return snprintf(outbuf, COLWID, "%s", wchan(pp->wchan, pp->XXXID));
|
||||
}
|
||||
|
||||
static int pr_nwchan(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||
@@ -937,7 +938,7 @@ static int pr_suser(char *restrict const outbuf, const proc_t *restrict const pp
|
||||
|
||||
|
||||
static int pr_thread(char *restrict const outbuf, const proc_t *restrict const pp){ /* TID tid LWP lwp SPID spid */
|
||||
return snprintf(outbuf, COLWID, "%u", pp->pid); /* for now... FIXME */
|
||||
return snprintf(outbuf, COLWID, "%u", pp->tid);
|
||||
}
|
||||
static int pr_nlwp(char *restrict const outbuf, const proc_t *restrict const pp){ /* THCNT thcount NLWP nlwp */
|
||||
(void)pp; // FIXME
|
||||
@@ -1215,7 +1216,7 @@ static const format_struct format_array[] = {
|
||||
{"lstart", "STARTED", pr_lstart, sr_nop, 24, 0, XXX, RIGHT},
|
||||
{"luid", "LUID", pr_nop, sr_nop, 5, 0, LNX, RIGHT}, /* login ID */
|
||||
{"luser", "LUSER", pr_nop, sr_nop, 8, USR, LNX, USER}, /* login USER */
|
||||
{"lwp", "LWP", pr_thread, sr_nop, 5, 0, SUN, PIDMAX|RIGHT},
|
||||
{"lwp", "LWP", pr_thread, sr_tid, 5, 0, SUN, PIDMAX|RIGHT},
|
||||
{"m_drs", "DRS", pr_drs, sr_drs, 5, MEM, LNx, RIGHT},
|
||||
{"m_dt", "DT", pr_nop, sr_dt, 4, MEM, LNx, RIGHT},
|
||||
{"m_lrs", "LRS", pr_nop, sr_lrs, 5, MEM, LNx, RIGHT},
|
||||
@@ -1250,7 +1251,7 @@ static const format_struct format_array[] = {
|
||||
{"pending", "PENDING", pr_sig, sr_nop, 9, 0, BSD, SIGNAL}, /*sig*/
|
||||
{"pgid", "PGID", pr_pgid, sr_pgrp, 5, 0, U98, PIDMAX|RIGHT},
|
||||
{"pgrp", "PGRP", pr_pgid, sr_pgrp, 5, 0, LNX, PIDMAX|RIGHT},
|
||||
{"pid", "PID", pr_pid, sr_pid, 5, 0, U98, PIDMAX|RIGHT},
|
||||
{"pid", "PID", pr_pid, sr_tgid, 5, 0, U98, PIDMAX|RIGHT},
|
||||
{"pmem", "%MEM", pr_pmem, sr_nop, 4, 0, XXX, RIGHT}, /*%mem*/
|
||||
{"poip", "-", pr_nop, sr_nop, 1, 0, BSD, RIGHT},
|
||||
{"policy", "POL", pr_class, sr_sched, 3, 0, DEC, LEFT},
|
||||
@@ -1296,7 +1297,7 @@ static const format_struct format_array[] = {
|
||||
{"sigmask", "BLOCKED", pr_sigmask, sr_nop, 9, 0, XXX, SIGNAL}, /*blocked*/
|
||||
{"size", "SZ", pr_swapable, sr_swapable, 1, 0, SCO, RIGHT},
|
||||
{"sl", "SL", pr_nop, sr_nop, 3, 0, XXX, RIGHT},
|
||||
{"spid", "SPID", pr_thread, sr_nop, 5, 0, SGI, PIDMAX|RIGHT},
|
||||
{"spid", "SPID", pr_thread, sr_tid, 5, 0, SGI, PIDMAX|RIGHT},
|
||||
{"stackp", "STACKP", pr_stackp, sr_nop, 8, 0, LNX, RIGHT}, /*start_stack*/
|
||||
{"start", "STARTED", pr_start, sr_nop, 8, 0, XXX, RIGHT},
|
||||
{"start_code", "S_CODE", pr_nop, sr_start_code, 8, 0, LNx, RIGHT},
|
||||
@@ -1316,7 +1317,7 @@ static const format_struct format_array[] = {
|
||||
{"sz", "SZ", pr_sz, sr_nop, 5, 0, HPU, RIGHT},
|
||||
{"tdev", "TDEV", pr_nop, sr_nop, 4, 0, XXX, RIGHT},
|
||||
{"thcount", "THCNT", pr_nlwp, sr_nop, 5, 0, AIX, RIGHT},
|
||||
{"tid", "TID", pr_thread, sr_nop, 5, 0, AIX, PIDMAX|RIGHT},
|
||||
{"tid", "TID", pr_thread, sr_tid, 5, 0, AIX, PIDMAX|RIGHT},
|
||||
{"time", "TIME", pr_time, sr_nop, 8, 0, U98, CUMUL|RIGHT}, /*cputime*/ /* was 6 wide */
|
||||
{"timeout", "TMOUT", pr_timeout, sr_timeout, 5, 0, LNX, RIGHT},
|
||||
{"tmout", "TMOUT", pr_timeout, sr_timeout, 5, 0, LNX, RIGHT},
|
||||
|
||||
22
ps/parser.c
22
ps/parser.c
@@ -264,6 +264,7 @@ static const char *parse_sysv_option(void){
|
||||
* SCO UnixWare uses -L too.
|
||||
*/
|
||||
trace("-L Print LWP (thread) info.\n");
|
||||
thread_flags |= TF_show_task;
|
||||
format_modifiers |= FM_L;
|
||||
break;
|
||||
case 'M': /* someday, maybe, we will have MAC like SGI's Irix */
|
||||
@@ -298,6 +299,7 @@ static const char *parse_sysv_option(void){
|
||||
* Also, testing shows PID==SPID for all normal processes.
|
||||
*/
|
||||
trace("-T adds strange SPID column (old sproc() threads?)\n");
|
||||
thread_flags |= TF_show_task;
|
||||
format_modifiers |= FM_T;
|
||||
break;
|
||||
case 'U': /* end */
|
||||
@@ -367,7 +369,8 @@ static const char *parse_sysv_option(void){
|
||||
case 'm':
|
||||
trace("-m shows threads.\n");
|
||||
/* note that AIX shows 2 lines for a normal process */
|
||||
/* not implemented -- silently ignore the option */
|
||||
thread_flags |= TF_show_proc;
|
||||
thread_flags |= TF_show_task;
|
||||
break;
|
||||
case 'n': /* end */
|
||||
trace("-n sets namelist file.\n");
|
||||
@@ -494,6 +497,11 @@ static const char *parse_bsd_option(void){
|
||||
return "Option C is reserved.";
|
||||
break;
|
||||
#endif
|
||||
case 'H': // The FreeBSD way (NetBSD:s OpenBSD:k FreeBSD:H -- NIH???)
|
||||
trace("H Print LWP (thread) info.\n"); // was: Use /vmcore as c-dumpfile\n");
|
||||
thread_flags |= TF_show_task; // FIXME: determine if TF_show_proc is needed
|
||||
//format_modifiers |= FM_L; // FIXME: determine if we need something like this
|
||||
break;
|
||||
case 'L': /* single */
|
||||
trace("L List all format specifiers\n");
|
||||
exclusive("L");
|
||||
@@ -587,12 +595,11 @@ static const char *parse_bsd_option(void){
|
||||
trace("j job control format\n");
|
||||
format_flags |= FF_Bj;
|
||||
break;
|
||||
#if 0
|
||||
case 'k':
|
||||
trace("k N/A Use /vmcore as c-dumpfile\n");
|
||||
return "Obsolete k option not supported.";
|
||||
case 'k': // The OpenBSD way (NetBSD:s OpenBSD:k FreeBSD:H -- NIH???)
|
||||
trace("k Print LWP (thread) info.\n"); // was: Use /vmcore as c-dumpfile\n");
|
||||
thread_flags |= TF_show_task; // FIXME: determine if TF_show_proc is needed
|
||||
//format_modifiers |= FM_L; // FIXME: determine if we need something like this
|
||||
break;
|
||||
#endif
|
||||
case 'l':
|
||||
trace("l Display long format\n");
|
||||
format_flags |= FF_Bl;
|
||||
@@ -607,7 +614,8 @@ static const char *parse_bsd_option(void){
|
||||
defer_sf_option("pmem", SF_B_m);
|
||||
break;
|
||||
}
|
||||
/* not implemented -- silently ignore the option */
|
||||
thread_flags |= TF_show_proc;
|
||||
thread_flags |= TF_show_task;
|
||||
break;
|
||||
case 'n':
|
||||
trace("n Numeric output for WCHAN, and USER replaced by UID\n");
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#include "../proc/readproc.h"
|
||||
#include "../proc/procps.h"
|
||||
|
||||
#define session_leader(p) ((p)->session == (p)->pid)
|
||||
#define process_group_leader(p) ((p)->pgid == (p)->pid)
|
||||
#define session_leader(p) ((p)->session == (p)->tgid)
|
||||
#define process_group_leader(p) ((p)->pgid == (p)->tgid)
|
||||
#define without_a_tty(p) ((unsigned short)((p)->tty) == (unsigned short)0)
|
||||
#define some_other_user(p) ((p)->euid != cached_euid)
|
||||
#define running(p) (((p)->state=='R')||((p)->state=='D'))
|
||||
@@ -101,7 +101,7 @@ static int proc_was_listed(proc_t *buf){
|
||||
break; case SEL_FGID: return_if_match(fgid,gid);
|
||||
|
||||
break; case SEL_PGRP: return_if_match(pgrp,pid);
|
||||
break; case SEL_PID : return_if_match(pid,pid);
|
||||
break; case SEL_PID : return_if_match(tgid,pid);
|
||||
break; case SEL_PPID: return_if_match(ppid,ppid);
|
||||
break; case SEL_TTY : return_if_match(tty,tty);
|
||||
break; case SEL_SESS: return_if_match(session,pid);
|
||||
|
||||
Reference in New Issue
Block a user