From 4a54e25acaf4f634832b905e274cce36d3b7a5c6 Mon Sep 17 00:00:00 2001 From: albert <> Date: Mon, 17 Feb 2003 00:57:15 +0000 Subject: [PATCH] 2.5.61 --- NEWS | 1 + proc/module.mk | 9 +- proc/procps.h | 5 + proc/readproc.c | 336 ++++++++++++++++++++++++++++++++++-------------- proc/readproc.h | 1 + 5 files changed, 255 insertions(+), 97 deletions(-) diff --git a/NEWS b/NEWS index e123cf4f..5787a254 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,6 @@ procps-3.1.5 --> procps-3.1.6 +handle the 2.5.61 kernel top: memory leak fixed ps: new --ppid option selects by PPID watch: new --no-title option #179862 diff --git a/proc/module.mk b/proc/module.mk index e0f1bd7a..de0399b5 100644 --- a/proc/module.mk +++ b/proc/module.mk @@ -14,19 +14,22 @@ LIBOBJ := $(LIBSRC:.c=.o) #ALL += proc/lib$(NAME).a #INSTALL += $(usr/lib)/lib$(NAME).a # plus $(usr/include)$(NAME) gunk +FPIC := -fpic + ifeq ($(SHARED),1) ALL += proc/$(SONAME) INSTALL += $(lib)/$(SONAME) -FPIC := -fpic +LIBFLAGS := -DSHARED=1 $(FPIC) LIBPROC := proc/$(SONAME) else ALL += proc/lib$(NAME).a +LIBFLAGS := -DSHARED=0 LIBPROC := proc/lib$(NAME).a endif # Separate rule for this directory, to use -fpic or -fPIC $(filter-out proc/version.o,$(LIBOBJ)): proc/%.o: proc/%.c - $(CC) -c $(CFLAGS) $(FPIC) $< -o $@ + $(CC) -c $(CFLAGS) $(LIBFLAGS) $< -o $@ LIB_X := COPYING module.mk library.map TARFILES += $(LIBSRC) $(LIBHDR) $(addprefix proc/,$(LIB_X)) @@ -71,4 +74,4 @@ $(lib)/$(SONAME) : proc/$(SONAME) proc/version.o: proc/version.c proc/version.h - $(CC) $(CFLAGS) $(FPIC) -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" -c -o $@ $< + $(CC) $(CFLAGS) $(LIBFLAGS) -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" -c -o $@ $< diff --git a/proc/procps.h b/proc/procps.h index 95134a6b..5909c20a 100644 --- a/proc/procps.h +++ b/proc/procps.h @@ -64,6 +64,11 @@ #define expected(x,y) (x) #endif +#if SHARED==1 && (__GNUC__ > 2 || __GNUC_MINOR__ >= 96) +#define LABEL_OFFSET +#endif + + // marks old junk, to warn non-procps library users #if ( __GNUC__ == 3 && __GNUC_MINOR__ > 0 ) || __GNUC__ > 3 #define OBSOLETE __attribute__((deprecated)) diff --git a/proc/readproc.c b/proc/readproc.c index f71ce163..941d7a83 100644 --- a/proc/readproc.c +++ b/proc/readproc.c @@ -31,6 +31,15 @@ #include #endif +#ifdef PROF +extern void __cyg_profile_func_enter(void*,void*); +#define ENTER(x) __cyg_profile_func_enter((void*)x,(void*)x) +#define LEAVE(x) __cyg_profile_func_exit((void*)x,(void*)x) +#else +#define ENTER(x) +#define LEAVE(x) +#endif + /* initiate a process table scan */ PROCTAB* openproc(int flags, ...) { @@ -77,103 +86,237 @@ void freeproc(proc_t* p) { } -// 2.5.xx looks like: -// -// "State:\t%s\n" -// "Tgid:\t%d\n" -// "Pid:\t%d\n" -// "PPid:\t%d\n" -// "TracerPid:\t%d\n" - -static void status2proc(const char *S, proc_t *restrict P){ - char* tmp; - unsigned i; - - // The cmd is escaped, with \\ and \n for backslash and newline. - // It certainly may contain "VmSize:" and similar crap. - if(unlikely(strncmp("Name:\t",S,6))) fprintf(stderr, "Internal error!\n"); - S += 6; - i = 0; - while(i < sizeof P->cmd - 1){ - int c = *S++; - if(unlikely(c=='\n')) break; - if(unlikely(c=='\0')) return; // should never happen - if(unlikely(c=='\\')){ - c = *S++; - if(c=='\n') break; // should never happen - if(!c) break; // should never happen - if(c=='n') c='\n'; // else we assume it is '\\' - } - P->cmd[i++] = c; - } - P->cmd[i] = '\0'; - - tmp = strstr (S,"State:\t"); - if(likely(tmp)) P->state = tmp[7]; - else fprintf(stderr, "Internal error!\n"); - - tmp = strstr (S,"PPid:"); - if(likely(tmp)) sscanf (tmp, - "PPid:\t%d\n", - &P->ppid - ); - else fprintf(stderr, "Internal error!\n"); - - tmp = strstr (S,"Uid:"); - if(likely(tmp)) sscanf (tmp, - "Uid:\t%d\t%d\t%d\t%d", - &P->ruid, &P->euid, &P->suid, &P->fuid - ); - else fprintf(stderr, "Internal error!\n"); +/////////////////////////////////////////////////////////////////////////// - tmp = strstr (S,"Gid:"); - if(likely(tmp)) sscanf (tmp, - "Gid:\t%d\t%d\t%d\t%d", - &P->rgid, &P->egid, &P->sgid, &P->fgid - ); - else fprintf(stderr, "Internal error!\n"); - - tmp = strstr (S,"VmSize:"); - if(likely(tmp)) sscanf (tmp, - "VmSize: %lu kB\n" - "VmLck: %lu kB\n" - "VmRSS: %lu kB\n" - "VmData: %lu kB\n" - "VmStk: %lu kB\n" - "VmExe: %lu kB\n" - "VmLib: %lu kB\n", - &P->vm_size, &P->vm_lock, &P->vm_rss, &P->vm_data, - &P->vm_stack, &P->vm_exe, &P->vm_lib - ); - else /* looks like an annoying kernel thread */ - { - P->vm_size = 0; - P->vm_lock = 0; - P->vm_rss = 0; - P->vm_data = 0; - P->vm_stack = 0; - P->vm_exe = 0; - P->vm_lib = 0; - } +typedef struct status_table_struct { + unsigned char name[6]; // /proc/*/status field name + short len; // name length +#ifdef LABEL_OFFSET + long offset; // jump address offset +#else + void *addr; +#endif +} status_table_struct; - // 2.1 SigPnd SigBlk SigIgn SigCat ("SigCat") - // other SigPnd SigBlk SigIgn SigCgt - // 2.5+ SigPnd ShdPnd SigBlk SigIgn SigCgt +#ifdef LABEL_OFFSET +#define F(x) {#x, sizeof(#x)-1, (int)(&&case_##x-&&base)}, +#else +#define F(x) {#x, sizeof(#x)-1, &&case_##x}, +#endif +#define NUL {"", 0, 0}, + +// Derived from: +// gperf -7 --language=ANSI-C --key-positions=1,3,4 -C -n -c sml.gperf + +static void status2proc(char *S, proc_t *restrict P){ + static const unsigned char asso[] = { + 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, 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, 56, 56, 56, 56, 56, 56, 15, 56, 56, 56, 56, 56, + 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, + 56, 30, 56, 8, 0, 0, 56, 25, 56, 5, 56, 56, 56, 0, 56, 56, + 56, 56, 56, 56, 0, 56, 56, 56, 0, 56, 56, 56, 56, 56, 56, 56 + }; + static const status_table_struct table[] = { + F(VmStk) + NUL + NUL + F(VmExe) + NUL + F(VmSize) + NUL + NUL + F(VmLib) + NUL + F(Name) + F(VmLck) + NUL + F(VmRSS) + NUL + NUL + NUL + NUL + F(ShdPnd) + NUL + F(Gid) + NUL + NUL + F(PPid) + NUL + NUL + NUL + NUL + F(SigIgn) + NUL + F(State) + NUL + NUL + F(Pid) + NUL + F(Tgid) + 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 NUL + +ENTER(0x220); + + P->vm_size = 0; + P->vm_lock = 0; + P->vm_rss = 0; + P->vm_data = 0; + P->vm_stack= 0; + P->vm_exe = 0; + P->vm_lib = 0; + + goto base; - tmp = strstr (S,"SigPnd:"); - if(likely(tmp)) sscanf (tmp, -#ifdef SIGNAL_STRING - "SigPnd: %s SigBlk: %s SigIgn: %s %*s %s", - P->signal, P->blocked, P->sigignore, P->sigcatch + for(;;){ + char *colon; + status_table_struct entry; + + // advance to next line + S = strchr(S, '\n'); + if(unlikely(!S)) break; // if no newline + S++; + + // examine a field name (hash and compare) + base: + if(unlikely(!*S)) break; + entry = table[63 & (asso[S[3]] + asso[S[2]] + asso[S[0]])]; + colon = strchr(S, ':'); + if(unlikely(!colon)) break; + if(unlikely(colon[1]!='\t')) break; + if(unlikely(colon-S != entry.len)) continue; + if(unlikely(memcmp(entry.name,S,colon-S))) continue; + + S = colon+2; // past the '\t' + +#ifdef LABEL_OFFSET + goto *(&&base + entry.offset); #else - "SigPnd: %Lx SigBlk: %Lx SigIgn: %Lx %*s %Lx", - &P->signal, &P->blocked, &P->sigignore, &P->sigcatch + goto *entry.addr; #endif - ); - else fprintf(stderr, "Internal error!\n"); -} + 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:{ + int i = 0; + while(i < sizeof P->cmd - 1){ + int c = *S++; + if(unlikely(c=='\n')) break; + if(unlikely(c=='\0')) return; // should never happen + if(unlikely(c=='\\')){ + c = *S++; + if(c=='\n') break; // should never happen + if(!c) break; // should never happen + if(c=='n') c='\n'; // else we assume it is '\\' + } + P->cmd[i++] = c; + } + P->cmd[i] = '\0'; + continue; + } + case_PPid: + P->ppid = strtol(S,&S,10); + continue; + case_Pid: + P->pid = strtol(S,&S,10); + continue; + + case_ShdPnd: + memcpy(P->signal, S, 16); + P->signal[16] = '\0'; + continue; + case_SigBlk: + memcpy(P->blocked, S, 16); + P->blocked[16] = '\0'; + continue; + case_SigCgt: + memcpy(P->sigcatch, S, 16); + P->sigcatch[16] = '\0'; + continue; + case_SigIgn: + memcpy(P->sigignore, S, 16); + P->sigignore[16] = '\0'; + continue; + case_SigPnd: + memcpy(P->signal, S, 16); + P->signal[16] = '\0'; + continue; + + case_State: + P->state = *S; + continue; + case_Tgid: + P->tgid = strtol(S,&S,10); + continue; + case_Uid: + P->ruid = strtol(S,&S,10); + P->euid = strtol(S,&S,10); + P->suid = strtol(S,&S,10); + P->fuid = strtol(S,&S,10); + continue; + case_VmData: + P->vm_data = strtol(S,&S,10); + continue; + case_VmExe: + P->vm_exe = strtol(S,&S,10); + continue; + case_VmLck: + P->vm_lock = strtol(S,&S,10); + continue; + case_VmLib: + P->vm_lib = strtol(S,&S,10); + continue; + case_VmRSS: + P->vm_rss = strtol(S,&S,10); + continue; + case_VmSize: + P->vm_size = strtol(S,&S,10); + continue; + case_VmStk: + P->vm_stack = strtol(S,&S,10); + continue; + } +LEAVE(0x220); +} +/////////////////////////////////////////////////////////////////////// // Reads /proc/*/stat files, being careful not to trip over processes with // names like ":-) 1 2 3 4 5 6". @@ -181,6 +324,8 @@ static void stat2proc(const char* S, proc_t *restrict P) { unsigned num; char* tmp; +ENTER(0x160); + /* fill in default values for older kernels */ P->exit_signal = SIGCHLD; P->processor = 0; @@ -225,8 +370,11 @@ static void stat2proc(const char* S, proc_t *restrict P) { /* -- Linux 2.2.8 to 2.5.17 end here -- */ &P->rtprio, &P->sched /* both added to 2.5.18 */ ); +LEAVE(0x160); } +///////////////////////////////////////////////////////////////////////// + static void statm2proc(const char* s, proc_t *restrict P) { int num; num = sscanf(s, "%ld %ld %ld %ld %ld %ld %ld", @@ -243,9 +391,9 @@ static int file2str(const char *directory, const char *what, char *ret, int cap) fd = open(filename, O_RDONLY, 0); if(unlikely(fd==-1)) return -1; num_read = read(fd, ret, cap - 1); - if(unlikely(num_read<=0)) num_read = -1; - else ret[num_read] = 0; close(fd); + if(unlikely(num_read<=0)) return -1; + ret[num_read] = '\0'; return num_read; } @@ -329,8 +477,8 @@ int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){ dst[n] = '\0'; i=n; while(i--){ - int c = dst[i]; - if(c<' ' || c>'~') dst[i]=' '; + int c = dst[i]; + if(c<' ' || c>'~') dst[i]=' '; } } return n; diff --git a/proc/readproc.h b/proc/readproc.h index 88fe7756..2ac033b5 100644 --- a/proc/readproc.h +++ b/proc/readproc.h @@ -133,6 +133,7 @@ typedef struct proc_t { session, /* session id */ tty, /* full device number of controlling terminal */ tpgid, /* terminal process group id */ + tgid, /* thread group ID */ exit_signal, /* might not be SIGCHLD */ processor; /* current (or most recent?) CPU */ #ifdef FLASK_LINUX -- 2.40.0