ast@cs.vu.nl (Andy Tanenbaum) (07/22/88)
: This is a shar archive. Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
: --------------------------- cut here --------------------------
PATH=/bin:/usr/bin:/usr/ucb
echo Extracting 'amoeba.c'
sed 's/^X//' > 'amoeba.c' << '+ END-OF-FILE ''amoeba.c'
X#ifdef AM_KERNEL
X/*
X** The Amoeba Transaction Layer System Call
X**
X** Amoeba transactions are implemented as a single system call
X** which implements trans(), getreq() and putrep(). timeout() is
X** implemented in the user library.
X** The job of the transaction layer is to ensure that a user task gets
X** only one kernel task. The kernel task is the exclusive domain of
X** the user task for the duration of a transaction.
X**
X** A note on programming style:
X** macros names are upper case (all of them except those from andy)
X** global variable names start with an upper case letter
X** local variables names are lower case
X**
X** The amoeba transactions use message type 2, just like the device
X** drivers. This is for compatibility with the revive code.
X*/
X
X#include "../h/const.h"
X#include "../h/com.h"
X#include "../h/type.h"
X#include "../h/error.h"
X#include "const.h"
X#include "glo.h"
X#include "amoeba.h"
X
X/*
X** There are several external global variables which you need to know about
X** but due to the hacks everywhere they are declared in an include file.
X** who - the task # of the task that sent the request = mm_in.m_source
X** mm_in - the message from that task
X** mm_out - a message buffer normally used by reply()
X** dont_reply - a flag to indicate that no reply should go to sender
X**
X** do_amoeba returns the error status that will be given to the requesting
X** task. The kernel has already done all the data transfers for the task
X** so no return message is required.
X*/
X
X
XPUBLIC int
Xdo_amoeba()
X{
X int ktasknr; /* # of kernel task to perform operation */
X int proc_nr; /* # of user task requesting the operation */
X int r; /* return status */
X int cmd;
X
X/* if it is a revive message from kernel then handle it */
X if (mm_in.AM_OP == AM_REVIVE)
X return am_revive(mm_in.AM_PROC_NR, mm_in.AM_STATUS, (int)mm_in.AM_FREE_IT);
X/*
X** check to see if this task already has a kernel task engaged.
X** if so then use that one, else find a free kernel task.
X*/
X if ((ktasknr = alloc_ktask()) >= 0)
X return TRYAGAIN; /* no free kernel task, try again? */
X proc_nr = who;
X mm_in.AM_PROC_NR = proc_nr;
X cmd = mm_in.AM_OP;
X if ((r = sendrec(ktasknr, &mm_in)) != OK)
X panic("do_amoeba: can't send", NO_NUM);
X/*
X** if necessary suspend. the kernel task will be freed during the revival.
X** otherwise we got an immediate answer.
X** in that case it was an error or an instant response. probably it
X** was an error. if so free the kernel task. if it was not an error
X** then don't free the kernel task if it was a getrequest.
X*/
X if (mm_in.AM_STATUS == SUSPEND)
X dont_reply = TRUE;
X else
X if (mm_in.AM_STATUS < 0 || cmd != AM_GETREQ)
X free_ktask(proc_nr);
X return mm_in.AM_STATUS;
X}
X
X
X/* task number of task in control of kernel task, 0 if task is free */
XPRIVATE struct
X{
X int proc;
X int signalled;
X} In_use[AM_NTASKS];
X
XPRIVATE int
Xalloc_ktask()
X{
X int i;
X int slot = -1;
X
X for (i = 0; i < AM_NTASKS; i++) /* look at all kernel tasks!! */
X if (In_use[i].proc == who)
X { /* already has a kernel task */
X slot = i;
X break;
X }
X else
X if (In_use[i].proc == 0)
X slot = i; /* slot i is free, but keep looking */
X if (slot < 0) /* no free slot was found */
X return 0;
X In_use[slot].proc = who;
X In_use[slot].signalled = 0;
X return AMOEBA_CLASS - slot;
X}
X
X
XPRIVATE int
Xfree_ktask(n)
X{
X int i;
X
X for (i = 0; i < AM_NTASKS; i++)
X if (In_use[i].proc == n)
X {
X In_use[i].proc = 0;
X return;
X }
X}
X
X
XPRIVATE int
Xam_revive(task, status, free_it)
Xint task;
Xint status;
Xint free_it;
X{
X if (who > 0)
X return EPERM;
X if (free_it)
X free_ktask(task); /* it was not a getreq! */
X reply(task, status, 0, (char *) 0); /* revive the task */
X dont_reply = TRUE;
X return OK;
X}
X
X
XPUBLIC int
Xam_check_sig(proc, type)
Xint proc;
Xint type;
X{
X/* return 0 if the signal was for a transacting task. otherwise return 1 */
X int i;
X
X for (i = 0; i < AM_NTASKS; i++)
X if (In_use[i].proc == proc && (!In_use[i].signalled || type == 1))
X {
X/* mm_out is not being used by anyone right now! */
X In_use[i].signalled = 1;
X if (type == 1)
X {
X In_use[i].proc = 0;
X mm_out.AM_OP = AM_TASK_DIED;
X }
X else
X mm_out.AM_OP = AM_PUTSIG;
X mm_out.AM_COUNT = i;
X send(AMINT_CLASS, &mm_out);
X return 0;
X }
X return 1;
X}
X#endif AM_KERNEL
+ END-OF-FILE amoeba.c
chmod 'u=rw,g=r,o=r' 'amoeba.c'
set `wc -c 'amoeba.c'`
count=$1
case $count in
4344) :;;
*) echo 'Bad character count in ''amoeba.c' >&2
echo 'Count should be 4344' >&2
esac
echo Extracting 'makefile'
sed 's/^X//' > 'makefile' << '+ END-OF-FILE ''makefile'
X# This makefile is used for both the PC and AT. If you run out of space
X# while compiling or linking, you may have to use the -T. flag, or even
X# rm /lib/cem and /lib/cpp while running asld. See the makefiles in
X# kernel/IBM_PC.
X#
X# If you do not intend to use the amoeba networking then remove the -DAM_KERNEL
X# from the CFLAGS. Do NOT change anything else in the makefile. It is
X# unnecessary.
X
XH=../../h
XM=../../mm
XA=../h
XL=/usr/lib
XCFLAGS = -DAM_KERNEL -Di8088 -w -F -I../../mm
X
XOBJ = main.s forkexit.s break.s exec.s signal.s getset.s \
X alloc.s utility.s table.s putc.s amoeba.s
X
Xmm: makefile $L/head.s $(OBJ) $L/libc.a $L/end.s
X @echo "Start linking MM."
X @asld -o mm $L/head.s $(OBJ) $L/libc.a $L/end.s
X @echo "MM done. "
X
Xclean:
X rm -f $(OBJ)
X
Xalloc.s: $M/const.h $H/const.h $H/type.h
X $(CC) $(CFLAGS) -c $M/alloc.c
X
Xamoeba.s: $H/const.h $H/com.h $H/type.h $H/error.h \
X $A/amoeba.h $A/host_os.h \
X $M/const.h $M/glo.h
X $(CC) $(CFLAGS) -c amoeba.c
X
Xbreak.s: $M/const.h $H/const.h $H/type.h
Xbreak.s: $H/error.h
Xbreak.s: $H/signal.h
Xbreak.s: $M/glo.h
Xbreak.s: $M/mproc.h
Xbreak.s: $M/param.h
X $(CC) $(CFLAGS) -c $M/break.c
X
Xexec.s: $M/const.h $H/const.h $H/type.h
Xexec.s: $H/callnr.h
Xexec.s: $H/error.h
Xexec.s: $H/stat.h
Xexec.s: $M/glo.h
Xexec.s: $M/mproc.h
Xexec.s: $M/param.h
X $(CC) $(CFLAGS) -c $M/exec.c
X
Xforkexit.s: $M/const.h $H/const.h $H/type.h
Xforkexit.s: $H/callnr.h
Xforkexit.s: $H/error.h
Xforkexit.s: $M/glo.h
Xforkexit.s: $M/mproc.h
Xforkexit.s: $M/param.h
X $(CC) $(CFLAGS) -c $M/forkexit.c
X
Xgetset.s: $M/const.h $H/const.h $H/type.h
Xgetset.s: $H/callnr.h
Xgetset.s: $H/error.h
Xgetset.s: $M/glo.h
Xgetset.s: $M/mproc.h
Xgetset.s: $M/param.h
X $(CC) $(CFLAGS) -c $M/getset.c
X
Xmain.s: $M/const.h $H/const.h $H/type.h
Xmain.s: $H/callnr.h
Xmain.s: $H/com.h
Xmain.s: $H/error.h
Xmain.s: $M/glo.h
Xmain.s: $M/mproc.h
Xmain.s: $M/param.h
X $(CC) $(CFLAGS) -c $M/main.c
X
Xputc.s: $H/const.h $H/type.h
Xputc.s: $H/com.h
X $(CC) $(CFLAGS) -c $M/putc.c
X
Xsignal.s: $M/const.h $H/const.h $H/type.h
Xsignal.s: $H/callnr.h
Xsignal.s: $H/com.h
Xsignal.s: $H/error.h
Xsignal.s: $H/signal.h
Xsignal.s: $H/stat.h
Xsignal.s: $M/glo.h
Xsignal.s: $M/mproc.h
Xsignal.s: $M/param.h
X $(CC) $(CFLAGS) -c $M/signal.c
X
Xtable.s: $M/const.h $H/const.h $H/type.h
Xtable.s: $H/callnr.h
Xtable.s: $M/glo.h
Xtable.s: $M/mproc.h
Xtable.s: $M/param.h
X $(CC) $(CFLAGS) -c $M/table.c
X
Xutility.s: $M/const.h $H/const.h $H/type.h
Xutility.s: $H/callnr.h
Xutility.s: $H/com.h
Xutility.s: $H/error.h
Xutility.s: $H/stat.h
Xutility.s: $M/glo.h
Xutility.s: $M/mproc.h
X $(CC) $(CFLAGS) -c $M/utility.c
+ END-OF-FILE makefile
chmod 'u=rw,g=r,o=r' 'makefile'
set `wc -c 'makefile'`
count=$1
case $count in
2565) :;;
*) echo 'Bad character count in ''makefile' >&2
echo 'Count should be 2565' >&2
esac
exit 0