Linux 2.5.xx /proc/*/wchan

This commit is contained in:
albert 2002-12-12 21:58:12 +00:00
parent 78d2adaa15
commit 8a745812cf
5 changed files with 74 additions and 18 deletions

4
NEWS
View File

@ -1,7 +1,9 @@
procps-3.1.2 --> procps-3.1.3 procps-3.1.2 --> procps-3.1.3
top: user selection top: user selection
sysctl: -e sysctl: add -e for Red Hat 8.0 boot scripts
sysctl: the obvious --help, -V, and --version
sysctl: some command line error checking
w: stdout, not stderr -- thanks to Sander van Malssen w: stdout, not stderr -- thanks to Sander van Malssen
procps-3.1.1 --> procps-3.1.2 procps-3.1.1 --> procps-3.1.2

View File

@ -465,6 +465,8 @@ static void default_message(const char *restrict format, ...) {
/*********************************/ /*********************************/
static int use_wchan_file;
int open_psdb_message(const char *restrict override, void (*message)(const char *, ...)) { int open_psdb_message(const char *restrict override, void (*message)(const char *, ...)) {
static const char *sysmap_paths[] = { static const char *sysmap_paths[] = {
"/boot/System.map-%s", "/boot/System.map-%s",
@ -474,26 +476,45 @@ int open_psdb_message(const char *restrict override, void (*message)(const char
"/System.map", "/System.map",
NULL NULL
}; };
struct stat sbuf;
struct utsname uts; struct utsname uts;
char path[64]; char path[64];
const char **fmt = sysmap_paths; const char **fmt = sysmap_paths;
const char *env; const char *sm;
read_and_parse();
#ifdef SYSMAP_FILENAME /* debug feature */ #ifdef SYSMAP_FILENAME /* debug feature */
override = SYSMAP_FILENAME; override = SYSMAP_FILENAME;
#endif #endif
if(override){ /* ought to search some path */
if(sysmap_mmap(override, message)) return 0; // first allow for a user-selected System.map file
return -1; /* ought to return "Namelist not found." */ if(
(sm=override)
||
(sm=getenv("PS_SYSMAP"))
||
(sm=getenv("PS_SYSTEM_MAP"))
){
read_and_parse();
if(sysmap_mmap(sm, message)) return 0;
/* failure is better than ignoring the user & using bad data */ /* failure is better than ignoring the user & using bad data */
return -1; /* ought to return "Namelist not found." */
} }
/* Arrrgh, the old man page and code did not match. */
if ((env = getenv("PS_SYSMAP")) && sysmap_mmap(env, message)) return 0; // next try the Linux 2.5.xx method
if ((env = getenv("PS_SYSTEM_MAP")) && sysmap_mmap(env, message)) return 0; if(!stat("/proc/self/wchan", &sbuf)){
use_wchan_file = 1; // hack
return 0;
}
// finally, search for the System.map file
uname(&uts); uname(&uts);
do{ do{
int did_ksyms = 0;
snprintf(path, sizeof path, *fmt, uts.release); snprintf(path, sizeof path, *fmt, uts.release);
if (sysmap_mmap(path, message)) return 0; if(!stat(path, &sbuf)){
if (did_ksyms++) read_and_parse();
if (sysmap_mmap(path, message)) return 0;
}
}while(*++fmt); }while(*++fmt);
/* TODO: Without System.map, no need to keep ksyms loaded. */ /* TODO: Without System.map, no need to keep ksyms loaded. */
return -1; return -1;
@ -507,18 +528,51 @@ int open_psdb(const char *restrict override) {
/***************************************/ /***************************************/
const char * read_wchan_file(unsigned pid){
static char buf[64];
const char *ret = buf;
ssize_t num;
int fd;
snprintf(buf, sizeof buf, "/proc/%d/wchan", pid);
fd = open(buf, O_RDONLY);
if(fd==-1) return "?";
num = read(fd, buf, sizeof buf - 1);
close(fd);
if(num<1) return "?"; // allow for "0"
buf[num] = '\0';
if(buf[0]=='0' && buf[1]=='\0') return "-";
// would skip over numbers if they existed -- but no
switch(*ret){
case 's': if(!strncmp(ret, "sys_", 4)) ret += 4; break;
case 'd': if(!strncmp(ret, "do_", 3)) ret += 3; break;
case '_': while(*ret=='_') ret++; break;
}
return ret;
}
/***************************************/
#define MAX_OFFSET (0x1000*sizeof(long)) /* past this is generally junk */ #define MAX_OFFSET (0x1000*sizeof(long)) /* past this is generally junk */
/* return pointer to temporary static buffer with function name */ /* return pointer to temporary static buffer with function name */
const char * wchan(unsigned long address) { const char * wchan(unsigned long address, unsigned pid) {
const symb *mod_symb; const symb *mod_symb;
const symb *map_symb; const symb *map_symb;
const symb *good_symb; const symb *good_symb;
const char *ret; const char *ret;
unsigned hash = (address >> 4) & 0xff; /* got 56/63 hits & 7/63 misses */ unsigned hash;
if(!address) return dash;
read_and_parse();
// can't cache it due to a race condition :-(
if(use_wchan_file) return read_wchan_file(pid);
if(!address) return dash;
read_and_parse();
hash = (address >> 4) & 0xff; /* got 56/63 hits & 7/63 misses */
if(hashtable[hash].addr == address) return hashtable[hash].name; if(hashtable[hash].addr == address) return hashtable[hash].name;
mod_symb = search(address, ksyms_index, ksyms_count); mod_symb = search(address, ksyms_index, ksyms_count);
if(!mod_symb) mod_symb = &fail; if(!mod_symb) mod_symb = &fail;

View File

@ -5,7 +5,7 @@
EXTERN_C_BEGIN EXTERN_C_BEGIN
extern const char * wchan(unsigned long address); extern const char * wchan(unsigned long address, unsigned pid);
extern int open_psdb(const char *restrict override); extern int open_psdb(const char *restrict override);
extern int open_psdb_message(const char *restrict override, void (*message)(const char *, ...)); extern int open_psdb_message(const char *restrict override, void (*message)(const char *, ...));

View File

@ -567,7 +567,7 @@ static int pr_wchan(char *restrict const outbuf, const proc_t *restrict const pp
*/ */
if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "%s", "-"); if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "%s", "-");
if(wchan_is_number) return snprintf(outbuf, COLWID, "%lx", pp->wchan & 0xffffff); if(wchan_is_number) return snprintf(outbuf, COLWID, "%lx", pp->wchan & 0xffffff);
return snprintf(outbuf, COLWID, "%s", wchan(pp->wchan)); return snprintf(outbuf, COLWID, "%s", wchan(pp->wchan, pp->pid));
} }
/* Terrible trunctuation, like BSD crap uses: I999 J999 K999 */ /* Terrible trunctuation, like BSD crap uses: I999 J999 K999 */
@ -773,7 +773,7 @@ static int pr_wname(char *restrict const outbuf, const proc_t *restrict const pp
* more than one thread waiting in the kernel. * more than one thread waiting in the kernel.
*/ */
if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "%s", "-"); if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "%s", "-");
return snprintf(outbuf, COLWID, "%s", wchan(pp->wchan)); return snprintf(outbuf, COLWID, "%s", wchan(pp->wchan, pp->pid));
} }
static int pr_nwchan(char *restrict const outbuf, const proc_t *restrict const pp){ static int pr_nwchan(char *restrict const outbuf, const proc_t *restrict const pp){

2
top.c
View File

@ -3019,7 +3019,7 @@ static void task_show (const WIN_t *q, const proc_t *p)
#endif #endif
MKCOL((long)p->wchan); MKCOL((long)p->wchan);
} else { } else {
MKCOL(wchan(p->wchan)); MKCOL(wchan(p->wchan, p->pid));
} }
break; break;