summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2005-06-08 22:36:44 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2005-06-08 22:36:44 +0000
commitd8d35b90679f0c4c39638afa56d4dfa1a14f0cd4 (patch)
tree2da4281c272a7fe88962c1caba31e6b562de1a09 /usr.bin
parent09fc260787b747e5484efa3b2527d23b187115f3 (diff)
Multi-cpu support for top. Each cpu now gets its own stats line.
Based on work by todd@ at the hackathon.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/top/display.c244
-rw-r--r--usr.bin/top/display.h6
-rw-r--r--usr.bin/top/layout.h12
-rw-r--r--usr.bin/top/machine.c63
-rw-r--r--usr.bin/top/machine.h4
-rw-r--r--usr.bin/top/top.c5
-rw-r--r--usr.bin/top/top.h10
-rw-r--r--usr.bin/top/utils.c15
-rw-r--r--usr.bin/top/utils.h4
9 files changed, 238 insertions, 125 deletions
diff --git a/usr.bin/top/display.c b/usr.bin/top/display.c
index f5d1e289c77..a652d300708 100644
--- a/usr.bin/top/display.c
+++ b/usr.bin/top/display.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: display.c,v 1.19 2005/04/13 02:33:09 deraadt Exp $ */
+/* $OpenBSD: display.c,v 1.20 2005/06/08 22:36:43 millert Exp $ */
/*
* Top users/processes display for Unix
@@ -46,8 +46,11 @@
*/
#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/sched.h>
#include <stdio.h>
#include <ctype.h>
+#include <err.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
@@ -74,7 +77,7 @@ static int last_hi = 0; /* used in u_process and u_endscreen */
static int lastline = 0;
static int display_width = MAX_COLS;
-static char *cpustates_tag(void);
+static char *cpustates_tag(int);
static int string_count(char **);
static void summary_format(char *, size_t, int *, char **);
static void line_update(char *, char *, int, int);
@@ -94,11 +97,20 @@ static int num_procstates;
static int num_cpustates;
static int *lprocstates;
-static int *lcpustates;
+static int64_t **lcpustates;
static int *cpustate_columns;
static int cpustate_total_length;
+/* display ips */
+int y_mem;
+int y_message;
+int y_header;
+int y_idlecursor;
+int y_procs;
+extern int ncpu;
+int Header_lines;
+
static enum {
OFF, ON, ERASE
} header_status = ON;
@@ -126,8 +138,8 @@ display_resize(void)
display_width = MAX_COLS - 1;
/* now, allocate space for the screen buffer */
- screenbuf = (char *) malloc(display_lines * display_width);
- if (screenbuf == (char *) NULL)
+ screenbuf = malloc(display_lines * display_width);
+ if (screenbuf == NULL)
return (-1);
/* return number of lines available */
@@ -138,9 +150,16 @@ display_resize(void)
int
display_init(struct statics * statics)
{
- int display_lines, *ip, i;
+ int display_lines, *ip, i, cpu;
char **pp;
+ y_mem = 2 + ncpu;
+ y_message = 3 + ncpu;
+ y_header = 4 + ncpu;
+ y_idlecursor = 3 + ncpu;
+ y_procs = 5 + ncpu;
+ Header_lines = 5 + ncpu;
+
/* call resize to do the dirty work */
display_lines = display_resize();
@@ -149,12 +168,24 @@ display_init(struct statics * statics)
/* save pointers and allocate space for names */
procstate_names = statics->procstate_names;
num_procstates = string_count(procstate_names);
- lprocstates = (int *) malloc(num_procstates * sizeof(int));
+ lprocstates = malloc(num_procstates * sizeof(int));
+ if (lprocstates == NULL)
+ err(1, NULL);
cpustate_names = statics->cpustate_names;
num_cpustates = string_count(cpustate_names);
- lcpustates = (int *) malloc(num_cpustates * sizeof(int));
- cpustate_columns = (int *) malloc(num_cpustates * sizeof(int));
+ lcpustates = malloc(ncpu * sizeof(int64_t *));
+ if (lcpustates == NULL)
+ err(1, NULL);
+ for (cpu = 0; cpu < ncpu; cpu++) {
+ lcpustates[cpu] = malloc(num_cpustates * sizeof(int64_t));
+ if (lcpustates[cpu] == NULL)
+ err(1, NULL);
+ }
+
+ cpustate_columns = malloc(num_cpustates * sizeof(int));
+ if (cpustate_columns == NULL)
+ err(1, NULL);
memory_names = statics->memory_names;
@@ -339,112 +370,149 @@ static int cpustates_column;
/* cpustates_tag() calculates the correct tag to use to label the line */
static char *
-cpustates_tag(void)
+cpustates_tag(int cpu)
{
- static char *short_tag = "CPU: ";
- static char *long_tag = "CPU states: ";
- char *use;
+ static char *tag;
+ static int cpulen, old_width;
+ int i;
- /*
- * if length + strlen(long_tag) >= screen_width, then we have to use
- * the shorter tag (we subtract 2 to account for ": ")
- */
- if (cpustate_total_length + (int) strlen(long_tag) - 2 >= screen_width)
- use = short_tag;
- else
- use = long_tag;
-
- /* set cpustates_column accordingly then return result */
- cpustates_column = strlen(use);
- return (use);
+ if (cpulen == 0 && ncpu > 1) {
+ /* compute length of the cpu string */
+ for (i = ncpu; i > 0; cpulen++, i /= 10)
+ continue;
+ }
+
+ if (old_width == screen_width) {
+ if (ncpu > 1) {
+ /* just store the cpu number in the tag */
+ i = tag[3 + cpulen];
+ snprintf(tag + 3, cpulen + 1, "%.*d", cpulen, cpu);
+ tag[3 + cpulen] = i;
+ }
+ } else {
+ /*
+ * use a long tag if it will fit, otherwise use short one.
+ */
+ free(tag);
+ if (cpustate_total_length + 10 + cpulen >= screen_width)
+ i = asprintf(&tag, "CPU%.*d: ", cpulen, cpu);
+ else
+ i = asprintf(&tag, "CPU%.*d states: ", cpulen, cpu);
+ if (i == -1)
+ tag = NULL;
+ else {
+ cpustates_column = strlen(tag);
+ old_width = screen_width;
+ }
+ }
+ return (tag);
}
void
-i_cpustates(int *states)
+i_cpustates(int64_t *ostates)
{
- int i = 0, value;
+ int i, cpu, value;
+ int64_t *states;
char **names = cpustate_names, *thisname;
- /* print tag and bump lastline */
- printf("\n%s", cpustates_tag());
- lastline++;
+ for (cpu = 0; cpu < ncpu; cpu++) {
+ /* print tag and bump lastline */
+ printf("\n%s", cpustates_tag(cpu));
+ lastline++;
- /* now walk thru the names and print the line */
- while ((thisname = *names++) != NULL) {
- if (*thisname != '\0') {
- /* retrieve the value and remember it */
- value = *states++;
-
- /* if percentage is >= 1000, print it as 100% */
- printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
- i++ == 0 ? "" : ", ",
- ((float) value) / 10.,
- thisname);
+ /* now walk thru the names and print the line */
+ names = cpustate_names;
+ i = 0;
+ states = ostates + (CPUSTATES * cpu);
+ while ((thisname = *names++) != NULL) {
+ if (*thisname != '\0') {
+ /* retrieve the value and remember it */
+ value = *states++;
+
+ /* if percentage is >= 1000, print it as 100% */
+ printf((value >= 1000 ? "%s%4.0f%% %s" :
+ "%s%4.1f%% %s"), i++ == 0 ? "" : ", ",
+ ((float) value) / 10., thisname);
+ }
}
- }
- /* copy over values into "last" array */
- memcpy(lcpustates, states, num_cpustates * sizeof(int));
+ /* copy over values into "last" array */
+ memcpy(lcpustates[cpu], ostates, num_cpustates * sizeof(int64_t));
+ }
}
void
-u_cpustates(int *states)
+u_cpustates(int64_t *ostates)
{
- char **names = cpustate_names, *thisname;
- int value, *lp, *colp;
-
- Move_to(cpustates_column, y_cpustates);
- lastline = y_cpustates;
- lp = lcpustates;
- colp = cpustate_columns;
-
- /* we could be much more optimal about this */
- while ((thisname = *names++) != NULL) {
- if (*thisname != '\0') {
- /* did the value change since last time? */
- if (*lp != *states) {
- /* yes, move and change */
- Move_to(cpustates_column + *colp, y_cpustates);
- lastline = y_cpustates;
-
- /* retrieve value and remember it */
- value = *states;
-
- /* if percentage is >= 1000, print it as 100% */
- printf((value >= 1000 ? "%4.0f" : "%4.1f"),
- ((double) value) / 10.);
+ char **names, *thisname;
+ int cpu, value, *colp;
+ int64_t *lp, *states;
+
+ for (cpu = 0; cpu < ncpu; cpu++) {
+ lastline = y_cpustates + cpu;
+ states = ostates + (CPUSTATES * cpu);
+ Move_to(cpustates_column, lastline);
+ lp = lcpustates[cpu];
+ colp = cpustate_columns;
+
+ /* we could be much more optimal about this */
+ names = cpustate_names;
+ while ((thisname = *names++) != NULL) {
+ if (*thisname != '\0') {
+ /* did the value change since last time? */
+ if (*lp != *states) {
+ /* yes, move and change */
+ lastline = y_cpustates + cpu;
+ Move_to(cpustates_column + *colp,
+ lastline);
+
+ /* retrieve value and remember it */
+ value = *states;
+
+ /* if percentage is >= 1000,
+ * print it as 100%
+ */
+ printf((value >= 1000 ? "%4.0f" :
+ "%4.1f"), ((double) value) / 10.);
- /* remember it for next time */
- *lp = *states;
+ /* remember it for next time */
+ *lp = *states;
+ }
}
+ /* increment and move on */
+ lp++;
+ states++;
+ colp++;
}
- /* increment and move on */
- lp++;
- states++;
- colp++;
}
}
void
z_cpustates(void)
{
- char **names = cpustate_names, *thisname;
- int i = 0, *lp;
+ char **names, *thisname;
+ int cpu, i;
+ int64_t *lp;
- /* show tag and bump lastline */
- printf("\n%s", cpustates_tag());
- lastline++;
+ for (cpu = 0; cpu < ncpu; cpu++) {
+ /* show tag and bump lastline */
+ printf("\n%s", cpustates_tag(cpu));
+ lastline++;
- while ((thisname = *names++) != NULL) {
- if (*thisname != '\0')
- printf("%s %% %s", i++ == 0 ? "" : ", ", thisname);
- }
+ names = cpustate_names;
+ i = 0;
+ while ((thisname = *names++) != NULL) {
+ if (*thisname != '\0')
+ printf("%s %% %s", i++ == 0 ? "" : ", ",
+ thisname);
+ }
- /* fill the "last" array with all -1s, to insure correct updating */
- lp = lcpustates;
- i = num_cpustates;
- while (--i >= 0)
- *lp++ = -1;
+ /* fill the "last" array with all -1s, to ensure correct updating */
+ lp = lcpustates[cpu];
+ i = num_cpustates;
+ while (--i >= 0)
+ *lp++ = -1;
+ }
}
static char memory_buffer[MAX_COLS];
diff --git a/usr.bin/top/display.h b/usr.bin/top/display.h
index 532e27c6fa3..643efecc3e3 100644
--- a/usr.bin/top/display.h
+++ b/usr.bin/top/display.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: display.h,v 1.6 2003/06/13 04:29:59 pvalchev Exp $ */
+/* $OpenBSD: display.h,v 1.7 2005/06/08 22:36:43 millert Exp $ */
/*
* Top users/processes display for Unix
@@ -40,8 +40,8 @@ extern void u_loadave(int, double *);
extern void i_timeofday(time_t *);
extern void i_procstates(int, int *);
extern void u_procstates(int, int *);
-extern void i_cpustates(int *);
-extern void u_cpustates(int *);
+extern void i_cpustates(int64_t *);
+extern void u_cpustates(int64_t *);
extern void z_cpustates(void);
extern void i_memory(int *);
extern void u_memory(int *);
diff --git a/usr.bin/top/layout.h b/usr.bin/top/layout.h
index 5b91271d32f..c3e1264ef0f 100644
--- a/usr.bin/top/layout.h
+++ b/usr.bin/top/layout.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: layout.h,v 1.2 2002/07/15 17:20:36 deraadt Exp $ */
+/* $OpenBSD: layout.h,v 1.3 2005/06/08 22:36:43 millert Exp $ */
/*
* Top users/processes display for Unix
@@ -46,12 +46,12 @@
#define x_brkdn 15
#define y_brkdn 1
#define x_mem 8
-#define y_mem 3
-#define y_message 4
+extern int y_mem;
+extern int y_message;
#define x_header 0
-#define y_header 5
+extern int y_header;
#define x_idlecursor 0
-#define y_idlecursor 4
-#define y_procs 6
+extern int y_idlecursor;
+extern int y_procs;
#define y_cpustates 2
diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c
index 0cb2d9a9065..1950a27a706 100644
--- a/usr.bin/top/machine.c
+++ b/usr.bin/top/machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machine.c,v 1.47 2004/12/06 15:57:04 markus Exp $ */
+/* $OpenBSD: machine.c,v 1.48 2005/06/08 22:36:43 millert Exp $ */
/*-
* Copyright (c) 1994 Thorsten Lockert <tholo@sigmasoft.com>
@@ -96,9 +96,9 @@ char *state_abbrev[] = {
static int stathz;
/* these are for calculating cpu state percentages */
-static long cp_time[CPUSTATES];
-static long cp_old[CPUSTATES];
-static long cp_diff[CPUSTATES];
+static int64_t **cp_time;
+static int64_t **cp_old;
+static int64_t **cp_diff;
/* these are for detailing the process states */
int process_states[8];
@@ -109,7 +109,7 @@ char *procstatenames[] = {
};
/* these are for detailing the cpu states */
-int cpu_states[CPUSTATES];
+int64_t *cpu_states;
char *cpustatenames[] = {
"user", "nice", "system", "interrupt", "idle", NULL
};
@@ -162,12 +162,28 @@ int
machine_init(struct statics *statics)
{
size_t size = sizeof(ncpu);
- int mib[2], pagesize;
+ int mib[2], pagesize, cpu;
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
if (sysctl(mib, 2, &ncpu, &size, NULL, 0) == -1)
return (-1);
+ cpu_states = malloc(ncpu * CPUSTATES * sizeof(int64_t));
+ if (cpu_states == NULL)
+ err(1, NULL);
+ cp_time = malloc(ncpu * sizeof(int64_t *));
+ cp_old = malloc(ncpu * sizeof(int64_t *));
+ cp_diff = malloc(ncpu * sizeof(int64_t *));
+ if (cp_time == NULL || cp_old == NULL || cp_diff == NULL)
+ err(1, NULL);
+ for (cpu = 0; cpu < ncpu; cpu++) {
+ cp_time[cpu] = malloc(CPUSTATES * sizeof(int64_t));
+ cp_old[cpu] = malloc(CPUSTATES * sizeof(int64_t));
+ cp_diff[cpu] = malloc(CPUSTATES * sizeof(int64_t));
+ if (cp_time[cpu] == NULL || cp_old[cpu] == NULL ||
+ cp_diff[cpu] == NULL)
+ err(1, NULL);
+ }
stathz = getstathz();
if (stathz == -1)
@@ -216,16 +232,37 @@ get_system_info(struct system_info *si)
{
static int sysload_mib[] = {CTL_VM, VM_LOADAVG};
static int vmtotal_mib[] = {CTL_VM, VM_METER};
- static int cp_time_mib[] = {CTL_KERN, KERN_CPTIME};
struct loadavg sysload;
struct vmtotal vmtotal;
double *infoloadp;
size_t size;
int i;
-
- size = sizeof(cp_time);
- if (sysctl(cp_time_mib, 2, &cp_time, &size, NULL, 0) < 0)
- warn("sysctl kern.cp_time failed");
+ int64_t *tmpstate;
+
+ if (ncpu > 1) {
+ size = CPUSTATES * sizeof(int64_t);
+ for (i = 0; i < ncpu; i++) {
+ int cp_time_mib[] = {CTL_KERN, KERN_CPTIME2, i};
+ tmpstate = cpu_states + (CPUSTATES * i);
+ if (sysctl(cp_time_mib, 3, cp_time[i], &size, NULL, 0) < 0)
+ warn("sysctl kern.cp_time2 failed");
+ /* convert cp_time2 counts to percentages */
+ (void) percentages(CPUSTATES, tmpstate, cp_time[i],
+ cp_old[i], cp_diff[i]);
+ }
+ } else {
+ int cp_time_mib[] = {CTL_KERN, KERN_CPTIME};
+ long cp_time_tmp[CPUSTATES];
+
+ size = sizeof(cp_time_tmp);
+ if (sysctl(cp_time_mib, 2, cp_time_tmp, &size, NULL, 0) < 0)
+ warn("sysctl kern.cp_time failed");
+ for (i = 0; i < CPUSTATES; i++)
+ cp_time[0][i] = cp_time_tmp[i];
+ /* convert cp_time counts to percentages */
+ (void) percentages(CPUSTATES, cpu_states, cp_time[0],
+ cp_old[0], cp_diff[0]);
+ }
size = sizeof(sysload);
if (sysctl(sysload_mib, 2, &sysload, &size, NULL, 0) < 0)
@@ -234,8 +271,6 @@ get_system_info(struct system_info *si)
for (i = 0; i < 3; i++)
*infoloadp++ = ((double) sysload.ldavg[i]) / sysload.fscale;
- /* convert cp_time counts to percentages */
- (void) percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
/* get total -- systemwide main memory usage structure */
size = sizeof(vmtotal);
@@ -380,7 +415,7 @@ state_abbr(struct kinfo_proc2 *pp)
static char buf[10];
if (ncpu > 1 && pp->p_cpuid != KI_NOCPU)
- snprintf(buf, sizeof buf, "%s/%d",
+ snprintf(buf, sizeof buf, "%s/%llu",
state_abbrev[(unsigned char)pp->p_stat], pp->p_cpuid);
else
snprintf(buf, sizeof buf, "%s",
diff --git a/usr.bin/top/machine.h b/usr.bin/top/machine.h
index 5a7adc8097c..4a7243cb108 100644
--- a/usr.bin/top/machine.h
+++ b/usr.bin/top/machine.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: machine.h,v 1.12 2004/10/07 06:26:12 otto Exp $ */
+/* $OpenBSD: machine.h,v 1.13 2005/06/08 22:36:43 millert Exp $ */
/*
* Top users/processes display for Unix
@@ -55,7 +55,7 @@ struct system_info {
int p_active; /* number of procs considered
* "active" */
int *procstates;
- int *cpustates;
+ int64_t *cpustates;
int *memory;
};
diff --git a/usr.bin/top/top.c b/usr.bin/top/top.c
index 1c4be009ecb..e0cb26faec9 100644
--- a/usr.bin/top/top.c
+++ b/usr.bin/top/top.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: top.c,v 1.38 2005/05/14 09:03:31 jmc Exp $ */
+/* $OpenBSD: top.c,v 1.39 2005/06/08 22:36:43 millert Exp $ */
/*
* Top users/processes display for Unix
@@ -42,6 +42,7 @@ const char copyright[] = "Copyright (c) 1984 through 1996, William LeFebvre";
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
+#include <sys/stat.h>
/* includes specific to top */
#include "display.h" /* interface to display package */
@@ -79,7 +80,7 @@ int order_index;
/* pointers to display routines */
void (*d_loadave)(int, double *) = i_loadave;
void (*d_procstates)(int, int *) = i_procstates;
-void (*d_cpustates)(int *) = i_cpustates;
+void (*d_cpustates)(int64_t *) = i_cpustates;
void (*d_memory)(int *) = i_memory;
void (*d_message)(void) = i_message;
void (*d_header)(char *) = i_header;
diff --git a/usr.bin/top/top.h b/usr.bin/top/top.h
index d99393704e5..b2165b35200 100644
--- a/usr.bin/top/top.h
+++ b/usr.bin/top/top.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: top.h,v 1.5 2003/06/13 21:52:25 deraadt Exp $ */
+/* $OpenBSD: top.h,v 1.6 2005/06/08 22:36:43 millert Exp $ */
/*
* Top users/processes display for Unix
@@ -40,7 +40,7 @@
#define VERSION 3
/* Number of lines of header information on the standard screen */
-#define Header_lines 6
+extern int Header_lines;
/* Maximum number of columns allowed for display */
#define MAX_COLS 128
@@ -82,3 +82,9 @@ extern uid_t userid(char *);
/* version.c */
extern char *version_string(void);
+extern int y_mem;
+extern int y_message;
+extern int y_header;
+extern int y_idlecursor;
+extern int y_procs;
+extern int num_CPUS;
diff --git a/usr.bin/top/utils.c b/usr.bin/top/utils.c
index 17cf3576243..38e4dd5577b 100644
--- a/usr.bin/top/utils.c
+++ b/usr.bin/top/utils.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: utils.c,v 1.15 2004/11/22 15:26:53 pat Exp $ */
+/* $OpenBSD: utils.c,v 1.16 2005/06/08 22:36:43 millert Exp $ */
/*
* Top users/processes display for Unix
@@ -34,6 +34,7 @@
#include <sys/param.h>
#include <sys/sysctl.h>
+#include <err.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -162,10 +163,12 @@ argparse(char *line, int *cntp)
cnt += 3;
/* allocate a char * array to hold the pointers */
- argarray = (char **) malloc(cnt * sizeof(char *));
+ if ((argarray = malloc(cnt * sizeof(char *))) == NULL)
+ err(1, NULL);
/* allocate another array to hold the strings themselves */
- args = (char *) malloc(length + 2);
+ if ((args = malloc(length + 2)) == NULL)
+ err(1, NULL);
/* initialization for main loop */
from = line;
@@ -207,9 +210,9 @@ argparse(char *line, int *cntp)
* useful on BSD mchines for calculating cpu state percentages.
*/
int
-percentages(int cnt, int *out, long *new, long *old, long *diffs)
+percentages(int cnt, int64_t *out, int64_t *new, int64_t *old, int64_t *diffs)
{
- long change, total_change, *dp, half_total;
+ int64_t change, total_change, *dp, half_total;
int i;
/* initialization */
@@ -220,7 +223,7 @@ percentages(int cnt, int *out, long *new, long *old, long *diffs)
for (i = 0; i < cnt; i++) {
if ((change = *new - *old) < 0) {
/* this only happens when the counter wraps */
- change = ((unsigned int)*new - (unsigned int)*old);
+ change = (*new - *old);
}
total_change += (*dp++ = change);
*old++ = *new++;
diff --git a/usr.bin/top/utils.h b/usr.bin/top/utils.h
index 4d0261da47d..e38e4b2f593 100644
--- a/usr.bin/top/utils.h
+++ b/usr.bin/top/utils.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: utils.h,v 1.7 2004/10/07 06:26:12 otto Exp $ */
+/* $OpenBSD: utils.h,v 1.8 2005/06/08 22:36:43 millert Exp $ */
/*
* Top users/processes display for Unix
@@ -36,7 +36,7 @@ char *format_uid(uid_t);
int digits(int);
int string_index(char *, char **);
char **argparse(char *, int *);
-int percentages(int, int *, long *, long *, long *);
+int percentages(int, int64_t *, int64_t *, int64_t *, int64_t *);
char *format_time(time_t);
char *format_k(int);
int find_pid(pid_t);