*BSD News Article 25309


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