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