[alt.sources] nap

zeeff@b-tech.ann-arbor.mi.us (Jon Zeeff) (03/29/89)

#! /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:  ft.c nap.c test.c
# Wrapped by zeeff@b-tech on Mon Oct 17 10:17:48 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f ft.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"ft.c\"
else
echo shar: Extracting \"ft.c\" \(1082 characters\)
sed "s/^X//" >ft.c <<'END_OF_ft.c'
X
X/*
X   Written by Jon Zeeff umix!b-tech!zeeff
X
X   This "device driver" uses the kernel delay() call to allow calls
X   to nap() from user processes.  Nap() is like sleep, but with finer
X   resolution.
X 
X   Compile with cc -O  -c ft.c 
X
X   Written for a Sys V.3 system, but should work on others.
X
X   For Sys V.3:
X   
X   Make a new kernel according to the instructions and then:
X   mknod /dev/ft c 28 0 
X
X   modules/ft/config:
X       character(28)
X       prefix = ft 
X       functions = open, close, read
X   
X   Edit systems/system.std and add ft.
X   Copy ft.o to modules/ft/config
X
X*/
X
X#include <sys/signal.h>
X#include <sys/types.h>
X#include <sys/sysmacros.h>
X#include <sys/param.h>
X#include <sys/systm.h>
X#include <sys/buf.h>
X#include <sys/iobuf.h>
X#include <sys/conf.h>
X#include <sys/dir.h>
X#include <sys/user.h>
X#include <sys/utsname.h>
X#include <sys/elog.h>
X#include <sys/errno.h>
X#include <sys/trap.h>
X#include <sys/seg.h>
X#include <sys/map.h>
X
X/* use a raw device interface */
X
Xftopen() {}
X
Xftread(dev)
Xint dev;
X{
Xdelay(u.u_count);
Xu.u_count = 0;
X}
X
Xftwrite() {}
Xftclose() {}
X
END_OF_ft.c
if test 1082 -ne `wc -c <ft.c`; then
    echo shar: \"ft.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f nap.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"nap.c\"
else
echo shar: Extracting \"nap.c\" \(115 characters\)
sed "s/^X//" >nap.c <<'END_OF_nap.c'
X
Xnap(ticks)
Xunsigned ticks;
X{
Xstatic int fd=0;
X
Xif (fd == 0) fd = open("/dev/ft",0);
Xread(fd,(char *)0,ticks);
X
X}
X
END_OF_nap.c
if test 115 -ne `wc -c <nap.c`; then
    echo shar: \"nap.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f test.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"test.c\"
else
echo shar: Extracting \"test.c\" \(26 characters\)
sed "s/^X//" >test.c <<'END_OF_test.c'
X
Xmain()
X{
X
Xnap(1000);
X
X}
X
END_OF_test.c
if test 26 -ne `wc -c <test.c`; then
    echo shar: \"test.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
-- 
  Jon Zeeff			zeeff@b-tech.ann-arbor.mi.us
  Ann Arbor, MI			mailrus!b-tech!zeeff

heiby@mcdchg.chi.il.us (Ron Heiby) (04/01/89)

I made some changes to an earlier posting of Sys V nap() to run
a bit more reliably and be of sufficient quality and documentation
that I could hand the stuff (below) to one of my customers and
wish them luck.  Some of it is specific to the Motorola Delta Series,
but most of it is pretty generic.

