#! /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 <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README Makefile memtst-start memtst-stop memtst.c
# Wrapped by phil@mira on Thu Oct  7 13:37:43 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(3359 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
XMemtst package
X--------------
X
XThis simple memory testing program was written to test sparcstation 2
Xmemory. The problem was that the sun diagnostics (sundiag) would always
Xpass even if it was left running for several days, though some memory
Xhungry applications that we were working on would crash with memory parity
Xerrors. The only difference that I could see between the application and
Xthe sundiags was that the sundiag memory tester did not write into memory.
XThe whole package consists of 1 C program and 2 shell scripts.
X
XThe C Program (memtst)
X----------------------
X
XThe binary (the compiled version of memtst.c) is what does the
Xtesting. It allocates (malloc(3)) all the memory that it can up to the
Xmaximum specified.  The amount of memory that you want tested may be
Xspecified as the first argument (eg. memtst 16 -- tests 16MB of memory)
Xor memtst will prompt you for it at run time as in:
X
X# memtst
XHow many MEGS of memory do you want to test? 16
XTesting 16MB or 16777216 bytes of virtual memory with 4 patterns
X  Pattern       Pass
X  FFFFFFFF       1
X
XMemtst has two different output formats which depend on what the standard
Xoutput is. If stdout is to a terminal (isatty(3)) memtst will update the
Xscreen every sub-pass.  (as shown above). If output is to a pipe or a file
X(not a tty) memtst reports after every 10 full passes. A full pass is completed
Xwhen all of the test patterns have been used. You may change or add to the
Xnumber of patterns by editing memtst.c.
X
XCompile memtst with "cc -O -o memtst memtst.c" or use the Makefile.
X
XThe Scripts
X-----------
X
XThe two shell scripts were written to start and stop memtst from cron.
Xmemtst-start starts up memtst. It saves the PID in a file for memtst-stop.
XIt takes a single numeric argument which is the number of megabytes that you
Xwant to test. If no value is supplied 16MB is used.
X
XMemtst-stop stops memtst and mails a report (be it good or bad) to someone.
Xmemtst-stop takes a single argument which is the email address of the
Xindividual to send the report to, with no argument it is sent to root.
XIt always greps the error log files (/var/adm/messages*) if an error is
Xsuspected and mails this too. Memtst-stop suspects a crash if the PID
Xfile does not exist because the PID file is kept on /tmp which is usually
Xcleared at startup. 
X
XExample crontab entries
X-----------------------
X
XTest 64MB starting at 10:00 PM every day and stopping at 6:00 AM every
Xmorning. Output is sent to "person@host.subdom.domain".
X
X00 22 * * * /usr/local/src/memtst/memtst-start 64
X00 06 * * * /usr/local/src/memtst/memtst-stop person@host.subdom.domain
X
X
XFinally
X-------
X
XMemtst is a real memory hog and may cause some noticeable drop in performance.
XIf you start up memtst on all of your systems available virtual memory
Xyou might lock out all other processes (not enough memory to fork!), plus
Xyour system will start paging itself to death. A good rule of thumb is
Xto start up memtst on the amount of physical memory minus 7MB. This will
Xusually prevent paging and will allow openwindows or sunview some breathing
Xspace. On the other hand if you want to test your swap/paging mechanism
X(or see a Sparcstation really sweat) bump the value up to the maximum
Xvirtual adress space of your system.
X
X
XWritten by P. Blanchfield (phil@dgbt.doc.ca) at The Communications Research
XCentre, Ottawa.  June 1991.
END_OF_FILE
if test 3359 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(1321 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X# Simple makefile to compile and install a program.
X#
X# To use this makefile you must first fill in the configuration information
X# below.
X#
X# To compile and link type:
X# make
X#
X# To install type:
X# make install
X#
X# To uninstall (remove) type:
X# make uninstall
X#
X# To clean up after the build type:
X# make clean
X#
X# Use "make clean" followed by "make" and then "make install" to force
X# a complete recompilation.
X#
X# To copy a new Makefile into your current directory type:
X# "newmake".
X#
X
X# START OF CONFIGURATION AREA
X
X# Change the following to the name of your program.
X# If your program source is called prog.c it would be:
X# PROGNAME=prog
X
X
XPROGNAME=memtst
X
X# cc flags (options which will be used by the c compiler)
X
X#CFLAGS= -O -Wall
XCFLAGS= -O
X
X# C compiler to use.
X# SUN cc by default, for gcc (GNU C) uncomment the next line
X#CC=gcc
X
X# linker flags (options to be used by the linker)
X
XLDFLAGS=
X
X# Where to install the binary
XBINDIR = /usr/local/bin
X
X# END OF CONFIGURATION AREA
X
X$(PROGNAME): $(PROGNAME).o
X	$(CC) $(PROGNAME).o -o $(PROGNAME) $(LDFLAGS)
X
Xinstall:
X	install $(PROGNAME) $(BINDIR)
X	@echo
X	@echo "      If this is the first time that you have built this program"
X	@echo "      you must now type \"rehash\"."
X	@echo
X
Xuninstall:
X	rm -f $(BINDIR)/$(PROGNAME)
X
Xclean:
X	rm -f $(PROGNAME).o $(PROGNAME)
X
END_OF_FILE
if test 1321 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'memtst-start' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'memtst-start'\"
else
echo shar: Extracting \"'memtst-start'\" \(893 characters\)
sed "s/^X//" >'memtst-start' <<'END_OF_FILE'
X#!/bin/sh
X#
X# Script to start up the memory tester may be run from cron in the eve.
X#
X# Typical crontab entries to start at 10:00 PM & stop at 6:00 AM (64MB):
X# 00 22 * * * /usr/local/src/memtst/memtst-start 64
X# 00 06 * * * /usr/local/src/memtst/memtst-stop person@host.subdom.domain
X#
XPATH=:/usr/local/bin:/usr/ucb:/usr/bin:/usr/etc:
X#
X# Default # of megs checked 
X#
X
XDEFMEGS=16
XPMEM=${1:-$DEFMEGS}
X
X#
X# The following have to jibe with the ones in memtst-stop.
X# PIDFILE should be left in /tmp so that the code in memtst-stop
X# properly detects a reboot (/tmp is cleared on reboot). OUTFILE
X# is the output from memtst and should be kept on a real disk partition
X# which survives a reboot (/usr/tmp).
X#
X
XPIDFILE=/tmp/memtst.pid
XOUTFILE=/usr/tmp/memtst.out
X
X#
X
Xif [ -f $PIDFILE ]
Xthen
X  echo "memtst is already running, $PIDFILE exists"
X  exit
Xfi
Xmemtst $PMEM > $OUTFILE &
Xecho $! > $PIDFILE
END_OF_FILE
if test 893 -ne `wc -c <'memtst-start'`; then
    echo shar: \"'memtst-start'\" unpacked with wrong size!
fi
chmod +x 'memtst-start'
# end of 'memtst-start'
fi
if test -f 'memtst-stop' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'memtst-stop'\"
else
echo shar: Extracting \"'memtst-stop'\" \(1855 characters\)
sed "s/^X//" >'memtst-stop' <<'END_OF_FILE'
X#!/bin/sh
X#
X# Shell script to kill off memtst (in the morning from cron)
X#
X# Typical crontab entries to start at 10:00 PM & stop at 6:00 AM (64MB):
X# 00 22 * * * /usr/local/src/memtst/memtst-start 64
X# 00 06 * * * /usr/local/src/memtst/memtst-stop person@host.subdom.domain
X#
XPATH=:/usr/local/bin:/usr/ucb:/usr/bin:/usr/etc:
X#
X# Parameter 1 is the email address to send the report to,
X# by default send to "root".
X
XDEFMAILTO=root
XMAILTO=${1-$DEFMAILTO}
X
X#
X# Where the error log files are on a SUN. Use * to look through
X# all of them they are shuffled on SAT AM on SUN-OS 4.1.1.
X#
X
XMESSAGES=/var/adm/messages*
X
X#
X# The following have to jibe with the ones in memtst-start.
X# PIDFILE should be left in /tmp so that the code following
X# properly detects a reboot (/tmp is cleared on reboot). OUTFILE
X# is the output from memtst and should be kept on a real disk partition
X# which survives a reboot (/usr/tmp).
X#
X
XPIDFILE=/tmp/memtst.pid
XOUTFILE=/usr/tmp/memtst.out
X
X# Start of program
X
XHOST=`hostname`
XTMPFILE=/tmp/memtst$$
X
Xif [ ! -f $PIDFILE ]
Xthen
X  echo "memtst is not running, $PIDFILE does not exist." >> $TMPFILE
X  echo "The system may have crashed and rebooted." >> $TMPFILE
X  echo "The error log file(s) \"$MESSAGES\" will be searched for parity errors." >> $TMPFILE
X  echo "" >> $TMPFILE
Xelse
X  kill -9 `cat $PIDFILE`
X  rm $PIDFILE
Xfi
X
Xfgrep -i parity $MESSAGES >> $TMPFILE
Xif [ -s $TMPFILE ]
Xthen
X  echo "" >> $TMPFILE
X  echo "----------------------memtst output follows---------------------------" >> $TMPFILE
X  echo "" >> $TMPFILE
X  cat $OUTFILE >> $TMPFILE
X  Mail -s "Memory failure on $HOST" $MAILTO < $TMPFILE
Xelse
X  echo "" >> $TMPFILE
X  echo "No errors to report, here is the memtst output:" >> $TMPFILE
X  echo "" >> $TMPFILE
X  cat $OUTFILE >> $TMPFILE
X  Mail -s "No Memory Parity errors found on $HOST" $MAILTO < $TMPFILE
Xfi
Xrm $TMPFILE 
END_OF_FILE
if test 1855 -ne `wc -c <'memtst-stop'`; then
    echo shar: \"'memtst-stop'\" unpacked with wrong size!
fi
chmod +x 'memtst-stop'
# end of 'memtst-stop'
fi
if test -f 'memtst.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'memtst.c'\"
else
echo shar: Extracting \"'memtst.c'\" \(3077 characters\)
sed "s/^X//" >'memtst.c' <<'END_OF_FILE'
X/*
X * Program to test virtual memory.
X * It tests as much memory as it can allocate in one chunk to the
X * maximum provided from standard in or the command line as argv[1].
X * 
X * Syntax: memtst #MEGS (or) memtst
X * Eg.: memtst 48
X *
X * Two companion shell scripts memtst-start and memtst-stop can be fired up
X * from cron to test memory at specified intervals.
X *
X * Typical crontab entries to start at 10:00 PM & stop at 6:00 AM (64MB):
X * 00 22 * * * /usr/local/src/memtst/memtst-start 64
X * 00 06 * * * /usr/local/src/memtst/memtst-stop
X *
X * This was written because sundiag does not write to memory.
X *	       
X * P. Blanchfield CRC June 1991
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <signal.h>
X
X#define MEGS (1024*1024)
X#define DEFAULT_MEGS 16
X
Xint main(argc,argv)
Xint argc;
Xchar **argv;
X{
Xint fprintf(), isatty(), printf(), fflush();
Xchar answer[132],*malloc();
Xint not_done = 1, pmem = 0;
Xint *ptr=NULL,pass,i,j,tmp,memory,words;
Xstatic int patterns[] = { 0xFFFFFFFF, 0x01010101, 0xAAAAAAAA, 0x07070707 };
Xvoid (*signal())();
X
X
X	/* Don't dump core, this sucker is big! */
X
X	signal(SIGQUIT,SIG_IGN);
X	signal(SIGILL,SIG_IGN);
X	signal(SIGTRAP,SIG_IGN);
X	signal(SIGABRT,SIG_IGN);
X	signal(SIGEMT,SIG_IGN);
X	signal(SIGFPE,SIG_IGN);
X	signal(SIGBUS,SIG_IGN);
X	signal(SIGSEGV,SIG_IGN);
X	signal(SIGSYS,SIG_IGN);
X	signal(SIGLOST,SIG_IGN);
X
X
X	if(argc > 1) /* #MEGS to test on the command line? */
X	{ /* yes... */
X	  if((pmem = atoi(argv[1])) == 0)
X	  {
X	    fprintf(stderr,"Bad Value for #MEGS\n");
X	    exit(1);
X	  }
X	  
X	}
X
X	else if ( isatty(0) ) /* get it from the user (stdin) */
X	{
X	  while( not_done )
X	  {
X	    printf("How many MEGS of memory do you want to test? ");
X	    fflush(stdout);
X	    if(gets(answer) == NULL)
X	    {
X	      fprintf(stderr,"EOF or read error from call to gets\n");
X	      exit(1);
X	    }
X
X	    if((pmem = atoi(answer)) == 0)
X	    {
X	      printf("Bad Value Try Again\n");
X	      continue;
X	    }
X
X	    not_done = 0;
X	  }
X	}
X
X	else pmem = DEFAULT_MEGS; /* not a tty, use default */
X
X	/*
X	 * Try to allocate this much (pmem) memory.
X	 * if it fails keep trying until it works a Meg at a time.
X	 */
X
X	for(i=pmem;i>0;i--)
X	{
X	  if((ptr = (int *)malloc(i*MEGS) ) != NULL)
X	    break;
X	}
X	pmem = i;
X	if ( i == 0)
X	{
X	  fprintf(stderr,"Could not allocate any memory\n");
X	  exit(1);
X	}
X
X	memory = pmem*MEGS;
X	printf("Testing %dMB or %d bytes of virtual memory with %d patterns\n",
X		        pmem,  memory,        sizeof(patterns)/sizeof(int));
X	if ( isatty(1) )
X	  printf("  Pattern	Pass\n");
X
X	/* run forever */
X
X	for(pass=1;;pass++)
X	{
X	  /* foreach pattern */
X	  for(i=0;i<(sizeof(patterns)/sizeof(int));i++)
X	  {
X	    if ( isatty(1) ) /* show activity */
X	      printf("\r  %08X	 %d",patterns[i],pass);
X	    else /* this might be going to a file cut back on output */
X	      if ( ((pass % 10) == 0) && (i == 0))
X	        printf("Pass = %d\n",pass);
X	    fflush(stdout);
X
X	    for(j=0,words=(memory>>2);j < words; j++)
X	    {
X	      ptr[j] = patterns[i]; /* write the pattern */
X	      tmp = ptr[j];	    /* read it back */
X	    }
X	  }
X	}
X}
END_OF_FILE
if test 3077 -ne `wc -c <'memtst.c'`; then
    echo shar: \"'memtst.c'\" unpacked with wrong size!
fi
# end of 'memtst.c'
fi
echo shar: End of shell archive.
exit 0
