thread-related hacks
This commit is contained in:
parent
9f62cb1b9d
commit
7046b34f42
2
NEWS
2
NEWS
@ -1,6 +1,8 @@
|
|||||||
procps-3.1.14 --> procps-3.1.15
|
procps-3.1.14 --> procps-3.1.15
|
||||||
|
|
||||||
install to /lib64 if it exists
|
install to /lib64 if it exists
|
||||||
|
hide kernel PID bug (Linux 2.4.13-pre1 to 2.4.MAX) #217278 #219730 #217525
|
||||||
|
ps: faster threaded display
|
||||||
|
|
||||||
procps-3.1.13 --> procps-3.1.14
|
procps-3.1.13 --> procps-3.1.14
|
||||||
|
|
||||||
|
304
proc/readproc.c
304
proc/readproc.c
@ -46,8 +46,8 @@ static int task_dir_missing;
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef struct status_table_struct {
|
typedef struct status_table_struct {
|
||||||
unsigned char name[6]; // /proc/*/status field name
|
unsigned char name[7]; // /proc/*/status field name
|
||||||
short len; // name length
|
unsigned char len; // name length
|
||||||
#ifdef LABEL_OFFSET
|
#ifdef LABEL_OFFSET
|
||||||
long offset; // jump address offset
|
long offset; // jump address offset
|
||||||
#else
|
#else
|
||||||
@ -64,84 +64,78 @@ typedef struct status_table_struct {
|
|||||||
|
|
||||||
// Derived from:
|
// Derived from:
|
||||||
// gperf -7 --language=ANSI-C --key-positions=1,3,4 -C -n -c sml.gperf
|
// gperf -7 --language=ANSI-C --key-positions=1,3,4 -C -n -c sml.gperf
|
||||||
|
//
|
||||||
|
// Suggested method:
|
||||||
|
// Grep this file for "case_", then strip those down to the name.
|
||||||
|
// (leave the colon and newline) So "Pid:\n" and "Threads:\n"
|
||||||
|
// would be lines in the file. (no quote, no escape, etc.)
|
||||||
|
//
|
||||||
|
// Watch out for name size in the status_table_struct (grrr, expanding)
|
||||||
|
// and the number of entries (we mask with 63 for now). The table
|
||||||
|
// must be padded out to 64 entries, maybe 128 in the future.
|
||||||
|
|
||||||
static void status2proc(char *S, proc_t *restrict P, int is_proc){
|
static void status2proc(char *S, proc_t *restrict P, int is_proc){
|
||||||
char ShdPnd[16] = "";
|
char ShdPnd[16] = "";
|
||||||
static const unsigned char asso[] = {
|
long Threads = 0;
|
||||||
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
|
long Tgid = 0;
|
||||||
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
|
long Pid = 0;
|
||||||
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
|
|
||||||
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 15, 56, 56, 56, 56, 56,
|
static const unsigned char asso[] =
|
||||||
56, 56, 25, 30, 15, 3, 56, 5, 56, 3, 56, 56, 3, 56, 10, 56,
|
{
|
||||||
18, 56, 13, 0, 30, 25, 0, 56, 56, 56, 56, 56, 56, 56, 56, 56,
|
61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
|
||||||
56, 30, 56, 8, 0, 0, 56, 25, 56, 5, 56, 56, 56, 0, 56, 56,
|
61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
|
||||||
56, 56, 56, 56, 0, 56, 56, 56, 0, 56, 56, 56, 56, 56, 56, 56
|
61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
|
||||||
|
61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
|
||||||
|
61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
|
||||||
|
61, 61, 61, 61, 61, 61, 61, 61, 15, 61,
|
||||||
|
61, 61, 61, 61, 61, 61, 30, 3, 5, 5,
|
||||||
|
61, 5, 61, 8, 61, 61, 3, 61, 10, 61,
|
||||||
|
6, 61, 13, 0, 30, 25, 0, 61, 61, 61,
|
||||||
|
61, 61, 61, 61, 61, 61, 61, 3, 61, 13,
|
||||||
|
0, 0, 61, 30, 61, 25, 61, 61, 61, 0,
|
||||||
|
61, 61, 61, 61, 5, 61, 0, 61, 61, 61,
|
||||||
|
0, 61, 61, 61, 61, 61, 61, 61
|
||||||
};
|
};
|
||||||
|
|
||||||
static const status_table_struct table[] = {
|
static const status_table_struct table[] = {
|
||||||
F(VmStk)
|
F(VmStk)
|
||||||
NUL
|
NUL NUL
|
||||||
NUL
|
F(State)
|
||||||
F(VmExe)
|
NUL
|
||||||
NUL
|
F(VmExe)
|
||||||
F(VmSize)
|
F(ShdPnd)
|
||||||
NUL
|
NUL
|
||||||
NUL
|
F(VmData)
|
||||||
F(VmLib)
|
NUL
|
||||||
NUL
|
F(Name)
|
||||||
F(Name)
|
NUL NUL
|
||||||
F(VmLck)
|
F(VmRSS)
|
||||||
NUL
|
NUL NUL
|
||||||
F(VmRSS)
|
F(VmLck)
|
||||||
NUL
|
NUL NUL NUL
|
||||||
NUL
|
F(Gid)
|
||||||
NUL
|
F(Pid)
|
||||||
NUL
|
NUL NUL NUL
|
||||||
F(ShdPnd)
|
F(VmSize)
|
||||||
NUL
|
NUL NUL
|
||||||
F(Gid)
|
F(VmLib)
|
||||||
NUL
|
NUL NUL
|
||||||
NUL
|
F(PPid)
|
||||||
F(PPid)
|
NUL
|
||||||
NUL
|
F(SigCgt)
|
||||||
NUL
|
NUL
|
||||||
NUL
|
F(Threads)
|
||||||
NUL
|
F(SigPnd)
|
||||||
F(SigIgn)
|
NUL
|
||||||
NUL
|
F(SigIgn)
|
||||||
F(State)
|
NUL
|
||||||
NUL
|
F(Uid)
|
||||||
NUL
|
NUL NUL NUL NUL NUL NUL NUL NUL NUL
|
||||||
F(Pid)
|
NUL NUL NUL NUL NUL
|
||||||
NUL
|
F(Tgid)
|
||||||
F(Tgid)
|
NUL NUL NUL NUL
|
||||||
NUL
|
F(SigBlk)
|
||||||
NUL
|
NUL NUL NUL
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
F(Uid)
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
F(SigPnd)
|
|
||||||
NUL
|
|
||||||
F(VmData)
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
F(SigBlk)
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
F(SigCgt)
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
NUL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef F
|
#undef F
|
||||||
@ -156,6 +150,7 @@ ENTER(0x220);
|
|||||||
P->vm_stack= 0;
|
P->vm_stack= 0;
|
||||||
P->vm_exe = 0;
|
P->vm_exe = 0;
|
||||||
P->vm_lib = 0;
|
P->vm_lib = 0;
|
||||||
|
P->nlwp = 0;
|
||||||
|
|
||||||
goto base;
|
goto base;
|
||||||
|
|
||||||
@ -186,12 +181,6 @@ ENTER(0x220);
|
|||||||
goto *entry.addr;
|
goto *entry.addr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case_Gid:
|
|
||||||
P->rgid = strtol(S,&S,10);
|
|
||||||
P->egid = strtol(S,&S,10);
|
|
||||||
P->sgid = strtol(S,&S,10);
|
|
||||||
P->fgid = strtol(S,&S,10);
|
|
||||||
continue;
|
|
||||||
case_Name:{
|
case_Name:{
|
||||||
unsigned u = 0;
|
unsigned u = 0;
|
||||||
while(u < sizeof P->cmd - 1u){
|
while(u < sizeof P->cmd - 1u){
|
||||||
@ -210,16 +199,6 @@ ENTER(0x220);
|
|||||||
S--; // put back the '\n' or '\0'
|
S--; // put back the '\n' or '\0'
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case_PPid:
|
|
||||||
P->ppid = strtol(S,&S,10);
|
|
||||||
continue;
|
|
||||||
case_Pid:
|
|
||||||
P->tid = strtol(S,&S,10);
|
|
||||||
continue;
|
|
||||||
case_Threads:
|
|
||||||
P->nlwp = strtol(S,&S,10);
|
|
||||||
continue;
|
|
||||||
|
|
||||||
case_ShdPnd:
|
case_ShdPnd:
|
||||||
memcpy(ShdPnd, S, 16);
|
memcpy(ShdPnd, S, 16);
|
||||||
// we know it to be 16 char, so no '\0' needed
|
// we know it to be 16 char, so no '\0' needed
|
||||||
@ -240,12 +219,20 @@ ENTER(0x220);
|
|||||||
memcpy(P->signal, S, 16);
|
memcpy(P->signal, S, 16);
|
||||||
P->signal[16] = '\0';
|
P->signal[16] = '\0';
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case_State:
|
case_State:
|
||||||
P->state = *S;
|
P->state = *S;
|
||||||
continue;
|
continue;
|
||||||
case_Tgid:
|
case_Tgid:
|
||||||
P->tgid = strtol(S,&S,10);
|
Tgid = strtol(S,&S,10);
|
||||||
|
continue;
|
||||||
|
case_Pid:
|
||||||
|
Pid = strtol(S,&S,10);
|
||||||
|
continue;
|
||||||
|
case_PPid:
|
||||||
|
P->ppid = strtol(S,&S,10);
|
||||||
|
continue;
|
||||||
|
case_Threads:
|
||||||
|
Threads = strtol(S,&S,10);
|
||||||
continue;
|
continue;
|
||||||
case_Uid:
|
case_Uid:
|
||||||
P->ruid = strtol(S,&S,10);
|
P->ruid = strtol(S,&S,10);
|
||||||
@ -253,6 +240,12 @@ ENTER(0x220);
|
|||||||
P->suid = strtol(S,&S,10);
|
P->suid = strtol(S,&S,10);
|
||||||
P->fuid = strtol(S,&S,10);
|
P->fuid = strtol(S,&S,10);
|
||||||
continue;
|
continue;
|
||||||
|
case_Gid:
|
||||||
|
P->rgid = strtol(S,&S,10);
|
||||||
|
P->egid = strtol(S,&S,10);
|
||||||
|
P->sgid = strtol(S,&S,10);
|
||||||
|
P->fgid = strtol(S,&S,10);
|
||||||
|
continue;
|
||||||
case_VmData:
|
case_VmData:
|
||||||
P->vm_data = strtol(S,&S,10);
|
P->vm_data = strtol(S,&S,10);
|
||||||
continue;
|
continue;
|
||||||
@ -282,6 +275,20 @@ ENTER(0x220);
|
|||||||
P->signal[16] = '\0';
|
P->signal[16] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Linux 2.4.13-pre1 to max 2.4.xx have a useless "Tgid"
|
||||||
|
// that is not initialized for built-in kernel tasks.
|
||||||
|
// Only 2.6.0 and above have "Threads" (nlwp) info.
|
||||||
|
|
||||||
|
if(Threads){
|
||||||
|
P->nlwp = Threads;
|
||||||
|
P->tgid = Tgid; // the POSIX PID value
|
||||||
|
P->tid = Pid; // the thread ID
|
||||||
|
}else{
|
||||||
|
P->nlwp = 1;
|
||||||
|
P->tgid = Pid;
|
||||||
|
P->tid = Pid;
|
||||||
|
}
|
||||||
|
|
||||||
LEAVE(0x220);
|
LEAVE(0x220);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,10 +303,10 @@ static void stat2proc(const char* S, proc_t *restrict P) {
|
|||||||
ENTER(0x160);
|
ENTER(0x160);
|
||||||
|
|
||||||
/* fill in default values for older kernels */
|
/* fill in default values for older kernels */
|
||||||
P->exit_signal = SIGCHLD;
|
|
||||||
P->processor = 0;
|
P->processor = 0;
|
||||||
P->rtprio = -1;
|
P->rtprio = -1;
|
||||||
P->sched = -1;
|
P->sched = -1;
|
||||||
|
P->nlwp = 0;
|
||||||
|
|
||||||
S = strchr(S, '(') + 1;
|
S = strchr(S, '(') + 1;
|
||||||
tmp = strrchr(S, ')');
|
tmp = strrchr(S, ')');
|
||||||
@ -343,6 +350,11 @@ ENTER(0x160);
|
|||||||
/* -- Linux 2.2.8 to 2.5.17 end here -- */
|
/* -- Linux 2.2.8 to 2.5.17 end here -- */
|
||||||
&P->rtprio, &P->sched /* both added to 2.5.18 */
|
&P->rtprio, &P->sched /* both added to 2.5.18 */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if(!P->nlwp){
|
||||||
|
P->nlwp = 1;
|
||||||
|
}
|
||||||
|
|
||||||
LEAVE(0x160);
|
LEAVE(0x160);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,59 +709,6 @@ static int listed_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p)
|
|||||||
return tgid;
|
return tgid;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// This "finds" processes by guessing every possible one of them!
|
|
||||||
// Return non-zero on success. (pid was handy)
|
|
||||||
#if 0
|
|
||||||
static int stupid_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p) {
|
|
||||||
char *restrict const path = PT->path;
|
|
||||||
pid_t pid = --PT->u;
|
|
||||||
if(likely( pid )){
|
|
||||||
snprintf(path, PROCPATHLEN, "/proc/%d", pid);
|
|
||||||
p->pid = pid;
|
|
||||||
}
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// This reads process info from proc_t structs already attached to a PROCTAB.
|
|
||||||
// Yeah, we don't retain any pointer for freeing the memory later. Oh well.
|
|
||||||
// This code is for development only.
|
|
||||||
#if 0
|
|
||||||
static proc_t* predone_readproc(PROCTAB *restrict const PT, proc_t *restrict const p) {
|
|
||||||
proc_t *tmp;
|
|
||||||
proc_t *ret = NULL;
|
|
||||||
for(;;){
|
|
||||||
tmp = PT->vp;
|
|
||||||
if(!tmp) _exit(49); // can't happen
|
|
||||||
PT->vp = tmp->next;
|
|
||||||
if(tmp->pid == tmp->tgid){ // got a leader?
|
|
||||||
memcpy(p,tmp,sizeof(proc_t)); // copy it, pointers and all
|
|
||||||
ret = p;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!ret) _exit(99); // can't happen
|
|
||||||
while(PT->vp){
|
|
||||||
tmp = PT->vp;
|
|
||||||
if(tmp->pid == tmp->tgid) break; // OK, next one is a leader
|
|
||||||
PT->vp = tmp->next;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// This "finds" processes by pulling them off of a list.
|
|
||||||
// Return non-zero on success.
|
|
||||||
#if 0
|
|
||||||
static int predone_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p) {
|
|
||||||
(void)p;
|
|
||||||
return !!PT->vp;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
/* readproc: return a pointer to a proc_t filled with requested info about the
|
/* readproc: return a pointer to a proc_t filled with requested info about the
|
||||||
* next process available matching the restriction set. If no more such
|
* next process available matching the restriction set. If no more such
|
||||||
@ -803,7 +762,9 @@ proc_t* readtask(PROCTAB *restrict const PT, const proc_t *restrict const p, pro
|
|||||||
saved_t = t;
|
saved_t = t;
|
||||||
if(!t) t = xcalloc(t, sizeof *t); /* passed buf or alloced mem */
|
if(!t) t = xcalloc(t, sizeof *t); /* passed buf or alloced mem */
|
||||||
|
|
||||||
if(task_dir_missing){ // got to fake a thread for old kernels
|
// 1. got to fake a thread for old kernels
|
||||||
|
// 2. for single-threaded processes, this is faster
|
||||||
|
if(task_dir_missing || p->nlwp < 2){
|
||||||
if(PT->did_fake) goto out;
|
if(PT->did_fake) goto out;
|
||||||
PT->did_fake=1;
|
PT->did_fake=1;
|
||||||
memcpy(t,p,sizeof(proc_t));
|
memcpy(t,p,sizeof(proc_t));
|
||||||
@ -826,42 +787,6 @@ out:
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void evil_grouping_hack(PROCTAB* PT){
|
|
||||||
proc_t *tp;
|
|
||||||
// first we read them
|
|
||||||
for(;;){
|
|
||||||
tp = malloc(sizeof(proc_t));
|
|
||||||
if(!tp) _exit(2);
|
|
||||||
if(!readproc(PT, tp)){
|
|
||||||
free(tp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tp->ring = tp;
|
|
||||||
tp->next = PT->vp;
|
|
||||||
PT->vp = tp;
|
|
||||||
}
|
|
||||||
// now we scan
|
|
||||||
tp = PT->vp;
|
|
||||||
while(tp){
|
|
||||||
if(tp->pid == tp->tgid){ // if we found a leader
|
|
||||||
proc_t *tmp = PT->vp;
|
|
||||||
while(tmp){
|
|
||||||
if(tmp != tp && tmp->tgid == tp->tgid){
|
|
||||||
tmp->ring = tp->ring;
|
|
||||||
tp->ring = tmp;
|
|
||||||
}
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tp = tp->next;
|
|
||||||
}
|
|
||||||
// later, readproc returns what we already have
|
|
||||||
PT->finder = predone_nextpid;
|
|
||||||
PT->reader = predone_readproc;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// initiate a process table scan
|
// initiate a process table scan
|
||||||
PROCTAB* openproc(int flags, ...) {
|
PROCTAB* openproc(int flags, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@ -889,13 +814,6 @@ PROCTAB* openproc(int flags, ...) {
|
|||||||
}
|
}
|
||||||
PT->flags = flags;
|
PT->flags = flags;
|
||||||
|
|
||||||
#if 0
|
|
||||||
if(getenv("EVIL_FINDER_HACK")){ // for development only
|
|
||||||
PT->finder = stupid_nextpid;
|
|
||||||
PT->u = 10000;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
va_start(ap, flags); /* Init args list */
|
va_start(ap, flags); /* Init args list */
|
||||||
if (flags & PROC_PID)
|
if (flags & PROC_PID)
|
||||||
PT->pids = va_arg(ap, pid_t*);
|
PT->pids = va_arg(ap, pid_t*);
|
||||||
@ -905,10 +823,6 @@ PROCTAB* openproc(int flags, ...) {
|
|||||||
}
|
}
|
||||||
va_end(ap); /* Clean up args list */
|
va_end(ap); /* Clean up args list */
|
||||||
|
|
||||||
#if 0
|
|
||||||
if(getenv("EVIL_GROUPING_HACK")) evil_grouping_hack(PT);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return PT;
|
return PT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user