----- cut here -----
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./README`
then
echo "writing ./README"
cat > ./README << '\Rogue\Monster\'
nap() - 12/88

This file describes the nap() package for the Motorola VME Delta Series
computer systems.  This work was based on ideas from several people on
the Usenet and skeletal code written by Jon Zeeff.  From there, it has
been enhanced to eliminate the possibility of causing a system panic as
well as in several smaller ways.

nap() has been tested under System V/68 Release 3 version 4 and under
System V/68 Release 3 version 5 (FE83.26).

To install the package, cd into the directory into which the files were
extracted and type "make".  This will build all the files you will need.
The file "lib.nap" must be copied into the directory /usr/src/uts/m68k/cf.
The file "nap.o" contains the definition of the nap() function call and
may be explicitly linked with code that calls it or may be placed into
a library of routines.  The file "sysgen.ft" should be copied to
/usr/src/uts/m68k/sysgen/descriptions/ft (file "ft" in the "descriptions"
directory).  This file declares that the "Major Character Device Number"
is 28.  This is the same number used by OfficeLAN.  If you are using the
OfficeLAN product in your system, you must choose a different number for
nap() and use it in place of 28 here, and in the "mknod" command below.
(See below for how to choose a number.)

Using the "sysgen" command, select ON the "Nap device" entry.  As you
"q" out of sysgen, answer "y" to all questions, causing the new kernel
to be built with the "Nap device" driver included.

Execute the command "mknod /dev/ft c 28 0".  Set permissions on it to
allow its use.  Users of nap() must have read permission on /dev/ft.
It may be desirable to restrict access to this device.

Once the system has been re-booted and the mknod command executed, the
nap() function is ready for use.  Included in this package is a program
called "naptest" which takes as it's argument the number to be passed
to nap().  If zero or more than one arguments are given to naptest, it
will call nap with a default of 600.

The ft driver attempts to ensure that the system resource it uses does
not become exhausted.  It does this by returning -1 with errno set to
EBUSY if the number of available slots becomes "small".  ("Small" is
about 20 as delivered.) The resource is called the "callout table",
and the number of slots in it is the NCALL tunable parameter in sysgen
(default 50).  If other drivers in your system cause more than about 15
callout table entries to be used sporadically, you must change the "20"
in ft.c to a larger value, reserving more spare slots.  This is not likely.
The callout table can be examined by using the "callout" request within
the "crash" command.

Here is the synopsis of the nap() routine.
-------
	int nap(ticks)
	unsigned ticks;
-------

The nap() call is similar to the sleep() call, documented in section
3C of the Programmer's Reference.  There are some significant differences,
though.
	1) Processes that call nap() pass an argument which is the number
		of clock ticks to sleep, rather than the number of seconds.
		(The number of clock ticks per second is #defined as HZ in
		the file /usr/include/sys/param.h.  On VME Delta systems,
		this is 60.)
	2) Wakeups do not occur at fixed one-second intervals.  They happen
		on the requested clock tick.
	3) The process "napping" will not process *ANY* signals, including
		SIGKILL, until it leaves it's nap.
	4) nap() has nothing to do with the use of the alarm(2) signal.
		Remember though, that SIGALRM will not be recognized until
		the nap is over.
	5) nap() will return 0 if the nap took place.  It will return -1
		with errno set to EBUSY if the nap was not done.

--------------------------------------------------
Choosing a Different Major Character Device Number
--------------------------------------------------

This section is for those using OfficeLAN, since it is set up as Character
Device number 28, as is the "ft" driver used by nap().

In the directory /usr/src/uts/m68k/cf, is a file named "conf.c".  In this
file, is the declaration:
	struct cdevsw cdevsw[] = {
		...
	};
The initialization lines (represented above as "...") each begin with a
number in comments, like
	/*28*/
and continue with names of driver routines that "belong to" that major
device number.  On systems where OfficeLAN has not been configured into
the kernel, the line for major device 28 looks something like
	/*28*/	nodev, 	nodev, 	nodev, 	nodev, 	nodev, 	notty,	nostr,

If it does not, then you must either remove OfficeLAN from your configuration
or find a line that *does* look similar to the above and choose that line's
number to use.  Remember to change the "ft" file in the "descriptions"
directory to use the new number instead of "28" and to use the new number in
the "mknod" command for the /dev/ft device.
\Rogue\Monster\
else
  echo "will not over write ./README"
fi
if `test ! -s ./ft.c`
then
echo "writing ./ft.c"
cat > ./ft.c << '\Rogue\Monster\'

/*
   Written by Jon Zeeff umix!b-tech!zeeff
   Modified by Ron Heiby mcdchg!heiby 12/88 to protect against too many
	simultaneous calls causing a system panic from being out of
	callout table entries.  A check is made to ensure that there
	is a fair buffer of free entries before making the call to
	delay().  If the test fails, we cause EBUSY to be returned.
	Also, deleted some unnecessary #include lines.

   This "device driver" uses the kernel delay() call to allow calls
   to nap() from user processes.  Nap() is like sleep, but with finer
   resolution.
*/

#include <sys/types.h>
#include <sys/signal.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/errno.h>
#include <sys/callo.h>
#include <sys/var.h>

/* use a raw device interface */

ftopen() {}

ftread(dev)
int dev;
{
	if (callout[v.v_call-20].c_func)
	{
		u.u_error = EBUSY;
		return;
	}
	delay(u.u_count);
	u.u_count = 0;
}

ftclose() {}
\Rogue\Monster\
else
  echo "will not over write ./ft.c"
fi
if `test ! -s ./makefile`
then
echo "writing ./makefile"
cat > ./makefile << '\Rogue\Monster\'
CFLAGS = -O -DINKERNEL

all:	lib.nap naptest

naptest:	nap.o naptest.o
	cc -o naptest naptest.o nap.o

lib.nap:	ft.o
	rm -f lib.nap
	ar r lib.nap ft.o
\Rogue\Monster\
else
  echo "will not over write ./makefile"
fi
if `test ! -s ./nap.c`
then
echo "writing ./nap.c"
cat > ./nap.c << '\Rogue\Monster\'

/*
	User-level library function that makes use of the "ft" device
	to sleep after scheduling a clock callout event for "ticks"
	clock ticks into the future.

	Returns either 0 (success) or -1 (failure).  Leaves errno alone
	(as set by the last system call).
*/

int nap(ticks)
unsigned ticks;
{
	static int fd=0;
	static int ret;

	if (fd == 0) fd = open("/dev/ft",0);
	ret = read(fd,(char *)0,ticks);
	return( (ret == -1) ? -1 : 0 );

}
\Rogue\Monster\
else
  echo "will not over write ./nap.c"
fi
if `test ! -s ./naptest.c`
then
echo "writing ./naptest.c"
cat > ./naptest.c << '\Rogue\Monster\'
#include	<sys/types.h>
#include	<time.h>
#include	<stdio.h>
#include	<errno.h>

#define	NAP_DEFAULT	600

main(argc, argv)
int	argc;
char	**argv;
{
	time_t		clock;
	unsigned	nap_time;
	int		nap_returns;

	if (argc == 2) {
		nap_time = atoi(argv[1]);
	} else {
		nap_time = NAP_DEFAULT;
		printf("Using default nap time of %d ticks.\n", nap_time);
	}

	clock = time(0);
	puts(ctime(&clock));

	nap_returns = nap(nap_time);

	clock = time(0);
	puts(ctime(&clock));
	printf("nap(%u) returned: %d.  errno = %d.\n", nap_time, nap_returns, errno);
	exit(0);
}
\Rogue\Monster\
else
  echo "will not over write ./naptest.c"
fi
if `test ! -s ./sysgen.ft`
then
echo "writing ./sysgen.ft"
cat > ./sysgen.ft << '\Rogue\Monster\'
* ft
*
Description File:	"Nap device"
*
* ft #1
*
Board Description:	"Nap device #1"
Description Keyword:	"ft #1"
Device Type:	"ft"
Bus Request Level:	0
Address:	0
Interrupt Vector Location:	0
Default Number Of Devices:	0
*
* ft
*
Device Description:	"Nap device driver"
Description Keyword:	"ft"
Device Name:	"ft"
Handler Prefix:	"ft"
Interrupt Vectors Size:	0
Major Block Device Number:	0
Major Character Device Number:	28
Maximum Bus Request Level:	0
Maximum Devices Per Controller:	1
Page Registers Size:	0
Block Or Character Device Handler Lines:
Has an open handler.
Has a close handler.
Has a read handler.
Device Type Information:
Do not create an interrupt vector for this device.
This is a character device.
Device Configuration Tables Declarations:
\Rogue\Monster\
else
  echo "will not over write ./sysgen.ft"
fi
echo "Finished archive 1 of 1"
exit
-- 
Ron Heiby, heiby@mcdchg.chi.il.us	Moderator: comp.newprod
"Life is indeed an inexplicable sequence of imponderable surprises."