home *** CD-ROM | disk | FTP | other *** search
- /*
- * process.c
- *
- * Code to collect information about memory usage in the system
- *
- * Copyright 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
-
- #define _KMEMUSER
- #include <sys/types.h>
- #include <sys/procfs.h>
- #include <sys/param.h>
- #include <sys/sysmp.h>
- #include <sys/sysinfo.h>
- #include <sys/sysmacros.h>
- #include <sys/sbd.h>
- #include <sys/pfdat.h>
- #include <sys/proc.h>
-
- #include <dirent.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <stdio.h>
- #include <ctype.h>
-
- #include "process.h"
- #include "inode.h"
-
- #define PROCDIR "/proc"
- #define MAXMAPS 256
-
-
- /*
- * dirp is for opening /proc
- */
- static DIR *dirp = NULL;
- static unsigned long kpstart, ktext, ketext, kend, kpbase, kpfdat;
- static unsigned long kpagesize;
-
- static int pgsize; /* page size in 1000 of bytes (ie. 4, 16, etc...) */
-
- /*
- * void
- * KernelInfo()
- *
- * Description:
- * Initialize a few constant global kernel variables
- */
- void
- KernelInfo(void)
- {
- register int fd;
-
- /* Only do once */
- if (!kend) {
- /* Get some info from sysmp() */
- if ((kpstart = sysmp(MP_KERNADDR, MPKA_PSTART)) == -1)
- perror("sysmp(MP_KERNADDR, MPKA_PSTART)");
- kpstart = PHYS_TO_K0(kpstart);
- if ((ktext = sysmp(MP_KERNADDR, MPKA_TEXT)) == -1)
- perror("sysmp(MP_KERNADDR, MPKA_TEXT)");
- if ((ketext = sysmp(MP_KERNADDR, MPKA_ETEXT)) == -1)
- perror("sysmp(MP_KERNADDR, MPKA_ETEXT)");
- if ((kend = sysmp(MP_KERNADDR, MPKA_END)) == -1)
- perror("sysmp(MP_KERNADDR, MPKA_END)");
- if ((kpfdat = sysmp(MP_KERNADDR, MPKA_PFDAT)) == -1)
- perror("sysmp(MP_KERNADDR, MPKA_PFDAT)");
- if ((kpbase = sysmp(MP_KERNADDR, MPKA_KPBASE)) == -1)
- perror("sysmp(MP_KERNADDR, MPKA_KPBASE)");
-
- /* Read some stuff from /dev/kmem */
- if (fd = open("/dev/kmem", 0)) {
- /* Get value of KPBASE */
- if (lseek(fd, kpbase, SEEK_SET) == -1)
- perror("lseek");
- if (read(fd, (caddr_t)&kpbase, sizeof kpbase) < 0)
- perror("read");
- kpfdat += btoct(kpbase) * sizeof (pfd_t);
- kpbase = PHYS_TO_K0(kpbase);
-
- close(fd);
- }
- }
- }
-
- /*
- * static PROGRAM *
- * AddElem(PROGRAM *head, char *progName, char *mapName, char *mapType,
- * long privSize, long weightSize, long resSize, long size,
- * pid_t pid, int markNProc)
- *
- * Description:
- * Add an element to our program list.
- *
- * Parameters:
- * head The list to add this element to
- * progName Name of program to add
- * privSize Size of private pages
- * weightSize Weighted memusage size
- * resSize resident size of program to add
- * size total size of program to add
- * pid process id of program to add
- * markNProc 1 if we care about keeping nProc up to date
- *
- * Returns:
- * A new list (the element being added may go at the beginning)
- */
-
- static PROGRAM *
- AddElem(PROGRAM *head, char *progName, char *mapName, char *mapType,
- long privSize, long weightSize, long resSize,
- long size, pid_t pid, int markNProc)
- {
- PROGRAM *elem, *prev, *pidPlace;
- int cmp;
-
- elem = head;
- prev = NULL;
- pidPlace = NULL;
-
- /*
- * Look for another copy of the same program already running
- */
- while (elem && (cmp = strcmp(progName, elem->progName)) != 0) {
- /*
- * Remember where the program should go (we sort by pid) in
- * case this is the first of its kind that we've found
- */
- if (pid < elem->pid && !pidPlace) {
- pidPlace = prev;
- }
- prev = elem;
- elem = elem->next;
- }
-
- if (elem && cmp == 0) {
- /*
- * Another copy is running; just add the new one's stats to
- * the old one
- */
- elem->privSize += privSize;
- elem->weightSize += weightSize;
- elem->resSize += resSize;
- elem->size += size;
- if (markNProc) {
- elem->nProc++;
- }
- } else {
- /*
- * A new program is encountered. Allocate a new element, and
- * insert it into the list.
- */
- elem = malloc(sizeof *elem);
-
- /*
- * progName and mapName get strduped because the point to
- * things like prinfo structs that change. mapType points to
- * static storage that does not change. Be very careful if
- * you change this, because FreeUsage (in this file) knows
- * about this, AND SO DOES DrawSetup (in draw.c)!!!
- */
- elem->progName = strdup(progName);
- elem->mapName = mapName ? strdup(mapName) : NULL;
- elem->mapType = mapType; /* Don't need to dup this; it points */
- /* to static storage that won't change */
- elem->privSize = privSize;
- elem->weightSize = weightSize;
- elem->resSize = resSize;
- elem->size = size;
- elem->pid = pid;
- elem->nProc = 1;
- elem->print = 1;
-
- if (!prev) {
- elem->prev = NULL;
- elem->next = head;
- head = elem;
- } else {
- if (pidPlace) {
- prev = pidPlace;
- }
- elem->next = prev->next;
- elem->prev = prev;
- prev->next = elem;
- if (elem->next) {
- elem->next->prev = elem;
- }
- }
- }
- return head;
- }
-
- /*
- * static PROGRAM *
- * SortList(PROGRAM *head, int flag)
- *
- * Description:
- * Sort the element list by physical size (largest first)
- *
- * Parameters:
- * head Start of the double linked list of elements
- *
- * Returns:
- * New head of the list
- */
-
- static PROGRAM *
- SortList(PROGRAM *head, int flag)
- {
- PROGRAM *new = NULL, *prev, *walk, *next, *scan;
-
- /* Walk the original list */
- for (walk = head; walk != NULL; walk = next) {
- /* Correct weightSize values */
- if (flag != 0) {
- walk->weightSize += MA_WSIZE_FRAC - 1;
- walk->weightSize /= MA_WSIZE_FRAC;
- }
-
- /* Get it now, will be rewritten below */
- next = walk->next;
-
- /* No sort, just scale */
- if (flag < 0) {
- new = head;
- continue;
- }
-
- /* Put into new sorted list */
- for (prev = NULL, scan = new; scan != NULL;
- scan = scan->next) {
- if (walk->weightSize > scan->weightSize)
- break;
- prev = scan;
- }
-
- /* Insert into new list before current element */
- if (scan) {
- walk->next = scan;
- walk->prev = scan->prev;
- scan->prev = walk;
- if (prev)
- prev->next = walk;
- else
- new = walk;
- } else if (new) {
- walk->prev = prev;
- prev->next = walk;
- walk->next = NULL;
- } else {
- new = walk;
- walk->prev = NULL;
- walk->next = NULL;
- }
- }
-
- return new;
- }
-
- /*
- * Indentify RLD bss extents
- */
- isrldbss(struct prmap_sgi *map)
- {
- if (((unsigned)map->pr_vaddr >= 0x0fbc0000) &&
- ((unsigned)map->pr_vaddr < 0x0fc40000))
- return 1;
- return 0;
- }
-
- /*
- * Indentify /dev/zero
- */
- isdevzero(struct prmap_sgi *map)
- {
- static dev_t zdev;
- static ino_t zino;
-
- /* Lookup /dev/zero */
- if (!zdev) {
- FindInode("zero", &zdev, &zino);
- }
-
- /* Match? */
- if (map->pr_dev == zdev && map->pr_ino == zino)
- return 1;
- return 0;
- }
-
- /*
- * char *
- * MapFlags(prmap_sgi_t *map)
- *
- * Description:
- * Translate the flags for a region into a meaningful word that
- * describes what type of region it is
- *
- * Parameters:
- * map region pointer
- *
- * Returns:
- * string describing the type of region
- */
-
- char *
- MapFlags(prmap_sgi_t *map)
- {
- if (map->pr_mflags & MA_PHYS) {
- return "Physical Device";
- } else if (map->pr_mflags & MA_STACK) {
- return "Stack";
- } else if (map->pr_mflags & MA_BREAK) {
- return "Break";
- } else if (map->pr_mflags & MA_EXEC) {
- return "Text";
- } else if (map->pr_mflags & MA_COW) {
- return "Data";
- } else if (map->pr_mflags & MA_SHMEM) {
- return "Shmem";
- } else if ((map->pr_mflags & (MA_READ | MA_WRITE)) ==
- (MA_READ | MA_WRITE)) {
- return "RW";
- } else if (map->pr_mflags & MA_READ) {
- return "RO";
- }
- return "Other";
- }
-
- /*
- * int
- * PteAccounting(prmap_sgi_t *maps, int nmaps)
- *
- * Description:
- * Try and figure out how many page tables are in core
- *
- * Parameters:
- * maps region pointer
- * nmaps number of maps in region list
- */
- PteAccounting(prmap_sgi_t *maps, int nmaps)
- {
- unsigned pteblksize = (kpagesize / sizeof (caddr_t)) * kpagesize;
- prmap_sgi_t *map;
- long segno, refcnt, lrefcnt = 0, space = 0;
- caddr_t vaddr, vend;
- int i, last = -1;
-
- /* Search all the segments */
- for (map = maps, i = 0; i < nmaps; ++map, ++i) {
- /* Skip empty ones */
- if (map->pr_vsize == 0)
- continue;
-
- /* Walk segment one segment at a time (XXX fix me) */
- vaddr = map->pr_vaddr;
- vend = map->pr_vaddr + map->pr_size;
- refcnt = map->pr_mflags >> MA_REFCNT_SHIFT;
- while (vaddr < vend) {
- /* If not same as last time & incore, then bill me */
- segno = (long)vaddr / pteblksize;
- if (last == -1)
- last = segno;
- if (last != segno) {
- space += kpagesize / lrefcnt;
- last = segno;
- lrefcnt = 0;
- }
- vaddr += pteblksize;
- if (!lrefcnt || (refcnt < lrefcnt)) {
- lrefcnt = refcnt;
- }
- }
- }
- if (lrefcnt) {
- space += kpagesize / lrefcnt;
- }
-
- return space / 1024;
- }
-
- /*
- * Indentify PROGRAM text extent
- */
- static int
- isprgtxt(struct prmap_sgi *map)
- {
- if ((map->pr_mflags & (MA_EXEC|MA_PRIMARY)) == (MA_PRIMARY|MA_EXEC))
- return 1;
- return 0;
- }
-
- /*
- * Indentify RLD text extent
- */
- static int
- isrldtxt(struct prmap_sgi *map)
- {
- if ((unsigned)map->pr_vaddr == 0x0fb60000)
- return 1;
- return 0;
- }
-
- /*
- * static void OpenProcDir(void)
- *
- * Description:
- * Open /proc if it's not open, and rewind. dirp is a global
- * variable.
- */
-
- static void OpenProcDir(void)
- {
- /* Get system page size */
- if (!kpagesize)
- kpagesize = getpagesize();
-
- pgsize = kpagesize/1024;
-
- if (!dirp) {
- if ((dirp = opendir(PROCDIR)) == NULL) {
- perror(PROCDIR);
- exit(1);
- }
- }
-
- rewinddir(dirp);
- }
-
- /*
- * void GetObjInfo(char *objName, PROGRAM **all, PROGRAM **objp)
- *
- * Description:
- * Get physical memory usage information for all mapped objects
- * in the system.
- *
- * Parameters:
- * objName name of object to get detailed information for
- * all gets usage for all objectss
- * objp gets usage for a specific object
- */
-
- void GetObjInfo(char *objName, PROGRAM **all, PROGRAM **objp)
- {
- struct dirent *dent;
- char procFile[MAXPATHLEN];
- int status, fd, nmaps, i, pid = 1, ppid = 1, mino;
- register struct prmap_sgi *map, *amap, *rmap, *bmap;
- struct prmap_sgi maps[MAXMAPS];
- prmap_sgi_arg_t maparg;
- PROGRAM *list = NULL;
- PROGRAM *plist = NULL;
- unsigned long refCount;
- double rss;
- char *mname, *flagName;
- struct prpsinfo info;
- long uspace = 0, ptespace = 0, mem;
-
- maparg.pr_vaddr = (caddr_t)maps;
- maparg.pr_size = sizeof maps;
-
- OpenProcDir();
-
- while ((dent = readdir(dirp)) != NULL) {
- if (!isdigit(dent->d_name[0]))
- continue;
-
- sprintf(procFile, "%s/%s", PROCDIR, dent->d_name);
-
- status = (fd = open(procFile, O_RDONLY)) != -1
- && ioctl(fd, PIOCPSINFO, &info) != -1
- && (nmaps = ioctl(fd, PIOCMAP_SGI, &maparg)) != -1;
-
- close(fd);
-
- if (!status) {
- continue;
- }
-
- /* Figure out if U-area is in core and charge process for it */
- uspace += (info.pr_flag & SULOAD) ? (USIZE * kpagesize / 1024) : 0;
-
- /* Try and figure out how many page tables are resident in memory */
- ptespace += PteAccounting(maps, nmaps);
-
- amap = NULL;
- rmap = NULL;
-
- /* Search regions to find app segment & rld segment */
- for (map = maps, i = nmaps; i-- > 0; ++map) {
- /* Hack for app region */
- if (!amap && isprgtxt(map)) {
- amap = map;
- }
-
- /* Remember primary BRK region */
- if ((map->pr_mflags & (MA_PRIMARY|MA_BREAK)) ==
- (MA_PRIMARY|MA_BREAK)) {
- bmap = map;
- }
-
- /* Remember RLD region */
- if (!rmap && isrldtxt(map)) {
- rmap = map;
- }
- }
-
- /* Scan the table */
- for (map = maps, i = nmaps; i-- > 0; ++map) {
- if (map->pr_mflags & MA_PHYS) {
- continue;
- }
-
- /* Try and bill /dev/zero regions to real owners */
- if (isdevzero(map)) {
- /* Hack for rld's /dev/zero regions */
- if (rmap && isrldbss(map)) {
- map->pr_dev = rmap->pr_dev;
- map->pr_ino = rmap->pr_ino;
- map->pr_mflags |= MA_BREAK;
- }
- /* Otherwise bill to apps primary break region */
- else if (bmap) {
- map->pr_dev = bmap->pr_dev;
- map->pr_ino = bmap->pr_ino;
- map->pr_mflags |= MA_BREAK;
- }
- } else if (amap && ((map->pr_mflags & MA_STACK) ||
- (map->pr_mflags & MA_BREAK))) {
- map->pr_dev = amap->pr_dev;
- map->pr_ino = amap->pr_ino;
- }
-
- if (map->pr_dev == amap->pr_dev && map->pr_ino == amap->pr_ino) {
- mname = info.pr_fname;
- } else {
- mname = map->pr_ino ?
- InodeLookup(map->pr_dev, map->pr_ino) : NULL;
- }
-
- flagName = MapFlags(map);
- refCount = map->pr_mflags >> MA_REFCNT_SHIFT;
- rss = (double)map->pr_wsize;
- rss *= pgsize; /* use 1KB resolution */
- rss /= (double)refCount;
- list = AddElem(list, mname ? mname : flagName,
- mname, flagName,
- (map->pr_psize * pgsize) / refCount, rss,
- 0, 0, pid++, 0);
- if (objName && mname && strcmp(objName, mname) == 0) {
- plist = AddElem(plist, flagName, mname, flagName,
- (map->pr_psize * pgsize) / refCount, rss,
- 0, 0, ppid++, 0);
- }
- }
- }
- list = SortList(list, 1);
- if (plist) plist = SortList(plist, -1);
- mem = uspace + ptespace;
- list = AddElem(list, "U areas & PTEs", "U areas & PTES", IRIX,
- mem, mem, 0, 0,
- pid++, 0);
- *all = list;
- *objp = plist;
- }
-
- /*
- * void
- * GetProcInfo(char *procName, PROGRAM **all, PROGRAM **proc)
- *
- * Description:
- * Get memory usage information for all processes in the system.
- * In addition, collect detailed information for procName if it
- * is non-NULL.
- *
- * Parameters:
- * procName name of program to get detailed information for
- * all gets usage for all processes
- * proc gets usage for a specific process
- */
-
- void
- GetProcInfo(char *procName, PROGRAM **all, PROGRAM **proc)
- {
- struct dirent *dent;
- char procFile[MAXPATHLEN];
- int fd, i;
- struct prpsinfo info;
- register prmap_sgi_t *map, *amap;
- prmap_sgi_t maps[MAXMAPS];
- prmap_sgi_arg_t maparg;
- unsigned nmaps;
- PROGRAM *list = NULL;
- PROGRAM *plist = NULL;
- char mapObjName[MAXPATHLEN + 20], *mname, *flagName;
- int status;
- struct rminfo rminfo;
- struct minfo minfo;
- long userTotal, pteTotal, uspace, ptespace, wrss, kmem, mem, privSize;
- long weighted, refCount;
-
- maparg.pr_vaddr = (caddr_t)maps;
- maparg.pr_size = sizeof maps;
-
- OpenProcDir();
-
- userTotal = pteTotal = 0;
- while ((dent = readdir(dirp)) != NULL) {
- if (!isdigit(dent->d_name[0]))
- continue;
-
- sprintf(procFile, "%s/%s", PROCDIR, dent->d_name);
-
- status = (fd = open(procFile, O_RDONLY)) != -1
- && ioctl(fd, PIOCPSINFO, &info) != -1
- && (nmaps = ioctl(fd, PIOCMAP_SGI, &maparg)) != -1;
-
- close(fd);
-
- if (!status) {
- continue;
- }
-
- #define pr_rss pr_fill[1]
- wrss = 0;
- privSize = 0;
- /* Compute weighted rss from valid and usage counts */
- for (map = maps, i = nmaps; i-- > 0; ++map) {
- if ((map->pr_mflags & MA_PHYS) == 0) {
- refCount = map->pr_mflags >> MA_REFCNT_SHIFT;
- weighted = map->pr_wsize;
- weighted *= pgsize; /* use 1KB resolution */
- weighted /= MA_WSIZE_FRAC;
- weighted /= refCount;
- map->pr_rss = (long)weighted;
- wrss += weighted;
- if ((map->pr_mflags & MA_SHMEM) == 0) {
- privSize += (map->pr_psize * pgsize) / refCount;
- }
- } else {
- map->pr_rss = 0;
- }
- }
- userTotal += wrss;
-
- /* Figure out if U-area is in core and charge process for it */
- uspace = (info.pr_flag & SULOAD) ? (USIZE * kpagesize / 1024) : 0;
- userTotal += uspace;
- privSize += uspace;
-
- /* Try and figure out how many page tables are resident in memory */
- ptespace = PteAccounting(maps, nmaps);
- pteTotal += ptespace;
- privSize += ptespace;
-
- list = AddElem(list, info.pr_fname, NULL, NULL, privSize,
- (long)wrss + uspace + ptespace,
- info.pr_rssize * pgsize + uspace + ptespace,
- info.pr_size * pgsize, info.pr_pid, 1);
-
- if (procName && strcmp(procName, info.pr_fname) == 0) {
- amap = 0;
- /*
- * Find program text region, so we can get good names for
- * the regions associated with each executable file even
- * if that file isn't in our inode map.
- */
- for (map = maps, i = nmaps; i-- > 0; ++map) {
- if (isprgtxt(map)) {
- amap = map;
- break;
- }
- }
-
- /* List all the address space segments in virtual order */
- for (map = maps, i = nmaps; i-- > 0; ++map) {
- if (isdevzero(map) && isrldbss(map)) {
- mname = "rld";
- map->pr_mflags |= MA_BREAK;
- } else if ((map->pr_mflags & MA_STACK) ||
- (map->pr_mflags & MA_BREAK) ||
- (map->pr_dev == amap->pr_dev && map->pr_ino ==
- amap->pr_ino)) {
- mname = procName;
- } else {
- mname = map->pr_ino ?
- InodeLookup(map->pr_dev, map->pr_ino) : NULL;
- }
- flagName = MapFlags(map);
- if (mname) {
- sprintf(mapObjName, "%s (%s)", flagName, mname);
- if (strlen(mapObjName) > 15) {
- mapObjName[15] = ')';
- mapObjName[16] = '\0';
- }
- }
- refCount = map->pr_mflags >> MA_REFCNT_SHIFT;
- plist = AddElem(plist, mname ? mapObjName : flagName,
- mname, flagName,
- ((map->pr_mflags & MA_PHYS) ||
- (map->pr_mflags & MA_SHMEM)) ?
- 0 : (map->pr_psize * pgsize) / refCount,
- map->pr_rss,
- (map->pr_vsize * pgsize) / refCount,
- (map->pr_size + 1023) / 1024, nmaps - i, 0);
- }
-
- /* Add U area & PTE space at the bottom */
- mem = uspace + ptespace;
- plist = AddElem(plist, "U area & PTEs", "U area & PTEs",
- IRIX, mem, mem, mem, mem, nmaps+1, 0);
- }
- }
-
- /*
- * Special case if procName is "Irix". We get info from the sysmp
- * call.
- */
- if (procName && strcmp(procName, IRIX) == 0) {
- KernelInfo();
- if (sysmp(MP_SAGET, MPSA_RMINFO, &rminfo, sizeof rminfo) == -1
- ||sysmp(MP_SAGET, MPSA_MINFO, &minfo, sizeof minfo) == -1) {
- perror("sysmp");
- } else {
- i = 0;
- kmem = (rminfo.physmem - rminfo.availrmem) * pgsize;
- kmem -= pteTotal;
- mem = (rminfo.physmem - rminfo.freemem) * pgsize
- - (userTotal + kmem + pteTotal) + rminfo.bufmem * pgsize;
- plist = AddElem(plist, "FS Cache", "FS Cache", IRIX, mem, mem,
- 0, 0, i++, 0);
- kmem -= rminfo.bufmem * pgsize;
-
- /*
- * Subtract streams from heap, since streams memory is
- * part of the heap
- */
- mem = minfo.heapmem / 1024 - rminfo.strmem * pgsize;
- plist = AddElem(plist, "Heap", "Heap", IRIX,
- mem, mem, 0, 0, i++, 0);
- kmem -= mem;
-
- mem = rminfo.strmem * pgsize;
- plist = AddElem(plist, "Streams", "Streams", IRIX,
- mem, mem, 0, 0, i++, 0);
- kmem -= mem;
-
- mem = minfo.zonemem / 1024;
- plist = AddElem(plist, "Zone", "Zone", IRIX,
- mem, mem, 0, 0, i++, 0);
- kmem -= mem;
-
- mem = minfo.bsdnet / 1024;
- plist = AddElem(plist, "BSD Networking",
- "BSD Networking", IRIX,
- mem, mem, 0, 0, i++, 0);
- kmem -= mem;
-
- mem = ketext - kpstart; /* Kernel Text */
- mem += kend - ketext; /* Kernel Data */
- if (kpbase > kend) {
- mem += kpbase - kpfdat; /* Page Frames */
- mem += kpfdat - kend; /* Kernel Tables */
- }
- mem /= 1024;
- kmem -= mem;
- plist = AddElem(plist, "Other", "Other", IRIX,
- kmem, kmem, 0, 0, i++, 0);
-
- if (kpbase > kend) {
- mem = (kpbase - kpfdat) / 1024;
- plist = AddElem(plist, "Page Frame Data", "Page Frame Data",
- IRIX, mem, mem, 0, 0, i++, 0);
- mem = (kpfdat - kend) / 1024;
- plist = AddElem(plist, "Kernel Tables", "Kernel Tables",
- IRIX, mem, mem, 0, 0, i++, 0);
- }
- mem = (kend - ketext) / 1024;
- plist = AddElem(plist, "Unix Data Space", "Unix Data Space",
- IRIX, mem, mem, 0, 0, i++, 0);
- if ((ktext - kpstart) > 2*NBPP) {
- mem = (ketext - ktext) / 1024;
- plist = AddElem(plist, "Unix Code Space", "Unix Code Space",
- IRIX, mem, mem, 0, 0, i++, 0);
- mem = (ktext - kpstart) / 1024;
- plist = AddElem(plist, "Symmon", "Symmon", IRIX,
- mem, mem, 0, 0, i++, 0);
- } else {
- mem = (ketext - kpstart) / 1024;
- plist = AddElem(plist, "Unix Code Space", "Unix Code Space",
- IRIX, mem, mem, 0, 0, i++, 0);
- }
- }
- }
- *all = list;
- *proc = plist;
- }
-
- /*
- * void
- * FreeUsage(PROGRAM *usage)
- *
- * Description:
- * Free all the memory used by a usage list.
- *
- * Parameters:
- * usage
- */
-
- void
- FreeUsage(PROGRAM *usage)
- {
- PROGRAM *next;
-
- while (usage) {
- next = usage->next;
- free(usage->progName);
- if (usage->mapName) {
- free(usage->mapName);
- }
- free(usage);
- usage = next;
- }
- }
-