nap() for Sys V
Ron Heiby
heiby at mcdchg.chi.il.us
Sat Apr 1 07:34:25 AEST 1989
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 at mcdchg.chi.il.us Moderator: comp.newprod
"Life is indeed an inexplicable sequence of imponderable surprises."
More information about the Alt.sources
mailing list