Return to BSD News archive
Path: sserve!newshost.anu.edu.au!munnari.oz.au!constellation!paladin.american.edu!europa.eng.gtefsd.com!howland.reston.ans.net!xlink.net!zib-berlin.de!cs.tu-berlin.de!wosch From: wosch@cs.tu-berlin.de (Wolfram Schneider) Newsgroups: comp.os.386bsd.apps Subject: top(1l) patch for ``last pid'' Date: 23 Dec 1993 14:11:39 GMT Organization: Komische Universitaet, Charlottenburg Lines: 632 Message-ID: <2fc8uv$cpd@news.cs.tu-berlin.de> NNTP-Posting-Host: beauvoir.cs.tu-berlin.de Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit This is a patch for the unused feature ``last pid'' (and some minor bugs, swap usage). NOTE: You're going to have to recompile the kernel after you modify /sys/kern/kern_fork.c file!!! Wolfram ---------------------------------------------------------------------- last pid: 10205155; load averages: 1.29, 1.26, 1.23 00:31:47 ^^^^^^^^^^^^^^^^^^ 22 processes: 19 sleeping, 3 running Memory: Free: 5224K Act: 2308K Inact: 7576K Wired: 3768K Swap: 54% PID USERNAME PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND 15586 wosch 105 20 168K 120K run 614:31 38.67% 38.67% sh 11160 wosch 18 0 624K 508K sleep 0:01 1.17% 1.17% bash 11637 wosch 30 0 400K 292K run 0:00 0.00% 0.00% top-3.3patched 11641 wosch 105 20 168K 12K run 0:00 0.00% 0.00% sh ---------------------------------------------------------------------- ---------------------------------------------------------------------- # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # README-FreeBSD.last_pid # command.c.diff # display.c.diff # kern_fork.c.diff # m_386bsd.c.diff # echo x - README-FreeBSD.last_pid sed 's/^X//' >README-FreeBSD.last_pid << 'END-of-README-FreeBSD.last_pid' X# unpack Xmkdir top-3.3beta; cd top-3.3beta Xtar xfvz ../top33beta.tgz Xsh ../top-patch.shar X X# patch for top Xpatch -p < command.c.diff Xpatch -p < display.c.diff Xpatch -p < m_386bsd.c.diff X X# kernel patch Xsu root Xcd /sys/kern Xpatch -p < kern_fork.c.diff Xsuspend X X# compile top X./Configure 386bsd Xmake X END-of-README-FreeBSD.last_pid echo x - command.c.diff sed 's/^X//' >command.c.diff << 'END-of-command.c.diff' X*** commands.c Thu Jul 8 00:58:03 1993 X--- /home/w/wosch/../wosch3/tmp/top-3.3/commands.c Thu Dec 16 18:33:58 1993 X*************** X*** 454,460 **** X X #if defined(PRIO_MIN) && defined(PRIO_MAX) X /* check for validity */ X! if (procnum == -1 || prio <= PRIO_MIN || prio >= PRIO_MAX) X { X return(" bad priority value"); X } X--- 454,460 ---- X X #if defined(PRIO_MIN) && defined(PRIO_MAX) X /* check for validity */ X! if (procnum == -1 || prio < PRIO_MIN || prio > PRIO_MAX) X { X return(" bad priority value"); X } END-of-command.c.diff echo x - display.c.diff sed 's/^X//' >display.c.diff << 'END-of-display.c.diff' X*** display.c Mon Aug 30 21:04:14 1993 X--- /home/w/wosch/work/top-3.3.2/display.c Tue Dec 21 15:28:45 1993 X*************** X*** 160,166 **** X /* mpid == -1 implies this system doesn't have an _mpid */ X if (mpid != -1) X { X! printf("last pid: %5d; ", mpid); X } X X printf("load averages"); X--- 160,166 ---- X /* mpid == -1 implies this system doesn't have an _mpid */ X if (mpid != -1) X { X! printf("last pid: %7d; ", mpid); X } X X printf("load averages"); X*************** X*** 188,194 **** X if (mpid != lmpid) X { X Move_to(x_lastpid, y_lastpid); X! printf("%5d", mpid); X lmpid = mpid; X } X X--- 188,194 ---- X if (mpid != lmpid) X { X Move_to(x_lastpid, y_lastpid); X! printf("%7d", mpid); X lmpid = mpid; X } X X*************** X*** 197,207 **** X } X else X { X! i = x_loadave_nompid; X } X X /* move into position for load averages */ X! Move_to(i, y_loadave); X X /* display new load averages */ X /* we should optimize this and only display changes */ X--- 197,207 ---- X } X else X { X! i = x_loadave_nompid-3; X } X X /* move into position for load averages */ X! Move_to(i+2, y_loadave); X X /* display new load averages */ X /* we should optimize this and only display changes */ END-of-display.c.diff echo x - kern_fork.c.diff sed 's/^X//' >kern_fork.c.diff << 'END-of-kern_fork.c.diff' X*** kern_fork.c Sat Oct 16 16:24:03 1993 X--- /sys/kern/kern_fork.c Thu Dec 16 22:19:21 1993 X*************** X*** 47,52 **** X--- 47,55 ---- X #include "ktrace.h" X #include "vm/vm.h" X X+ int mpid; /* max pid */ X+ unsigned long int tpid = 0; /* total pid */ X+ X /* ARGSUSED */ X fork(p, uap, retval) X struct proc *p; X*************** X*** 292,296 **** X--- 295,306 ---- X */ X retval[0] = p2->p_pid; X retval[1] = 0; X+ X+ mpid = nextpid; X+ X+ if (mpid > tpid) X+ tpid = mpid; X+ else X+ tpid++; X return (0); X } END-of-kern_fork.c.diff echo x - m_386bsd.c.diff sed 's/^X//' >m_386bsd.c.diff << 'END-of-m_386bsd.c.diff' X*** machine/m_386bsd.c Sat Sep 4 00:00:51 1993 X--- ../../../wosch3/tmp/top-3.3/machine/m_386bsd.c Tue Dec 21 15:11:22 1993 X*************** X*** 14,20 **** X * LIBS: -lutil X * X * AUTHOR: Steve Hocking (adapted from Christos Zoulas <christos@ee.cornell.edu>) X! * Updated by Andrew Herbert <andrew@werple.apana.org.au> X */ X X #include <sys/types.h> X--- 14,23 ---- X * LIBS: -lutil X * X * AUTHOR: Steve Hocking (adapted from Christos Zoulas <christos@ee.cornell.edu>) X! * Updated by Andrew Herbert <andrew@werple.apana.org.au> X! * Added swap statistics Wolfram Schneider <wosch@cs.tu-berlin.de> X! * Changed swap format Nate Williams <nate@bsd.coe.montana.edu> X! * Added last pid Wolfram Schneider <wosch@cs.tu-berlin.de> X */ X X #include <sys/types.h> X*************** X*** 42,53 **** X #include <sys/vmmeter.h> X X X! /* #define PATCHED_KVM /* READ THE FOLLOWING NOTE: */ X /* define this ONLY if your version of 386bsd X has patchkit 2.4 installed. */ X X /* #define TOTAL_WORKING */ /* Uncomment when the total structure in */ X /* the kernel actually works */ X #define DOSWAP X X #include "top.h" X--- 45,75 ---- X #include <sys/vmmeter.h> X X X! #define PATCHED_KVM /* READ THE FOLLOWING NOTE: */ X /* define this ONLY if your version of 386bsd X has patchkit 2.4 installed. */ X X /* #define TOTAL_WORKING */ /* Uncomment when the total structure in */ X /* the kernel actually works */ X+ X+ /* #define MPID */ /* define this ONLY if you has X+ * kern_fork.c patched. See below. X+ * X+ * test with: strings -a /386bsd | grep _mpid X+ * X+ * mpid is the last pid. X+ * 100 <= _mpid <= PID_MAX X+ */ X+ X+ /* #define TPID */ /* tpid is the total number of used pid. X+ * You cannot use TPID and MPID together! X+ * X+ * 100 <= _tpid <= ULONG_MAX (2^32) X+ * X+ */ X+ X+ #define PID_MAX 30000 /* see /usr/include/sys/proc.h */ X+ X #define DOSWAP X X #include "top.h" X*************** X*** 98,104 **** X--- 120,129 ---- X #define X_PG_ACTIVE 6 X #define X_PG_INACTIVE 7 X #define X_PG_WIRED 8 X+ #define X_MPID 9 X+ #define X_TPID 10 X X+ X static struct nlist nlst[] = { X { "_ccpu" }, /* 0 */ X { "_cp_time" }, /* 1 */ X*************** X*** 109,114 **** X--- 134,141 ---- X { "_vm_page_active_count" }, /* 6 */ X { "_vm_page_inactive_count" },/* 7 */ X { "_vm_page_wire_count" }, /* 8 */ X+ { "_mpid" }, /* 9 */ X+ { "_tpid" }, /* 10 */ X { 0 } X }; X X*************** X*** 149,154 **** X--- 176,184 ---- X X static unsigned long cp_time_offset; X static unsigned long avenrun_offset; X+ static unsigned long mpid_offset; X+ static unsigned long tpid_offset; X+ X X /* these are for calculating cpu state percentages */ X X*************** X*** 174,187 **** X X /* these are for detailing the memory statistics */ X X! int memory_stats[8]; X char *memorynames[] = { X #ifdef TOTAL_WORKING X "Real: ", "K/", "K ", "Virt: ", "K/", X "K ", "Free: ", "K", NULL X #else X! " Free: ", "K ", " Active: ", "K ", " Inactive: ", X! "K ", " Wired: ", "K ", NULL X #endif X }; X X--- 204,217 ---- X X /* these are for detailing the memory statistics */ X X! int memory_stats[10]; X char *memorynames[] = { X #ifdef TOTAL_WORKING X "Real: ", "K/", "K ", "Virt: ", "K/", X "K ", "Free: ", "K", NULL X #else X! " Free: ", "K ", " Act: ", "K ", " Inact: ", X! "K ", " Wired: ", "K ", " Swap: ", "% ", NULL X #endif X }; X X*************** X*** 241,246 **** X--- 271,278 ---- X /* stash away certain offsets for later use */ X cp_time_offset = nlst[X_CP_TIME].n_value; X avenrun_offset = nlst[X_AVENRUN].n_value; X+ mpid_offset = nlst[X_MPID].n_value; X+ tpid_offset = nlst[X_TPID].n_value; X X /* this is used in calculating WCPU -- calculate it ahead of time */ X logcpu = log(loaddouble(ccpu)); X*************** X*** 293,298 **** X--- 325,331 ---- X { X long total; X load_avg avenrun[3]; X+ unsigned long mpid, tpid; X X /* get the cp_time array */ X (void) getkval(cp_time_offset, (int *)cp_time, sizeof(cp_time), X*************** X*** 300,305 **** X--- 333,346 ---- X (void) getkval(avenrun_offset, (int *)avenrun, sizeof(avenrun), X "_avenrun"); X X+ /* get mpid -- process id of last process */ X+ (void) getkval(mpid_offset, (unsigned long *)(&mpid), sizeof(mpid), X+ "_mpid"); X+ X+ /* get tpid -- total numbers of used processes */ X+ (void) getkval(tpid_offset, (unsigned long)(&tpid), sizeof(tpid), X+ "_tpid"); X+ X /* convert load averages to doubles */ X { X register int i; X*************** X*** 349,356 **** X memory_stats[6] = -1; X memory_stats[7] = pagetok(total.t_free); X #else X! static int free, active, inactive, wired; X X (void) getkval(nlst[X_PG_FREE].n_value, (int *)(&free), sizeof(free), X nlst[X_PG_FREE].n_name); X (void) getkval(nlst[X_PG_ACTIVE].n_value, (int *)(&active), sizeof(active), X--- 390,398 ---- X memory_stats[6] = -1; X memory_stats[7] = pagetok(total.t_free); X #else X! static int free, active, inactive, wired, swap; X X+ X (void) getkval(nlst[X_PG_FREE].n_value, (int *)(&free), sizeof(free), X nlst[X_PG_FREE].n_name); X (void) getkval(nlst[X_PG_ACTIVE].n_value, (int *)(&active), sizeof(active), X*************** X*** 367,379 **** X--- 409,444 ---- X memory_stats[5] = pagetok(inactive); X memory_stats[6] = -1; X memory_stats[7] = pagetok(wired); X+ memory_stats[8] = -1; X+ memory_stats[9] = swap_used(); X+ X+ if (memory_stats[9] < 0) /* ignore errors */ X+ memory_stats[9] = 0; X+ X #endif X } X X /* set arrays and strings */ X si->cpustates = cpu_states; X si->memory = memory_stats; X+ X+ #ifdef MPID X+ /* avoid wrong last pid */ X+ if(mpid < 0 || mpid > PID_MAX) X+ si->last_pid = -1; X+ else X+ si->last_pid = mpid; X+ #elif defined (TPID) X+ /* avoid wrong total number pid */ X+ if(mpid < 0 || mpid > PID_MAX || tpid < 0) X+ si->last_pid = -1; X+ else X+ si->last_pid = tpid; X+ #else X+ /* normal, unpatched kernel */ X si->last_pid = -1; X+ #endif X+ X } X X static struct handle handle; X*************** X*** 693,695 **** X--- 758,956 ---- X } X return(-1); X } X+ X+ X+ /* X+ * Code from swapinfo(1) X+ */ X+ X+ /* X+ * swapinfo X+ * X+ * Swapinfo will provide some information about the state of the swap X+ * space for the system. It'll determine the number of swap areas, X+ * their original size, and their utilization. X+ * X+ * Kevin Lahey, February 16, 1993 X+ */ X+ X+ /* #include <stdlib.h> */ X+ #include <sys/ioctl.h> X+ #include <sys/termios.h> X+ #include <sys/stat.h> X+ #include <sys/tty.h> X+ #include <sys/uio.h> X+ #include <sys/buf.h> X+ #include <sys/conf.h> X+ #include <sys/rlist.h> /* swapmap defined here... */ X+ X+ X+ static struct nlist nl[] = {{"_swapmap"}, /* list of free swap areas */ X+ #define VM_SWAPMAP 0 X+ {"_swdevt"}, /* list of swap devices and sizes */ X+ #define VM_SWDEVT 1 X+ {"_nswap"}, /* size of largest swap device */ X+ #define VM_NSWAP 2 X+ {"_nswdev"}, /* number of swap devices */ X+ #define VM_NSWDEV 3 X+ {"_dmmax"}, /* maximum size of a swap block */ X+ #define VM_DMMAX 4 X+ {""}}; X+ X+ int swap_used() X+ { X+ int i, total_avail, total_free, total_partitions, *by_device, X+ total_used, X+ nswap, nswdev, dmmax, ch; X+ struct swdevt *swdevt; X+ struct rlist head; X+ static long blocksize; X+ X+ X+ /* Open up /dev/kmem for reading. */ X+ X+ if (kvm_openfiles (NULL, NULL, NULL) == -1) X+ return(-1); X+ X+ /* Figure out the offset of the various structures we'll need. */ X+ X+ if (kvm_nlist (nl) == -1) X+ return(-1); X+ X+ if (kvm_read ((void *)nl [VM_NSWAP].n_value, &nswap, X+ sizeof (nswap)) != sizeof (nswap)) X+ return(-1); X+ X+ if (kvm_read ((void *)nl [VM_NSWDEV].n_value, &nswdev, X+ sizeof (nswdev)) != sizeof (nswdev)) X+ return(-1); X+ X+ if (kvm_read ((void *)nl [VM_DMMAX].n_value, &dmmax, X+ sizeof (dmmax)) != sizeof (dmmax)) X+ return(-1); X+ X+ X+ if ((swdevt = (void *)malloc (sizeof (struct swdevt) * nswdev)) == X+ NULL || X+ (by_device = (void *)calloc (sizeof (*by_device), nswdev)) == X+ NULL) X+ return(-1); X+ X+ if (kvm_read ((void *)nl [VM_SWDEVT].n_value, swdevt, X+ sizeof (struct swdevt) * nswdev) != X+ sizeof (struct swdevt) * nswdev) X+ return(-1); X+ X+ if (kvm_read ((void *)nl [0].n_value, &swapmap, X+ sizeof (struct rlist *)) != sizeof (struct rlist *)) X+ return(-1); X+ X+ /* Traverse the list of free swap space... */ X+ X+ total_free = 0; X+ while (swapmap) { X+ int top, bottom, next_block; X+ X+ if (kvm_read ((void *) swapmap, &head, sizeof (struct rlist )) X+ != sizeof (struct rlist )) X+ return(-1); X+ X+ top = head.rl_end; X+ bottom = head.rl_start; X+ X+ total_free += top - bottom + 1; X+ X+ /* X+ * Swap space is split up among the configured disk. X+ * The first dmmax blocks of swap space some from the X+ * first disk, the next dmmax blocks from the next, X+ * and so on. The list of free space joins adjacent X+ * free blocks, ignoring device boundries. If we want X+ * to keep track of this information per device, we'll X+ * just have to extract it ourselves. X+ */ X+ X+ while (top / dmmax != bottom / dmmax) { X+ next_block = ((bottom + dmmax) / dmmax); X+ by_device [(bottom / dmmax) % nswdev] += X+ next_block * dmmax - bottom; X+ bottom = next_block * dmmax; X+ } X+ X+ by_device [(bottom / dmmax) % nswdev] += X+ top - bottom + 1; X+ X+ swapmap = head.rl_next; X+ } X+ X+ /* header = getbsize("swapinfo", &headerlen, &blocksize); */ X+ blocksize = 1024; X+ X+ total_used = 0; X+ for (total_avail = total_partitions = i = 0; i < nswdev; i++) { X+ X+ /* X+ * Don't report statistics for partitions which have not X+ * yet been activated via swapon(8). X+ */ X+ X+ if (!swdevt [i].sw_freed) { X+ /* printf (" *** not available for swapping ***\n"); */ X+ } else { X+ total_avail += swdevt [i].sw_nblks/ (blocksize/512); X+ total_used += (swdevt [i].sw_nblks - X+ by_device [i]) / (blocksize/512); X+ } X+ } X+ if ( total_avail == 0 ) X+ return(0); X+ else X+ return((int)(100 * total_used/total_avail + 0.5)); X+ X+ X+ /* X+ * If only one partition has been set up via swapon(8), we don't X+ * need to bother with totals. X+ */ X+ X+ } X+ X+ X+ /* X+ /* Kernel patch for last pid X+ /* X+ */ X+ X+ #if 0 X+ X+ *** kern_fork.c Sat Oct 16 16:24:03 1993 X+ --- /sys/kern/kern_fork.c Thu Dec 16 22:19:21 1993 X+ *************** X+ *** 47,52 **** X+ --- 47,55 ---- X+ #include "ktrace.h" X+ #include "vm/vm.h" X+ X+ + int mpid; /* max pid */ X+ + unsigned long int tpid = 0; /* total pid */ X+ + X+ /* ARGSUSED */ X+ fork(p, uap, retval) X+ struct proc *p; X+ *************** X+ *** 292,296 **** X+ --- 295,306 ---- X+ */ X+ retval[0] = p2->p_pid; X+ retval[1] = 0; X+ + X+ + mpid = nextpid; X+ + X+ + if (mpid > tpid) X+ + tpid = mpid; X+ + else X+ + tpid++; X+ return (0); X+ } X+ X+ #endif END-of-m_386bsd.c.diff exit ---------------------------------------------------------------------- -- ... Und stünde es nicht besser um die menschliche Gemeinschaft, wenn manche Kategorien von Tätigen dafür entlohnt würden, daß sie nichts tun? ... Müßig gehen ist subjektiv und objektiv lange nicht so verwerflich wie müßig arbeiten, schlimmer als die unnützen Nichtstuer sind die unnützen Tuer, und dem Geiste käme es zu hohem Nutzen, wenn mancher Fleißbold bezahlt würde dafür, daß er die Hände öfter in den Schoß und seltener auf die Schreibmaschine lege. Alfred Polgar, Die Mission des Luftballons