---------------------------------------------------------------------------- Source For hatstat - check if PMEG Stealing is happening SunFLASH Vol 19 #23 July 1990 ---------------------------------------------------------------------------- In 19.22 there was a discussion about the implications of the design of the Sun 4 Memory Management Unit (MMU). Under certain circumstances, pmegs will be stolen from another process that did have an active context. This is a BAD THING. The next release of SunOS will fix this problem and a patch will be made available for SunOS 4.1 by the end of July and for Sun4c 4.0.3 by early August. In the meantime, how do you know if this nasty PMEG stealing is happening to you ? Answer - use the enclosed program. If you are having this PMEG stealing problem, call your support number and they will send you a patch (when it is released). If you are not having this problem, don't worry - be happy ! Note that the enclosed program is Copyright 1990 by Sun Microsystems, Inc. We have been given permission to distribute this program to help you determine if you are having this PMEG problem. -flash (aka John McLaughlin) #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'hatstat.8' <<'END_OF_FILE' X.\" %Z%%M% %I% %E% SMI X.TH HATSTAT 8 "30 May 1990" X.SH NAME Xhatstat \- report HAT layer statistics X.SH SYNOPSIS X.B hatstat X[\fB-d\fR] [\fB-T\fR] [\fB-i X.IR interval ] X[ X.B \-c X.IR count ] X[ X.IR namelist ] X.SH DESCRIPTION X.LP X.B hatstat Xdisplays kernel statistics associated with the VM HAT layer. Statistics Xmay be displayed over an interval of time, or may be cumulative over the Xtime the system has been running. If no options are given, a single cumulative Xreport is displayed. If an interval is given (see OPTIONS, below), the Xdisplay has the following components: X.TP XPmegs free Xis the number of pmegs free X.I at the end Xof the displayed interval. X.TP XContexts alloc Xis the number of free contexts allocated during the interval. X.TP XContexts stoln Xis the number of contexts stolen from another process during the interval. X.TP XPmegs reatt Xis the number of pmegs reattached to a process at context allocation time. X.TP XPmegs reusd Xindicates the number of times a process needed a pmeg but already had one available. X.TP XPmegs alloc Xis the number of pmegs allocated from the free list during the interval. X.TP XPmegs stlnc Xspecifies the number of pmegs stolen from another process that did not have an Xactive context. These steals are expensive and indicate that the system is short Xof pmegs, but not so short that it must steal from other active processes. X.TP XPmegs stlcx Xis the number of pmegs stolen from another process that also had an active context. XIf this field is non-zero for any extended period of time, it indicates a serious Xpmeg thrashing situation. X.LP XThe remaining fields are displayed only on systems with three-level MMUs, which Xcurrently include only the SS-470 and SS-490. X.TP XSmegs free Xis the number of smegs free X.I at the end Xof the displayed interval. X.TP XSmegs reusd Xindicates the number of times a process needed a smeg but already had one available. X.TP XSmegs alloc Xis the number of smegs allocated from the free list during the interval. X.TP XSmegs stlnc Xspecifies the number of smegs stolen from another process that did not have an Xactive context. X.TP XSmegs stlcx Xis the number of smegs stolen from another process that also had an active context. X.LP XThe cumulative display is self-explanatory. X.SH OPTIONS X.PD 0 X.TP X.B \-d Xrequests detailed output. This means that cumulative statistics will be displayed. XIf this option is given along with an interval, the cumulative statistics will be Xdisplayed both at the start of execution and again at the end. X.TP X.B \-T Xrequests that a timestamp be displayed whenever a new header is displayed. XThis option makes it easier to correlate the information displayed by X.B hatstat Xwith actual system activity. X.TP X.BI \-i \ interval XInterval between samples, in seconds. If X.I count Xis given, defaults to 5 seconds. If X.I interval Xis given without a X.I count Xthe count defaults to infinite. X.TP X.BI \-c \ count XNumber of samples. X.TP X.I namelist Xspecifies the location of the system namelist. XIt defaults to X.BR /vmunix . X.PD X.SH CAVEATS X.B hatstat Xmust be installed SGID kmem, or the user must have read access to X.BR /dev/kmem . X.SH FILES X.PD 0 X.TP 16 X/vmunix Xthe default system namelist X.TP X/dev/kmem Xthe system memory image X.PD X.SH "SEE ALSO" Xiostat(8), vmstat(8) X.SH BUGS X.B hatstat Xis not synchronized with the kernel, so VM usage can Xchange while X.B hatstat Xis running, leading to (minor) inaccuracies. END_OF_FILE if test 3391 -ne `wc -c <'hatstat.8'`; then echo shar: \"'hatstat.8'\" unpacked with wrong size! fi # end of 'hatstat.8' fi if test -f 'hatstat.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hatstat.c'\" else echo shar: Extracting \"'hatstat.c'\" \(6786 characters\) sed "s/^X//" >'hatstat.c' <<'END_OF_FILE' X/* X * hatstat -- Get pmeg usage information from the kernel X * X * Copyright 1990 by Sun Microsystems, Inc. X */ X X#define MMU_3LEVEL /* Support 3-level MMU operations */ X X#include X#include X#include X#include X#include X#include X#include X X#define void char X X#define MON_MEMNAME "/dev/kmem" X#define MON_NLNAME "/vmunix" X Xextern char *optarg; Xextern int optind; X Xint on_exit(); X Xstruct nlist nl[] = { X#define N_HATCNT 0 X { "_hatcnt" }, X#define N_PMGRPFREE 1 X { "_pmgrpfree" }, X#define N_SMGRPFREE 2 X { "_smgrpfree" }, X "", X}; X Xstruct hatcnt { X int hc_ctxalloc; /* number of context allocations */ X int hc_ctxstolen; /* number of contexts stolen from other as's */ X int hc_pmghave; /* number of pmg_allocs that already have pmg */ X int hc_pmgalloc; /* number of pmg allocations */ X int hc_pmgstolennoctx; /* pmgs stolen from as's with no ctx */ X int hc_pmgstolenctx; /* pmgs stolen from other as's with a ctx */ X int hc_smghave; /* number of smg_allocs that already have smg */ X int hc_smgalloc; /* number of smg allocations */ X int hc_smgstolennoctx; /* smgs stolen from procs with no ctx */ X int hc_smgstolenctx; /* smgs stolen from other procs with a ctx */ X int hc_ctxpmgs; /* number of pmgs found on as at ctxalloc */ X} hatcnt; X Xstruct hatcnt old_hatcnt, diff_hatcnt; Xint detail = 0; Xint no_smegs = 0; Xint do_tod = 0; Xint mem; X Xmain (argc, argv) X X int argc; X char **argv; X X{ X struct nlist *np; X char *nlfile; X int interval = 5; X int have_interval = 0; X int count = 1; X int have_count = 0; X int i; X X/* X * Parse arguments X */ X while ((i = getopt (argc, argv, "dTi:c:")) != -1) { X switch (i) { X case 'd': X detail++; X break; X case 'T': X do_tod++; X break; X case 'i': X interval = atoi (optarg); X have_interval++; X break; X case 'c': X count = atoi (optarg); X have_count++; X break; X case '?': X default: Xusage: X printf ("Usage: hatstat [-d] [-T] [-i interval] [-c count] [namelist]\n"); X exit (1); X } X } X/* X * Optional argument is namelist file X */ X if (optind < argc) X nlfile = argv[optind++]; X else X nlfile = "/vmunix"; X if (optind != argc) X goto usage; X X if (have_interval && !have_count) X count = 0x7fffffff; X/* X * Open input file X */ X if ((mem = open ("/dev/kmem", O_RDONLY)) == -1) { X perror ("/dev/kmem"); X exit (1); X } X/* X * Get namelist file and addresses of relevant data X */ X nlist (nlfile, nl); X for (np = nl; *np->n_name; np++) { X if (np->n_type == 0) { X if (np == &nl[N_SMGRPFREE]) X no_smegs++; X else { X fprintf (stderr, "'%s' missing from name list.\n", X np->n_name); X exit (1); X } X } X } X X/* X * Read kernel data X */ X getkval ((void *)&hatcnt, mem, nl[N_HATCNT].n_value, X sizeof (struct hatcnt)); X/* X * If not iterating, display data in detail X */ X if (count == 1 || detail) X print_cumulative (&hatcnt); X if (count == 1) X exit (0); X X signal (SIGINT, on_exit); X/* X * Iterate X */ X X for (i = 0; i < count; i++) { X if ((i % 20) == 0) { X if (do_tod) { X time_t tod; X X time(&tod); X printf ("%s", ctime(&tod)); X } X X printf ("Pmegs Contexts Pmegs ---------Pmegs---------"); X if (!no_smegs) X printf (" Smegs ---------Smegs---------"); X printf ("\n free alloc stoln reatt reusd alloc stlnc stlcx"); X if (!no_smegs) X printf (" free reusd alloc stlnc stlcx\n"); X else X printf ("\n"); X } X old_hatcnt = hatcnt; X sleep (interval); X getkval ((void *)&hatcnt, mem, nl[N_HATCNT].n_value, X sizeof (struct hatcnt)); X compute_diff (&hatcnt, &old_hatcnt, &diff_hatcnt); X printf ("%5d%6d%6d%6d%6d%6d%6d%6d%", X count_free_pmgs(), X diff_hatcnt.hc_ctxalloc, diff_hatcnt.hc_ctxstolen, X diff_hatcnt.hc_ctxpmgs, diff_hatcnt.hc_pmghave, X diff_hatcnt.hc_pmgalloc, diff_hatcnt.hc_pmgstolennoctx, X diff_hatcnt.hc_pmgstolenctx); X if (no_smegs) X printf ("\n"); X else { X printf ("%6d%6d%6d%6d%6d\n", count_free_smgs(), X diff_hatcnt.hc_smghave, diff_hatcnt.hc_smgalloc, X diff_hatcnt.hc_smgstolennoctx, X diff_hatcnt.hc_smgstolenctx); X } X } X} X X/* X * getkval -- Read requested value (of requested size) from kernel memory. X */ Xgetkval (val, fd, addr, size) X X void *val; X int fd; X off_t addr; X int size; X X{ X if (lseek (fd, addr, L_SET) == -1) { X perror ("lseek (/dev/kmem)"); X exit (1); X } X if (read (fd, (char *)val, size) == -1) { X perror ("read (/dev/kmem)"); X exit (1); X } X} X Xcompute_diff (new, old, diff) X X struct hatcnt *new, *old, *diff; X{ X X diff->hc_ctxalloc = new->hc_ctxalloc - old->hc_ctxalloc; X diff->hc_ctxstolen = new->hc_ctxstolen - old->hc_ctxstolen; X diff->hc_pmghave = new->hc_pmghave - old->hc_pmghave; X diff->hc_pmgalloc = new->hc_pmgalloc - old->hc_pmgalloc; X diff->hc_pmgstolennoctx = new->hc_pmgstolennoctx - old->hc_pmgstolennoctx; X diff->hc_pmgstolenctx = new->hc_pmgstolenctx - old->hc_pmgstolenctx; X diff->hc_smghave = new->hc_smghave - old->hc_smghave; X diff->hc_smgalloc = new->hc_smgalloc - old->hc_smgalloc; X diff->hc_smgstolennoctx = new->hc_smgstolennoctx - old->hc_smgstolennoctx; X diff->hc_smgstolenctx = new->hc_smgstolenctx - old->hc_smgstolenctx; X diff->hc_ctxpmgs = new->hc_ctxpmgs - old->hc_ctxpmgs; X X} X Xprint_cumulative (cum) X Xstruct hatcnt *cum; X X{ X printf ("%10d Pmegs free\n", count_free_pmgs()); X printf ("%10d Contexts allocated\n", cum->hc_ctxalloc); X printf ("%10d Contexts stolen\n", cum->hc_ctxstolen); X printf ("%10d Pmegs reattached at context allocation\n", cum->hc_ctxpmgs); X printf ("%10d Pmegs reused\n", cum->hc_pmghave); X printf ("%10d Pmegs allocated\n", cum->hc_pmgalloc); X printf ("%10d Pmegs stolen from address space with no context\n", X cum->hc_pmgstolennoctx); X printf ("%10d Pmegs stolen from address space with context\n", X cum->hc_pmgstolenctx); X if (!no_smegs) { X printf ("%10d Smegs free\n", count_free_smgs()); X printf ("%10d Smegs reused\n", cum->hc_smghave); X printf ("%10d Smegs allocated\n", cum->hc_smgalloc); X printf ("%10d Smegs stolen from address space with no context\n", X cum->hc_smgstolennoctx); X printf ("%10d Smegs stolen from address space with context\n", X cum->hc_smgstolenctx); X } X X} X Xcount_free_pmgs() X X{ X struct pmgrp pmg; X struct pmgrp *pp; X int free_pmgs; X X getkval ((void *)&pp, mem, nl[N_PMGRPFREE].n_value, sizeof (pp)); X X for (free_pmgs = 0; pp != NULL; free_pmgs++) { X getkval ((void *)&pmg, mem, (off_t)pp, sizeof (struct pmgrp)); X pp = pmg.pmg_next; X } X X return (free_pmgs); X} X Xcount_free_smgs() X X{ X struct smgrp smg; X struct smgrp *sp; X int free_smgs; X X getkval ((void *)&sp, mem, nl[N_SMGRPFREE].n_value, sizeof (sp)); X X for (free_smgs = 0; sp != NULL; free_smgs++) { X getkval ((void *)&smg, mem, (off_t)sp, sizeof (struct smgrp)); X sp = smg.smg_next; X } X X return (free_smgs); X} X Xon_exit () X{ X X if (detail) X print_cumulative (&hatcnt); X X exit (0); X} END_OF_FILE if test 6786 -ne `wc -c <'hatstat.c'`; then echo shar: \"'hatstat.c'\" unpacked with wrong size! fi # end of 'hatstat.c' fi echo shar: End of shell archive. exit 0 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Sunflash is an electronic mail news service from Sun Microsystems, Ft. Lauderdale, Florida, USA. It is targeted at Sun Users and Customers. As a field sales and support office, we try to keep SunFlash useful and interesting to you. If you have any comments or suggestions for enhancing SunFlash, please send them to us. SunFlash is ditributed via a hierarchy of aliases. Please try to address change requests to the owner of the alias that you belong to. Please address comments to the SunFlash editor John McLaughlin (sun!sunvice!flash or flash@sunvice.East.Sun.COM). (305) 776-7770.