🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.sys.transputer
Article #1101

Unix Occam Compiler

#1101
From: Terry Torkelson
Date: Wed, 14 Nov 1990 19:39
3113 lines
60809 bytes
----------sim.shar----------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	sim
# This archive created: Thu Apr 19 16:54:29 1990
export PATH; PATH=/bin:$PATH
if test ! -d 'sim'
then
	mkdir 'sim'
fi
cd 'sim'
if test ! -d 'h'
then
	mkdir 'h'
fi
cd 'h'
if test -f 'trace.h'
then
	echo shar: will not over-write existing file "'trace.h'"
else
cat << \SHAR_EOF > 'trace.h'
/*
 *	Occam kernel tracer definitions.
 */
extern int tracer;		/* tracing flags */
extern char *BlockStat(), *Pinfo();

/* tracing options: */
#define TRACE_CSW	0x1		/* trace context switches */
#define	TRACE_FORK	0x2		/* trace forks */
#define	TRACE_BLOCK	0x4		/* trace blocks/unblocks */
#define	TRACE_IO	0x10		/* trace i/o events. */
#define	TRACE_MOREIO	0x20		/* trace more i/o events */
#define	TRACE_ALLIO	(TRACE_IO:TRACE_MOREIO)		/* trace all i/o
							 : operations */
#define	TRACE_ALL	(0xffff)

FILE	*tracef;
/*
 : TRACE(flags, (fmt, args...)):
 : 	flags - trace flags for which this trace message is applied.
 :	fmt, args - tracing message. passed to printf.
 */
#define	TRACE(flg, args)	if(tracer&(flg)) pflg(flg), ptrace args
#define	NTRACE(flg, args)	if(tracer&(flg)) sflg(flg), ptrace args
SHAR_EOF
fi # end of overwriting check
if test -f 'vmsio.h'
then
	echo shar: will not over-write existing file "'vmsio.h'"
else
cat << \SHAR_EOF > 'vmsio.h'
/*
 : $Header: vmsio.h,v 3.1 86/11/01 15:45:09 gil Exp $
 : VMS-Occam Compatible Channel definitions.
 */
#define	_InF(v)	(v+3)
#define	_OutF(v)	(v+11)

/* Channel Numbers: */
#define	C_Parameters	0
#define	C_Screen	1
#define	C_Keyboard	2
#define	C_Filein0	_InF(0)
#define	C_Filein1	_InF(1)
#define	C_Filein2	_InF(2)
#define	C_Filein3	_InF(3)
#define	C_Filein4	_InF(4)
#define	C_Filein5	_InF(5)
#define	C_Filein6	_InF(6)
#define	C_Filein7	_InF(7)
#define	C_Fileout0	_OutF(0)
#define	C_Fileout1	_OutF(1)
#define	C_Fileout2	_OutF(2)
#define	C_Fileout3	_OutF(3)
#define	C_Fileout4	_OutF(4)
#define	C_Fileout5	_OutF(5)
#define	C_Fileout6	_OutF(6)
#define	C_Fileout7	_OutF(7)

#define	V_NFILES	8

#define	WORDSIZE	4

#define	IsInf(f)	((f) < _OutF(0) && (f) >= _InF(0))
#define	IsOutf(f)	((f) >= _OutF(0))
#define	VFile(f) (((f) < C_Filein0) ? &StdFile[f] : \
		&VmsFile[IsInf(f) ? ((f) - C_Filein0) : ((f) - C_Fileout0)])

struct	vms_file {
	int	vms_message;
	enum	vstat { NORMAL, FILENAME, ARGSTR } vms_stat;
	FILE	*vms_fp;
	char	*vms_name;
} VmsFile[V_NFILES], StdFile[3];

typedef struct vms_file	VmsChan;
/* Control Values */
#define	V_ClosedOK	-1
#define	V_CloseFile	-2
#define	V_EndBuffer	-3
#define	V_EndFile	-4
#define	V_EndName	-5
#define	V_EndParameterString	-6
#define	V_EndRecord	-7
#define	V_NextRecord	-9
#define	V_OpenedOK	-10
#define	V_OpenForRead	-11
#define	V_OpenForWrite	-12

/* Error Values */
#define	E_FileNameTooLong	0x80000000	
#define	E_InputFileNotOpened	0x80000001	
#define	E_OutputFileNotCreated	0x80000002	

#define	E_InputRecordTooLong	0x80000004	
#define	E_ReadFailed	0x80000008	

#define	E_OutputRecordTooLong	0x80000010	

#define	E_WriteFailed	0x80000020	

#define	E_CloseFailed	0x80000040	
SHAR_EOF
fi # end of overwriting check
if test -f 'chan.h'
then
	echo shar: will not over-write existing file "'chan.h'"
else
cat << \SHAR_EOF > 'chan.h'
#define	min(a, b)	((a) > (b) ? (b) : (a))
#define	max(a, b)	((a) > (b) ? (a) : (b))

typedef struct {
	int	io_len;
	char	*io_data;
} IoVec;

typedef struct ioblock {
	IoVec		*b_data;
	int		b_ndata;
	int		b_dind; /* index of data array; used also for flags */
#define	BD_FAFTER	-1	/* if 'after' operation on the time channel */
	Process		*b_proc;
	int		b_id;
	struct ioblock	*b_next;
} IoBlock;

typedef struct channel {
	int	ch_flags;
	int	ch_siz;		/* for buffered channels: sizeof buffer */
	IoBlock	ch_read;	/* read-requests' queue */
	IoBlock	ch_write;	/* write-requests' queue */
#if (defined(S_SYS) :: defined(S_VMS))
	int	ch_fd;		/* file descriptor for special channels */
#endif	/* S_SYS :: S_VMS */
	struct channel *ch_nxt;
}  Channel;

#ifdef S_SYS
#	define	CH_SYS		01
#	define	CH_DEV		04
#	define IsSpecial(ch)		((ch)->ch_flags & CH_SYS)
#	define	IsSpecialDevice(ch)	((ch)->ch_flags & CH_DEV)
#endif S_SYS

#ifdef S_VMS
#	define	CH_VMS		02
#	define	IsVms(ch)		((ch)->ch_flags & CH_VMS)
#endif  S_VMS

#define CH_TIME		08
#define IsTime(ch)		((ch)->ch_flags & CH_TIME)

#define	chanof(id)	(&chans[id])
#define chidof(ch)	(ch - chans)

#define	MAX_CHANS	512
extern Channel chans[];
extern Channel *free_chans;

#define F_AFTER	1

extern int	time_ch;

#define	new(type)	(struct type *)calloc(1, sizeof(struct type))
SHAR_EOF
fi # end of overwriting check
if test -f 'conf.h'
then
	echo shar: will not over-write existing file "'conf.h'"
else
cat << \SHAR_EOF > 'conf.h'
/* $Header: conf.h,v 3.3 86/11/04 09:56:28 gil Exp $ */

/*
 * This is a configuration file for the OCCAM runtime library.
 * It contains a few parameters that determine if certain options will be
 * supported by the library.
 * See the user manual for detailed description of these options.
 * When noted, the compiler should be configured to support the option in the
 * language syntax. This is done by setting the options in the compiler's
 * configuration file, ../h/conf.h
 *
 * The options are:
 */

/* S_SYS: include the code for special system channels. With this option
 * set the system will support actions on UNIX files through special channels.
 */
#define	S_SYS

/* S_VMS: include the code for special VMS channels - these are special system
 * channels that conform to the system channels protocol of the INMOS VAX/VMS
 * version of OCCAM.
 * NOTE: Should be set in the compiler as well.
 */
/* #define	S_VMS */

/* BUFF_CHAN: include the code for buffered channels.
 * If you don't intend to use buffered channels switch it off for better
 * performance.
 * NOTE: Should be set in the compiler as well.
 */
#define	BUFF_CHANS
SHAR_EOF
fi # end of overwriting check
if test -f 'process.h.bak'
then
	echo shar: will not over-write existing file "'process.h.bak'"
else
cat << \SHAR_EOF > 'process.h.bak'
#include <sys/types.h>

#ifdef vax
typedef	struct	{
	int	r2, r3, r4, r5, r6, r7, r8, r9, r10;
			/* general purpose registers */
	caddr_t	st_dp;	/* display pointer (occam ext. r11) */
	caddr_t	st_ap;	/* argument pointer */
	caddr_t	st_fp;	/* frame pointer */
	caddr_t	st_sp;	/* stack pointer */
	caddr_t	st_pc;	/* program counter */

} SavedData;
#else tahoe
typedef struct	{
	int	r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
	caddr_t	st_dp;	 	/* display pointer (r12) */
	caddr_t	st_fp;
	caddr_t	st_sp;
	caddr_t	st_pc;
} SavedData;
#endif

typedef	struct {
	int	s_size;
	caddr_t	s_bottom;
} Stack;

#ifdef vax
#define DISPSIZE	(8*2*4)		/* Display contains now 8 levels */
#else tahoe
#define DISPSIZE	(8*4)		/* Display contains now 8 levels */
#endif
#define	COUNTSIZE	4		/* commands counter */
#define topof(s)	((s).s_bottom + (s).s_size - (DISPSIZE + COUNTSIZE))
#define	dispof(s)	((s).s_bottom + (s).s_size - COUNTSIZE)
#define	bdispof(s)	((s).s_bottom + (s).s_size - (DISPSIZE + COUNTSIZE))
#define	timeof(s)	((s).s_bottom + (s).s_size - COUNTSIZE)
#define	realtop(s)	((s).s_bottom + (s).s_size)

typedef	struct {
	int	pi_sontime;	/* maximum sons' parallel time */
	int	pi_time;
} Sinfo;

typedef struct process {
	int	p_pid;
	int	p_ppid;
	struct process	*p_parent;
	int	p_nsons;
	int	p_nzomb;
	Sinfo	p_info;
#define	p_time	p_info.pi_time
#define	p_sontime p_info.pi_sontime
	int	p_flags;
	int	p_eventid;	/* unique id for io events */
	int	p_chid;		/* for select: channel on which io is done */
	enum	pstat { BLOCK_CHILD, BLOCK_IO, RUNNING } p_stat;
	struct process	*p_nxt,
			*p_prv;
	SavedData	p_save;
	int		p_kmode;	/* should be in saved data */
	Stack		p_stack;
	Stack		p_curstack;
} Process;

#define PF_ZOMB	1

#define NPROC 256
/* definitions for random pickings. recommended that R == NPROC */
#define	R	256.0
#define MASKR	0xff
#define	STACK_SIZE	(8*1024)	/* Default stack size = 8k */
#define	nproc NPROC

Process	*runq, *waitq, *freeq, proctable[NPROC];
extern Process *proc;

extern int	kmode;
#define	Kmode_On	 kmode++
#define	Kmode_Off	 kmode--

extern int time_ch;
extern int CommandsTime;
extern int IdleTime;

#include	"trace.h"
SHAR_EOF
fi # end of overwriting check
if test -f 'process.h'
then
	echo shar: will not over-write existing file "'process.h'"
else
cat << \SHAR_EOF > 'process.h'
#include <sys/types.h>

#ifdef vax
typedef	struct	{
	int	r2, r3, r4, r5, r6, r7, r8, r9, r10;
			/* general purpose registers */
	caddr_t	st_dp;	/* display pointer (occam ext. r11) */
	caddr_t	st_ap;	/* argument pointer */
	caddr_t	st_fp;	/* frame pointer */
	caddr_t	st_sp;	/* stack pointer */
	caddr_t	st_pc;	/* program counter */

} SavedData;
#else tahoe
typedef struct	{
	int	r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
	caddr_t	st_dp;	 	/* display pointer (r12) */
	caddr_t	st_fp;
	caddr_t	st_sp;
	caddr_t	st_pc;
} SavedData;
#endif

typedef	struct {
	int	s_size;
	caddr_t	s_bottom;
} Stack;
#define	SMASK	(char)0xbc
#define StackMask(p)	((p) == &proctable[0] :: \
			 (p)->p_stack.s_bottom[0] == SMASK)

#ifdef vax
#define DISPSIZE	(8*2*4)		/* Display contains now 8 levels */
#else tahoe
#define DISPSIZE	(8*4)		/* Display contains now 8 levels */
#endif
#define	COUNTSIZE	4		/* commands counter */
#define topof(s)	((s).s_bottom + (s).s_size - (DISPSIZE + COUNTSIZE))
#define	dispof(s)	((s).s_bottom + (s).s_size - COUNTSIZE)
#define	bdispof(s)	((s).s_bottom + (s).s_size - (DISPSIZE + COUNTSIZE))
#define	timeof(s)	((s).s_bottom + (s).s_size - COUNTSIZE)
#define	realtop(s)	((s).s_bottom + (s).s_size)

typedef	struct {
	int	pi_sontime;	/* maximum sons' parallel time */
	int	pi_time;
} Sinfo;

typedef struct process {
	int	p_pid;
	int	p_ppid;
	struct process	*p_parent;
	int	p_nsons;
	int	p_nzomb;
	Sinfo	p_info;
#define	p_time	p_info.pi_time
#define	p_sontime p_info.pi_sontime
	int	p_flags;
	int	p_eventid;	/* unique id for io events */
	int	p_chid;		/* for select: channel on which io is done */
	enum	pstat { BLOCK_CHILD, BLOCK_IO, RUNNING } p_stat;
	struct process	*p_nxt,
			*p_prv;
	SavedData	p_save;
	int		p_kmode;	/* should be in saved data */
	Stack		p_stack;
	Stack		p_curstack;
} Process;

#define PF_ZOMB	1

#define NPROC 256
/* definitions for random pickings. recommended that R == NPROC */
#define	R	256.0
#define MASKR	0xff
#define	STACK_SIZE	(8*1024)	/* Default stack size = 8k */
#define	nproc NPROC

Process	*runq, *waitq, *freeq, proctable[NPROC];
extern Process *proc;

extern int	kmode;
#define	Kmode_On	 kmode++
#define	Kmode_Off	 kmode--

extern int time_ch;
extern int CommandsTime;
extern int IdleTime;

#include	"trace.h"
SHAR_EOF
fi # end of overwriting check
cd ..
if test -f 'ext.c'
then
	echo shar: will not over-write existing file "'ext.c'"
else
cat << \SHAR_EOF > 'ext.c'
static char	rcsid[] = "$Header: ext.c,v 3.3 86/11/03 12:34:59 gil Exp $";

/*
 * $Log:	ext.c,v $
 * Revision 3.3  86/11/03  12:34:59  gil
 * buffered channels and special channels are wrapped within 'ifdefs' for
 * flexible configuration.
 *
 * Revision 3.2  86/11/02  09:09:27  gil
 * somehow the buffered-cahnnels version got in the way as revision 3.1, BEWARE.
 *
 * Revision 2.1  86/10/30  18:14:52  gil
 * This version was submitted for the project. It is free of all major bugs.
 *
 * Revision 1.1  86/01/04  14:48:59  gil
 * Initial revision
 *
 */

#include <stdio.h>
#include "trace.h"

chtabopen(tab, siz, nel)
	register int	*tab;
{
	TRACE(TRACE_IO, ("open channel table at 0x%x - %d", tab, nel));
	while (nel--)
		*tab++ = chopen(siz);
}

chtabclose(tab, nel)
	register int	*tab;
{
	TRACE(TRACE_IO, ("close channel table at 0x%x - %d", tab, nel));
	while(nel--)
		chclose(*tab++);
}

int dflag;
#define debugfp stderr
/*VARARGS1*/
debug(fmt, a1, a2, a3, a4, a5, a6)
	char *fmt;
{
	if(dflag)
		fprintf(debugfp, fmt, a1, a2, a3, a4, a5, a6);
}

bcopy(from, to, len)
	register int	*from, *to;
	register len;
{

	len >>= 2;
	while(len--)
		*to++ = *from++;
}

SHAR_EOF
fi # end of overwriting check
if test -f 'machdep.s'
then
	echo shar: will not over-write existing file "'machdep.s'"
else
cat << \SHAR_EOF > 'machdep.s'
	.globl	_SetJmp			# the _Setjmp subroutine in VAX
					# became _setjmp procedure for TAHOE
_SetJmp:
	.word	0x0
	movl	4(fp),r1
	storer	$0x1ffc,(r1)
	addl2	$44,r1
	movl	(fp),(r1)
	addl2	$4,r1
	movab	8(fp),(r1)
	addl2	$4,r1
	movl	-8(fp),(r1)
	clrl	r0
	ret

	.globl	_LongJmp		# the _Longjmp subroutine in VAX
					# became _longjmp procedure for TAHOE
_LongJmp:
	.word	0x0000
	movl	4(fp),r1
	loadr	$0x3ffc,(r1)
	addl2	$48,r1
#	movl	(r2),r1
	movl	(r1),r0
	addl2	$4,r1
#	movab	(sp),r0
#	cmpl	r1,r0				# must be a pop
#	bgequ	lj2
#	pushab	lj1
#	callf	$8,_panic
lj2:
	movl	r0,sp
	movl	$1,r0
	jmp	*(r1)

lj1:	.asciz	"longjmp"
SHAR_EOF
fi # end of overwriting check
if test -f 'chq.c'
then
	echo shar: will not over-write existing file "'chq.c'"
else
cat << \SHAR_EOF > 'chq.c'
/* $Header: chq..c,v 3.3 86/11/03 12:34:56 gil Exp $ */

/*
 * $Log:	chq.c,v $
 * Revision 3.3  86/11/03  12:34:56  gil
 * buffered channels and special channels are wrapped within 'ifdefs' for
 * flexible configuration.
 *
 * Revision 3.2  86/11/03  11:08:21  gil
 * this version supports buffered channel.
 *
 * Revision 3.1  86/11/01  15:42:53  gil
 * *** empty log message ***
 *
 */

#include <stdio.h>
#include "conf.h"
#include "process.h"
#include "chan.h"


IO(ch, tm)
	Channel	*ch;
	int	tm;
{

	if (IsTime(ch)) {
		debug("[%d] read time\n",
			ch->ch_read.b_next->b_proc - proctable);
		tread(ch, tm);
#ifdef	S_VMS
	} else if (IsVms(ch)) {
		debug("(%d) i/o in vms channel\n", chidof(ch));
		VmsIO(ch, tm);
#endif S_VMS
#ifdef S_SYS
	} else if (IsSpecial(ch)) {	/* this is s UNIX channel */
		debug("(%d) i/o in sys channel\n", chidof(ch));
		SysIO(ch, tm);
#endif S_SYS
	} else
		IoMove(ch, tm);
}

IoMove(ch, tm)
	Channel	*ch;
	int	tm;
{

	IoBlock		*rblk, *wblk;
	register	ri, wi;
	register	i, n;
	int		len;

	rblk = ch->ch_read.b_next;
	wblk = ch->ch_write.b_next;

	if (rblk->b_ndata != wblk->b_ndata)
		panic("noncompatible receive-send request on channel\n");
		
	n = rblk->b_ndata;
	for (i = 0; i < n; i++, ri++, wi++) {

		if (rblk->b_data[i].io_len != wblk->b_data[i].io_len)	
			panic("noncompatible sizes in receive-send\n");
		len = rblk->b_data[i].io_len;
		NTRACE(TRACE_IO,
		       ("[%d] sent %d bytes from %s to %s", chidof(ch), len,
		         Pinfo(wblk->b_proc), Pinfo(rblk->b_proc)));
		bcopy(wblk->b_data[i].io_data,rblk->b_data[i].io_data, len);
	}

	ReadDone(ch, tm);
	WriteDone(ch, tm);
}

#ifdef	S_SYS
SysIO(ch, tm)
	Channel	*ch;
{

	IoBlock		*rblk, *wblk;

	rblk = ch->ch_read.b_next;
	wblk = ch->ch_write.b_next;

	if (!rblk)
		SysWrite(ch, tm);
	else if (!wblk)
		SysRead(ch, tm);
	else if (rblk->b_proc->p_time < wblk->b_proc->p_time)
		SysRead(ch, tm);
	else
		SysWrite(ch, tm);
}
#endif	S_SYS

#ifdef	S_VMS
VmsIO(ch, tm)
	Channel	*ch;
{

	IoBlock		*rblk, *wblk;

	rblk = ch->ch_read.b_next;
	wblk = ch->ch_write.b_next;

	if (!rblk)
		VmsWrite(ch, tm);
	else if (!wblk)
		VmsRead(ch, tm);
	else if (rblk->b_proc->p_time < wblk->b_proc->p_time)
		VmsRead(ch, tm);
	else
		VmsWrite(ch, tm);
}
#endif	S_VMS

/* EnterRequest:
 * Enter the read/write request into the channel's read/write queue,
 */
EnterRequest(io_list, flags, len, arg_iov, id)
	IoBlock	*io_list;
	IoVec	*arg_iov;
{

	register IoBlock	*blk;
	register IoBlock	*iob;
	register IoBlock	*ip;
	register	i;

	blk = new(ioblock);

	for (iob = io_list; iob->b_next; iob = iob->b_next)
		;
	blk->b_next = iob->b_next;
	iob->b_next = blk;	

	blk->b_ndata = len;
	blk->b_proc = proc;
	blk->b_id   = id;
	blk->b_data = (IoVec *)calloc(len, sizeof(IoVec));
	for(i = 0; i < len; i++)
		blk->b_data[i] = *arg_iov++;
		/* notice: this means that iov.io_data is passed
		 : by REFERENCE */
}

ReadDone(ch, time)
	Channel	*ch;
{
	register IoBlock	*ip;

	ip = ch->ch_read.b_next;
	ip->b_proc->p_time = time;
	ip->b_proc->p_chid = chidof(ch);
	ip->b_proc->p_eventid = 0;
		unblock(ip->b_proc, BLOCK_IO);
	free(ip->b_data);
	ch->ch_read.b_next = ip->b_next;
	free(ip);
}

WriteDone(ch, time)
	Channel	*ch;
{
	register IoBlock	*ip;
	register		n;

#ifdef	BUFF_CHANS
	/* notice: we walk n steps (and not n-1) because the current IO is
 	 * not freed yet. */
	for (ip = ch->ch_write.b_next, n = ch->ch_siz;
	     ip && n > 0;
	     ip = ip->b_next, n--)
		;

	if (ip) {
		ip->b_proc->p_time = time;
		unblock(ip->b_proc, BLOCK_IO);
	}

	ip = ch->ch_write.b_next;

#else	BUFF_CHANS
	ip = ch->ch_write.b_next;
	ip->b_proc->p_time = time;
	unblock(ip->b_proc, BLOCK_IO);
#endif	BUFF_CHANS

	free(ip->b_data);
	ch->ch_write.b_next = ip->b_next;
	free(ip);
}


TimeOf(ch)
	Channel	*ch;
{
/* return -1 if no I/O ready on 'ch', otherwise return the time of the I/O
 * operation
 */

	register IoBlock	*rfirst, *wfirst, *temp;
	IoVec			*iov;

	Expire(ch);

	rfirst = ch->ch_read.b_next;
	wfirst = ch->ch_write.b_next;

	if (IsTime(ch)) {
		if (rfirst == NULL)
			return -1;
		return(rfirst->b_proc->p_time);
	}

#ifdef	S_SYS
	if (IsSpecial(ch)) {
	
		if (rfirst && wfirst)
			return (
			  min(rfirst->b_proc->p_time,wfirst->b_proc->p_time)
			);

		if (rfirst)
			return(rfirst->b_proc->p_time);

		if (wfirst)
			return(wfirst->b_proc->p_time);

		return -1;
	}
#endif	S_SYS
	
	if (!rfirst :: !wfirst) {
		return -1;
	}
		
	debug("channel %d is ready for I/O\n", chidof(ch));

	return (max(wfirst->b_proc->p_time, rfirst->b_proc->p_time));
}


Expire(ch)
	Channel	*ch;
{

	register IoBlock	*rfirst;
	register IoBlock	*Iob;

	rfirst = &ch->ch_read;
	while (rfirst->b_next &&
	       rfirst->b_next->b_next->b_id &&
	       rfirst->b_next->b_proc->p_eventid != rfirst->b_next->b_id)
	{
		Iob = rfirst->b_next;
		rfirst->b_next = Iob->b_next;
		free(Iob->b_data);
		free(Iob);
	}
}

Size(Ioq)
	register IoBlock	*Ioq;
{
	register	i;

	for (i = 0; Ioq; Ioq = Ioq->b_next, i++)
		;
	return i;
}
SHAR_EOF
fi # end of overwriting check
if test -f 'stck.c'
then
	echo shar: will not over-write existing file "'stck.c'"
else
cat << \SHAR_EOF > 'stck.c'
static char	rcsid[] = "$Header: stck.c,v 3.2 86/11/03 12:35:11 gil Exp $";

/*
 * $Log:	stck.c,v $
 * Revision 3.2  86/11/03  12:35:11  gil
 * buffered channels and special channels are wrapped within 'ifdefs' for
 * flexible configuration.
 *
 * Revision 3.1  86/11/01  15:45:04  gil
 * A cleaner version, with timeout forced before each synchronization event.
 *
 * Revision 2.1  86/10/30  18:15:02  gil
 * This version was submitted for the project. It is free of all major bugs.
 *
 * Revision 1.1  86/01/04  14:49:05  gil
 * Initial revision
 *
 */

#include <stdio.h>
#include "conf.h"
#include "process.h"

caddr_t	StackBase;
int	StackReserve = 128;

Stack	NextStack;

extern kmode;

#ifdef vax
StackExpand(addr, sz, ap)
	caddr_t	addr, ap;
{
	register caddr_t	r11, r10, r9;
	int i;
	Stack	s, NewStack();

	Kmode_On;

	s = proc->p_curstack;
	proc->p_curstack = NextStack;
	r10 = realtop(proc->p_curstack);
/*	printf("stack expand addr: %x sz %d ap %x\n", addr, sz, ap); */
	write(1, "#", 1);
	asm("movl r10,sp")
/* call to functions will be executed on the new stack from this point */
	if(proc->p_curstack.s_size < (i = sz + StackReserve * 2)) {
		proc->p_curstack = NewStack(i);
		r10 = realtop(proc->p_curstack);
		asm("movl r10,sp")
	} else
		NextStack = NewStack(0);
		
	SetStack(&(proc->p_curstack));
	Kmode_Off;
	r10 = ap;
	r9 = addr;
	asm("callg (r10),(r9)")
	Kmode_On;
	FreeStack(proc->p_curstack);
	proc->p_curstack = s;
	SetStack(&(proc->p_curstack));
	Kmode_Off;
}
#else
StackExpand() {}
#endif

SetStack(s)
	register Stack	*s;
{
	StackBase = s->s_bottom;
}

#ifdef notdef
stacktrace() {
	register r12, r11;

	r12 = 0;
#ifdef tahoe
	asm("moval	(sp),r12")
	asm("movl	fp,r11")
#else vax
	asm("movl	sp, r11")
	asm("movl	fp, r10")
#endif
	fprintf(stderr, "proc: %d base: %x top: 0x%x sp: 0x%x fp: 0x%x used: %d\n",
		proc->p_pid, proc->p_stack.s_bottom,
		realtop(proc->p_stack), r12, r11, realtop(proc->p_stack)-r12);
}
#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'test.c'
then
	echo shar: will not over-write existing file "'test.c'"
else
cat << \SHAR_EOF > 'test.c'
static char	rcsid[] = "$Header: test.c,v 3.1 86/11/01 15:45:06 gil Exp $";

/*
 * $Log:	test.c,v $
 * Revision 3.1  86/11/01  15:45:06  gil
 * A cleaner version, with timeout forced before each synchronization event.
 *
 * Revision 2.1  86/10/30  18:15:05  gil
 * This version was submitted for the project. It is free of all major bugs.
 *
 * Revision 1.1  86/01/04  14:49:07  gil
 * Initial revision
 *
 */

test(){}

SHAR_EOF
fi # end of overwriting check
if test -f 'vmschan.c'
then
	echo shar: will not over-write existing file "'vmschan.c'"
else
cat << \SHAR_EOF > 'vmschan.c'
static	char	*rcsid = "$Header: vmschan.c,v 3.2 86/11/03 12:35:16 gil Exp $";
#include <stdio.h>
#include "conf.h"
#include "process.h"
#include "chan.h"
#include <sys/ioctl.h>
#include "vmsio.h"
#define	IsAtty	isatty

extern	char	*calloc();

#ifdef	S_VMS
	
chat(chid, vmsfd)
{
	Channel	*ch;
	
	ch = chanof(chid);
	ch->ch_flags = CH_VMS;
	ch->ch_fd = vmsfd;
}

VmsInit(av)
	char	**av;
{
	static	char	vmsbuf[256];

	while(*av) {
		strcat(vmsbuf, *av);
		if(*++av == NULL)
			break;
		strcat(vmsbuf, " ");
	}
	StdFile[C_Parameters].vms_stat = ARGSTR;
	StdFile[C_Parameters].vms_name = vmsbuf;

	StdFile[C_Keyboard].vms_stat = NORMAL;
	StdFile[C_Keyboard].vms_fp = stdin;

	StdFile[C_Screen].vms_stat = NORMAL;
	StdFile[C_Screen].vms_fp = stdout;
}


VmsWrite(ch, tm)
	Channel	*ch;
{
	IoBlock		*wblk;
	IoVec		*vv;
	register	i;
	int		len;
	VmsChan		*vc;

	vc = VFile(ch->ch_fd);
	
	wblk = ch->ch_write.b_next;
	vv = wblk->b_data;
	len = wblk->b_ndata;
	for(i = 0; i < len; i++, vv++) {
		if(vv->io_len != WORDSIZE)
			panic("non word messages are not alloud in Vms\n");
		Vwrite(vc, *vv->io_data);
	}
	WriteDone(ch, tm);
}

VmsRead(ch, tm)
	Channel	*ch;
{
	IoBlock		*rblk;
	IoVec		*vv;
	int		len;
	register 	i;
	VmsChan		*vc;

	vc = VFile(ch->ch_fd);
	
	rblk = ch->ch_read.b_next;
	vv = rblk->b_data;
	len = rblk->b_ndata;
	for(i = 0; i < len; i++, vv++) {
		if(vv->io_len != WORDSIZE)
			panic("non word messages are not alloud in Vms\n");
		Vread(vc, vv->io_data);
	}
	ReadDone(ch, tm);
}

VmsSelect() {
	panic("vms select not implemented yet");
	return 0;
}

Vread(vc, c)
	VmsChan	*vc;
	int	*c;
{
	int	cnt;

	if(vc->vms_message) {
		*c = vc->vms_message;
		vc->vms_message = 0;
		return;
	}
	if(vc->vms_stat == ARGSTR) {
		if((*c = *(vc->vms_name)) == '\0')
			*c = V_EndParameterString;
		else
			vc->vms_name++;
		return;
	}
	if(vc->vms_fp == NULL)
		panic("vms: can't read from closed file\n");
	if((vc->vms_fp->_flag & _IOREAD) == 0)
		panic("vms: file not open for reading\n");
again:
	if(vc->vms_fp->_cnt > 0) {
		*c = Getc(vc->vms_fp);
		return;
	}
	if(feof(vc->vms_fp)) {
		*c = V_EndFile;
		return;
	}
	if(IsAtty(vc->vms_fp)) {
		do
			ioctl(fileno(vc->vms_fp), FIONREAD, &cnt);
		while(cnt == 0 && vc->vms_fp->_cnt == 0 && Swtch());
		goto again;
	} else
		*c = Getc(vc->vms_fp);
}

Swtch() {
	swtch();
	return 1;
}

Getc(fp)
	FILE	*fp;
{
	int c;

	if((c = getc(fp)) == EOF) {
		if(ferror(fp))
			c = E_ReadFailed;
		else
			c = V_EndFile;
	}
	else if(c == '\n')
		c = V_EndRecord;
	return c;
}

Flush(vc)
	VmsChan	*vc;
{
	fflush(vc->vms_fp);
	if(ferror(vc->vms_fp))
		vc->vms_message = E_WriteFailed;
	else
		vc->vms_message = V_NextRecord;
}

Vwrite(vc, c)
	VmsChan	*vc;
{
	if(c < 0)
		goto control;

write:
	if(vc->vms_stat == NORMAL) {
		if(vc->vms_fp == NULL)
			panic("try to write on a closed file\n");
		putc(c, vc->vms_fp);
		if(c == '\n')
			Flush(vc);
	} else
	if(vc->vms_stat == FILENAME)
		AddC(vc, c);
	return;

control:
	switch (c) {
		case V_EndRecord:
			c = '\n';
			goto write;

		case V_NextRecord:
			break;

		case V_EndBuffer:
			if(vc->vms_fp == NULL)
				panic("flushing a closed file\n");
			Flush(vc);
			break;

		case V_OpenForRead:
			vc->vms_message = V_OpenForRead;
			vc->vms_stat = FILENAME;
			vc->vms_name = calloc(256, 1); /* XXX */
			break;

		case V_OpenForWrite:
			vc->vms_message = V_OpenForWrite;
			vc->vms_stat = FILENAME;
			vc->vms_name = calloc(256, 1); /* XXX */
			break;

		case V_EndName:
			OpenFile(vc);
			break;

		case V_CloseFile:
			CloseFile(vc);
			break;

		case V_EndFile:
			Flush(vc);
			break;
		default:
			panic("bad request\n");
	}
}

OpenFile(vc)
	VmsChan	*vc;
{
	char	*ms;

	if(vc->vms_message == V_OpenForRead)
		ms = "r";
	else
		ms = "w";
	vc->vms_fp = fopen(vc->vms_name+1, ms);
	if(vc->vms_fp == NULL)
		vc->vms_message = (vc->vms_message == V_OpenForRead) ?
				E_InputFileNotOpened :
				E_OutputFileNotCreated;
	else
		vc->vms_message = V_OpenedOK;
	vc->vms_stat = NORMAL;
	free(vc->vms_name);
}

AddC(vc, c)
	VmsChan	*vc;
{
	vc->vms_name[++(vc->vms_name[0])] = c;
}

CloseFile(vc)
	VmsChan	*vc;
{
	if(vc->vms_fp == NULL)
		panic("trying to close a closed file\n");
	fclose(vc->vms_fp);
	vc->vms_message = V_ClosedOK;
	vc->vms_fp = NULL;
}
#endif	S_VMS
SHAR_EOF
fi # end of overwriting check
if test -f 'chan.c'
then
	echo shar: will not over-write existing file "'chan.c'"
else
cat << \SHAR_EOF > 'chan.c'
static char	rcsid[] = "$Header: chan.c,v 3.4 86/11/03 12:34:21 gil Exp $";

/*
 : $Header: chan.c,v 3.4 86/11/03 12:34:21 gil Exp $
 */

/* $Log:	chan.c,v $
 * Revision 3.4  86/11/03  12:34:21  gil
 * buffered channels and special channels are wrapped within 'ifdefs' for
 * flexible configuration.
 *
 * Revision 3.3  86/11/03  11:08:08  gil
 * this version supports buffered channel.
 *
 * Revision 3.2  86/11/02  09:37:03  gil
 * fixed the race (Kmode_On should be BEFORE resched).
 *
 * Revision 3.1  86/11/01  15:48:04  gil
 * A cleaner version, with timeout forced before each synchronization event.
 *
 * Revision 2.1  86/10/30  18:14:49  gil
 * This version was submitted for the project. It is free of all major bugs.
 *
 * Revision 1.4  86/08/04  17:24:35  gil
 * 1. fixed few bugs
 * 2. change format of tracing messages
 *
 * Revision 1.3  86/05/29  10:28:49  gil
 * this version fits the new ready-requests-queue mechanism.
 *
 */

#include <stdio.h>
#include "conf.h"
#include "process.h"
#include "chan.h"

Channel	chans[MAX_CHANS];
Channel	*free_chans;

extern char	*calloc();
int	Eventid = 1;
int	time_ch;		/* keep the special time channel */

InitChans() {

	register i, j;
	
	for(i = 0, j = MAX_CHANS - 1; i < j; i++)
		chans[i].ch_nxt = &chans[i+1];
	chans[j].ch_nxt = NULL;
	free_chans = chans;
}

chopen(siz)
{

	register Channel *ch;

	Kmode_On;
	if (free_chans == NULL) {
		panic("no more channels\n");
		/*NOTREACHED*/
	}
	ch = free_chans;
	free_chans = free_chans->ch_nxt;
	Kmode_Off;
	TRACE(TRACE_IO, ("opened %d(%d)", ch-chans, siz));
	ch->ch_siz = siz;
	ch->ch_read.b_next = NULL;
	ch->ch_write.b_next = NULL;
	return (ch - chans);
}

chclose(chid) {

	register Channel *ch;

	Kmode_On;	
	if (chid < 0 :: chid >= MAX_CHANS)
		panic("bad channel\n");
	ch = &chans[chid];
	ch->ch_nxt = free_chans;
	free_chans = ch;
	ch->ch_read.b_next = 0;
	ch->ch_write.b_next = 0;
	TRACE(TRACE_IO, ("closed %d", chid));
	Kmode_Off;
}

chread(chid, flags, len, iov)
	IoVec	iov;
{

	register Channel	*ch;
	register		tm;

	ch = chanof(chid);
	timesync(proc);
	TRACE(TRACE_IO, ("read on %d", chid));
	if (IsTime(ch) && (flags & BD_FAFTER)) {
		proc->p_time =
		   max(proc->p_time, *((int *)(iov.io_data)));
		timewrite(proc);
		return;
	}
	Kmode_On;
	resched(0);
	EnterRequest(&(ch->ch_read), flags, len, &iov, 0);
	if ((tm = TimeOf(ch)) >= 0)
		IO(ch, tm);
	else
		block(proc, BLOCK_IO);
	Kmode_Off;
}

chwrite(chid, flags, len, iov)
	IoVec	iov;
{

	register Channel *ch;
	register	tm;

	ch = chanof(chid);
	timesync(proc);
	TRACE(TRACE_IO, ("write on %d", chid));
	Kmode_On;
	resched(0);
	EnterRequest(&(ch->ch_write), flags, len, &iov, 0);
	if ((tm = TimeOf(ch)) >= 0)
		IO(ch, tm);
#ifdef	BUFF_CHANS
	else if (!ch->ch_siz :: Size(ch->ch_write.b_next) > ch->ch_siz)
#else
	else
#endif
		block(proc, BLOCK_IO);
	Kmode_Off;
}

char *
chselect(nargs, arg1)
{
	struct IoReq {
		int	chid;
		int	nret;	/* saved data buf length */
		int	flags;
		int	len;
		IoVec	iov;
		/* Saved data [nret*4] */
	} *ap = (struct IoReq *)&arg1, *cp = ap;
	Channel *ch;
/*
 : This requires explanation:
 : We push quintets of 	< chid, nret, flags, len, iov >	as accepted
 : by 'chread'/'chwrite'. the problem is the 'iov' is actually a vector
 : of struct IoVec, and its length is given by 'len', and at the end of
 : each quintet is a data-buffer of length 'nret' * intsize.
 : So, when we advance to next quintet, the increment is of dynamic size,
 : which is:
 : 		sizeof (chid)
 :	    +	sizeof (flags)
 :	    +	sizeof (len)
 :	    +	sizeof (nret)
 :	    +	len * sizeof (iov)
 :	    +	nret * sizeof (int)
*/

	register i, n;
	int	ret;
	char	*p;
	char	b[5];
	static char buf[512];
	Channel	*chose = NULL;

	Kmode_On;
	Eventid++;
	sprintf(buf, "select on:");
	proc->p_eventid = Eventid;
	timesync(proc);
	resched(1);	/* let all the write-requests to get ready */
	resched(1);	/* let all the write-requests be acutally delivered */
	for(n = 1, i = nargs; i > 0; i--) {
		sprintf(b, " %d", cp->chid);
		strcat(buf, b);
		ch = chanof(cp->chid);
		EnterRequest(&(ch->ch_read), cp->flags, cp->len,
							&(cp->iov), Eventid);
		if (TimeOf(ch) >= 0) {
			if ((random() & MASKR) < (R / (float)n))
				/* first one alwaysgets chosen */
				chose = ch;
			n++;
		}
		cp = (struct IoReq *) ((char *)cp +
					sizeof(IoVec) * (cp->len-1) +
					cp->nret * sizeof(int));
		cp++;
	}
	TRACE(TRACE_IO, (buf));
	if (chose != NULL)
		IO(chose, TimeOf(chose));
	else
		block(proc, BLOCK_IO);

	for(cp = ap, i = nargs; i > 0; i--) {
		if(cp->chid == proc->p_chid) {
			p = (char *)(cp+1) + (cp->len - 1)* sizeof(IoVec);
			debug("chselect: 1st reg is %d\treg mask %x\n",
				((int *)p)[1], *((int *)p));
			debug("chselect: len = %d\n", cp->len);
			TRACE(TRACE_IO,
			      ("channel %d selected", cp->chid));
			Kmode_Off;
			return p;
		}
		cp = (struct IoReq *) ((char *)cp +
					sizeof(IoVec) * (cp->len-1) +
					cp->nret * sizeof(int));
		cp++;
	}
	panic("select channel disappeared");
	Kmode_Off;
}
SHAR_EOF
fi # end of overwriting check
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
# configurable parameters.
################################################################################
DESTDIR=/m/usr/gil
CC=cc
AS=as

CFLAGS=-Ih -g
################################################################################

LIB=lsim.a
OBJS=	chan.o\
	chq.o\
	ext.o\
	machdep.o\
	proto.o\
	sched.o\
	stck.o\
	sysio.o\
	test.o\
	vmschan.o\
	${EMPTY}

$(LIB): $(OBJS)
	ar cr $(LIB) $(OBJS)
	ranlib $(LIB)

install: $(LIB)
	mv $(LIB) $(DESTDIR)/lib/lsim.a
	ranlib $(DESTDIR)/lib/lsim.a

# dependencies on header files
################################################################################
chan.c:	h/conf.h
chan.c:	h/process.h
chan.c:	h/chan.h

chq.c:	h/conf.h
chq.c:	h/process.h
chq.c:	h/chan.h

ext.c:	h/trace.h

sched.c:	h/conf.h
sched.c:	h/process.h

stck.c:	h/conf.h
stck.c:	h/process.h

sysio.c:	h/conf.h
sysio.c:	h/process.h
sysio.c:	h/chan.h

vmschan.c:	h/conf.h
vmschan.c:	h/process.h
vmschan.c:	h/chan.h
vmschan.c:	h/vmsio.h
SHAR_EOF
fi # end of overwriting check
if test -f 'machdep.s.vax'
then
	echo shar: will not over-write existing file "'machdep.s.vax'"
else
cat << \SHAR_EOF > 'machdep.s.vax'
#	set/long jmp, no documatation since the source got lost, this is a
# disassembly.
		.globl	_SetJmp
_SetJmp:	.word 0x0
		movl	4(ap),r1
		movq	r2,(r1)+
		movq	r4,(r1)+
		movq	r6,(r1)+
		movq	r8,(r1)+
		movq	r10,(r1)+
		movq	8(fp),(r1)+
		moval	4(ap),(r1)+
		movl	16(fp),(r1)+
		movl	$0,r0
		ret

		.globl	_LongJmp
_LongJmp:	.word 0x0
		movl	4(ap),r1
		movq	(r1)+,r2
		movq	(r1)+,r4
		movq	(r1)+,r6
		movq	(r1)+,r8
		movq	(r1)+,r10
		movq	(r1)+,ap
		movl	(r1)+,sp
		movl	$1,r0
		jmp	*(r1)
SHAR_EOF
fi # end of overwriting check
if test -f 'sched.c'
then
	echo shar: will not over-write existing file "'sched.c'"
else
cat << \SHAR_EOF > 'sched.c'
static char rcsid[] = "$Header: sched.c,v 3.3 87/02/17 10:55:41 gil Exp $";

/*
 * $Log:	sched.c,v $
 * Revision 3.3  87/02/17  10:55:41  gil
 * Eventid removed.
 *
 * Revision 3.2  86/11/03  12:35:07  gil
 * buffered channels and special channels are wrapped within 'ifdefs' for
 * flexible configuration.
 *
 * Revision 3.1  86/11/01  15:42:58  gil
 * *** empty log message ***
 *
 * Revision 2.1  86/10/30  18:14:59  gil
 * This version was submitted for the project. It is free of all major bugs.
 *
 * Revision 1.6  86/07/07  17:08:34  gil
 * Cleaner version.
 * Removed cpu clock, sched and unused variables.
 *
 * Revision 1.5  86/07/07  16:47:12  gil
 * Working version.
 *
 * Revision 1.3  86/03/24  14:55:52  gil
 * added time synchronization for waiting processes.
 *
 * Revision 1.2  86/03/17  13:50:58  gil
 * *** empty log message ***
 *
 */

#include <stdio.h>
#include <sys/time.h>
#include "conf.h"
#include "process.h"

#define max(a, b)	((a) > (b) ? (a) : (b))

Process *proc;
/* dummy-firsts for: */
Process	wdummy,				/* wait-queue */
	rdummy,				/* run-queue */
	fdummy;				/* free-queue */

int	kmode;
extern	char	*malloc();	

#ifdef vax
#define savefp()	asm("	movl 12(fp), r11")
#define	saveap()	asm("	movl 8(fp),  r11")
#else tahoe
#define savefp()	asm("	movl (fp), r12")
#endif

Process *
nextrun()
{
	Process *run;

	run = runq->p_nxt;
	if (run == NULL)
		Deadlock();

	return run;
}

swtch() {
	register caddr_t fp;	/* must be r11(vax) r12(tahoe) */
	register Process *p;
	int	savedkmode = 0;

	p = nextrun();

	savefp();
	if(proc && !StackMask(proc))
		panic("Process Stack Underflow");
	if(p == proc)		/* no context switching is done - return */
		return;
	if(proc != NULL)
		if(save(proc)) {		/* save status */
			debug("start %d with kmode %d\n",
					proc-proctable, savedkmode);
			return;
		}
	
	if(!StackMask(p))
		panic("Process %s Stack Damaged", Pinfo(p));
	TRACE(TRACE_CSW, ("switching to %s", Pinfo(p)));
	resume(p);		/* transfer control to p - return on previous
				 : line... */
}

save(p)
	Process *p;
{

	p->p_kmode = kmode;
	return SetJmp(&(p->p_save));
}

resume(p)
	Process *p;
{
	debug("resuming %d pc %x\n", (p - proctable), p->p_save.st_pc);
	proc = p;
	SetStack(&(proc->p_curstack));
	kmode = p->p_kmode;
	sigsetmask(0);
	LongJmp(&(p->p_save));
	/*NOTREACHED*/
}

/* tick - interupt routine, called on each clock tick. */
tick() {

	if (kmode) {
		sigsetmask(0);
		return;
	}
	Kmode_On;
	resched(0);
	debug("kmode: %d\n", kmode);
	Kmode_Off;
	return;
}

resched(pri)
{
	if (proc != NULL) {
		timesync(proc);
		FreeMe(proc);
		if (pri)
			PriEnterMe(proc, runq);
		else
			EnterMe(proc, runq);
	}
	swtch();
}

int	DefaultStackSize = STACK_SIZE;

Stack
NewStack(sz)
{
	Stack s;

	if(sz == 0)
		sz = DefaultStackSize;
	s.s_bottom = malloc(sz);
	if(s.s_bottom == NULL)
		panic("alloc stack failed\n");
	s.s_bottom[0] = SMASK;
	s.s_size   = sz;
	return s;
}

FreeStack(s)
	Stack	s;
{
	free(s.s_bottom);
}

Process *
freeslot() {
	register Process *p;

	p = freeq->p_nxt;
	if(p == NULL)
		panic("no more process\n");
	freeq->p_nxt = p->p_nxt;
	p->p_nxt = NULL;
	p->p_prv = NULL;
	return p;
}

newproc(addr)
	caddr_t addr;
{
	register caddr_t save;	/* Must be in r11 (r12 on tahoe) */
/****	Don't use any other register for local storage	****/
	Process *p, *q;

	Kmode_On;
	p = proc;
	p->p_nsons++;

	q = freeslot();

	q->p_pid = genpid();
	q->p_ppid = p->p_pid;
	q->p_parent = p;
	q->p_nzomb = q->p_nsons = q->p_sontime = 0;
	timesync(p);
	q->p_time = p->p_time;	/* start with father's time */
	q->p_flags = 0;
	q->p_stack = NewStack(0);
	q->p_curstack = q->p_stack;
	SetJmp(&(q->p_save));
	q->p_save.st_dp = dispof(q->p_stack);
#ifdef vax
	saveap();
	q->p_save.st_ap = save;
#endif
	savefp();
	q->p_save.st_fp = save;
	q->p_save.st_sp = topof(q->p_stack);
	q->p_save.st_pc = addr;
	q->p_kmode = 0;
	/* Initialize the display */
	bcopy(bdispof(p->p_stack), bdispof(q->p_stack), DISPSIZE);
	timewrite(q);
	TRACE(TRACE_FORK, ("create %d at 0x%x", q->p_pid, addr));
	setrun(q);
	Kmode_Off;
	return;
}

endproc() {

	Kmode_On;
	timesync(proc);
	TRACE(TRACE_FORK, ("ended"));
	debug("endproc %d\n", proc - proctable);
	FreeMe(proc);
	if(proc->p_parent) {
		proc->p_parent->p_nsons--;
		WakePapa(proc->p_parent);
		/* Dalia was slightly drunk when she wrote this.
		 : please don't change */
	}
	if (proc->p_nsons > 0 :: proc->p_nzomb > 0) {
		proc->p_flags := PF_ZOMB;
		if(proc->p_parent)
			proc->p_parent->p_nzomb++;
		while(proc->p_nsons > 0 :: proc->p_nzomb > 0)
			block(proc, BLOCK_CHILD);
		if(proc->p_parent)
			proc->p_parent->p_nzomb--;
		WakePapa(proc->p_parent);
	}
	EnterMe(proc, freeq);
	FreeStack(proc->p_stack);
	proc = NULL;
	swtch();
	/*NOTREACHED*/
}

setrun(p)
	Process *p;
{
	debug("setrun: %d\n", p-proctable);
	p->p_stat = RUNNING;
	EnterMe(p, runq);
}

WakePapa(papa)
	Process *papa;
{
	if(papa) {
		papa->p_sontime = max(papa->p_sontime, proc->p_time);
		if(papa->p_nsons == 0)
			unblock(papa, BLOCK_CHILD);
	}
}

waitall() {

	Kmode_On;
	timesync(proc);
	while (proc->p_nsons > 0)
		block(proc, BLOCK_CHILD);

	proc->p_time = proc->p_sontime;
	proc->p_sontime = 0;
	timewrite(proc);
	Kmode_Off;
}

genpid() {
	static pid = 1;

	return pid++;
}

extern Stack	NextStack;

initproc() {
	register j, i;

	Kmode_On;
	NextStack = NewStack(0);
	for(i = 1, j = nproc - 1; i < j; i++) {
		proctable[i].p_nxt = &proctable[i+1];
		proctable[i+1].p_prv = &proctable[i];
	}
	proctable[j].p_nxt = NULL;

	freeq = &fdummy;
	fdummy.p_nxt = &proctable[1];
	proctable[1].p_prv = freeq;

	wdummy.p_nxt = wdummy.p_prv = NULL;
	waitq = &wdummy;

	proc = &proctable[0];
	runq = &rdummy;
	rdummy.p_nxt = proc;
	rdummy.p_prv = NULL;
	proc->p_prv = runq;

	Kmode_Off;
}

block(p, block_stat)
	Process	*p;
	enum pstat block_stat;
{

	TRACE(TRACE_BLOCK, ("blocked, on %s", BlockStat(block_stat)));
	debug("block %d\n", p - proctable);
	p->p_stat = block_stat;
	FreeMe(p);
	EnterMe(p, waitq);
	if (proc == p)
		swtch();
}

unblock(p, block_stat)
	Process	*p;
	enum pstat block_stat;
{

	debug("unblock %d\n", p - proctable);
	TRACE(TRACE_BLOCK,
	      ("unblock %s, on %s", Pinfo(p), BlockStat(block_stat)));
	if (p->p_stat == block_stat) {
		timewrite(p);
		FreeMe(p);
		setrun(p);
	}
}

EnterMe(pp, queue)
	Process	*pp, *queue;
{

	register		n;
	register Process	*q, *chose;

	for (q = queue;
	     q->p_nxt && q->p_nxt->p_time < pp->p_time;
	     q = q->p_nxt)
		;

	for (chose = q, n = 2;
	     q->p_nxt && q->p_nxt->p_time == pp->p_time;
	     q = q->p_nxt, n++)
	
	     	if ((random() & MASKR) < (R / (float)n))
			chose = q->p_nxt;

	pp->p_nxt = chose->p_nxt;
	pp->p_prv = chose;
	if (chose->p_nxt)
		chose->p_nxt->p_prv = pp;
	chose->p_nxt = pp;
}

PriEnterMe(pp, queue)
	Process	*pp, *queue;
{

	register Process	*q;

	for (q = queue;
	     q->p_nxt && q->p_nxt->p_time <= pp->p_time;
	     q = q->p_nxt)
		;

	pp->p_nxt = q->p_nxt;
	pp->p_prv = q;
	if (q->p_nxt)
		q->p_nxt->p_prv = pp;
	q->p_nxt = pp;
}

FreeMe(p)
	Process	*p;
{

	register Process *q;

	q = p->p_nxt;
	if(p->p_prv != NULL)
		p->p_prv->p_nxt = q;
	if(q != NULL)
		q->p_prv = p->p_prv;
}

Deadlock() {

	if (waitq->p_nxt != NULL)
		panic("deadlock\n");
	printf("process terminated successfully\n");
	exit(0);
}

timesync(p)
	Process	*p;
{
	p->p_time = *(int *)timeof(p->p_stack);
	debug("[%d] time %d\n", proc-proctable, p->p_time);
}

timewrite(p)
	Process	*p;
{
	*(int *) timeof(p->p_stack) = p->p_time;
}
SHAR_EOF
fi # end of overwriting check
if test -f 'proto.c'
then
	echo shar: will not over-write existing file "'proto.c'"
else
cat << \SHAR_EOF > 'proto.c'
static char	rcsid[] = "$Header: proto.c,v 3.2 86/11/03 12:35:04 gil Exp $";

/*
 * $Log:	proto.c,v $
 * Revision 3.2  86/11/03  12:35:04  gil
 * buffered channels and special channels are wrapped within 'ifdefs' for
 * flexible configuration.
 *
 * Revision 3.1  86/11/01  15:48:08  gil
 * A cleaner version, with timeout forced before each synchronization event.
 *
 * Revision 2.1  86/10/30  18:14:57  gil
 * This version was submitted for the project. It is free of all major bugs.
 *
 * Revision 1.1  86/01/04  14:49:02  gil
 * Initial revision
 *
 */

#include	<stdio.h>
#include	<signal.h>
#include	<sys/time.h>
#include 	"conf.h"
#include	"process.h"

extern tick();
#define	ALOT	(512*1024)
static char	display[DISPSIZE+COUNTSIZE];
extern	dflag;
int	qflag;
extern	DefaultStackSize, StackReserve;
char	*progname;
int	CommandsTime;

main(ac, av)
	char **av;
{
	register char *r11, i = 25;
	int	oc_main();


	progname = av[0];
	tracef = stderr;

	setlinebuf(stderr);
	while(**++av == '-')
	switch(*++*av) {
		case 'd':
			dflag++;
			break;
		case 's':
			{
			int s = atoi(++*av);
			if(s < DISPSIZE+64) {
			    	fprintf(stderr, "%d: Stack too small\n", s);
				break;
			    }
			debug("StackSize: %d\n", s);
			DefaultStackSize = s;
			break;
			}
		case 'r':
			{
			int s = atoi(++*av);
			if(s < 0) {
			    	fprintf(stderr, "Cannot UnReserve stack\n");
				break;
			    }
			debug("ReserveStack: %d\n", s);
			StackReserve = s;
			break;
			}
		case 'i':
			i = atoi(++*av);
			if(i < 1) {
			fprintf(stderr, "%d: Bad interval\n",
				i);
				i = 25;
			     }
			    debug("Will interupt %d times/sec\n", i);
			break;
		case 't':
			if(*++*av == '\0')
				tracer := TRACE_ALL;
			else
				tracer := tflag(*av);
			break;
		case 'q':
			qflag++;
			break;
		case 'f':
			if(*++*av == '\0')
				tracef = stdout;
			else {
				if((tracef = fopen(*av, "w")) == NULL) {
					fprintf(stderr,
					       "Cannot open trace file ");
					fflush(stderr);
					perror(*av);
					exit(1);
				}
			}
			break;
	
		default:
			fprintf	(stderr, "%c: Unknown option\n", **av);
			break;
	}
	srandom((int)time(0));
	initproc();
	InitChans();
#ifdef	S_VMS
	VmsInit(av);
#endif	S_VMS
	signal(SIGVTALRM, tick);
	inton(i);
	r11 = &display[DISPSIZE+COUNTSIZE];
	proc->p_stack.s_bottom = r11 - ALOT;
	proc->p_stack.s_size	 = ALOT;
	newproc(oc_main);
	test();
	waitall();
	if(!qflag)
		fprintf(stderr,
			"Executed %d instructions in %d time\n",
			CommandsTime, proctable[0].p_time);
	exit(0);
}

intoff() {
	struct itimerval it;
	it.it_interval.tv_sec = it.it_value.tv_usec = 0;
	it.it_value = it.it_interval;
	setitimer(ITIMER_VIRTUAL, &it, 0);
}

int	Ival;			/* IPS */

inton(t) {
	struct itimerval it;

	Ival = t;
	it.it_interval.tv_usec = 1000000/t;
	it.it_interval.tv_sec = 0;
	it.it_value = it.it_interval;
	setitimer(ITIMER_VIRTUAL, &it, 0);
}

panic(s, a1, a2, a3, a4) {
	fprintf(stderr, "Panic: %s: ", Pinfo(proc));
	fprintf(stderr, s, a1, a2, a3, a4);
	putc('\n', stderr);
	exit(1);
}


tflag(s)
	char	*s;
{
	int f = 0;

	while(*s) {
		switch (*s) {
			case 'c':
				f := TRACE_CSW;
				break;
			case 'f':
			case 's':
				f := TRACE_FORK;
				break;
			case 'b':
				f := TRACE_BLOCK;
				break;
			case 'a':
				f := TRACE_ALLIO;
				break;
			case 'i':
				f := TRACE_IO;
				break;
			default:
				fprintf(stderr, "%c: unknown trace flag\n",
					*s);
					break;
		}
		s++;
	}
	return f;
}

int	tracer;
char	*tstr = "\1CSW\0\2FORK\0\4BLOCK\0\010TIME\0\020IO\0\040MOREIO\0\100CPUT";

pflg(flg)
{

	fprintf(tracef, "%s", Pinfo(proc));
	nflg(flg);
}

sflg(flg)
{
	fprintf(tracef, "[ Sys   ]");
	nflg(flg);
}

char *
Pinfo(p)
	Process	*p;
{
	static char buf[3][128];
	static use;
	register char *s;

	s = buf[use++%3];
	if(p)
		sprintf(s, "[%-3d,%2d]", p->p_pid, p->p_time);
	else
		sprintf(s, "[ Nop   ]");
}

char *
BlockStat(b)
	enum pstat b;
{
	switch (b) {
		case BLOCK_CHILD:
			return "child event";
		case BLOCK_IO:
			return "I/O event";
		case RUNNING:
			return "Running???!!!";
		default:
			return "Unknown Status";
	}
}


nflg(flg)
{
	register char *s;
	register once = 0, c;

	putc('<', tracef);
	for(s = tstr; *s; s++) {
		c = *s;
		if(c & flg) {
			if(once)
				putc(',', tracef);
			once = 1;
			while(*++s)
				putc(*s, tracef);
		} else
			while(*++s)
				;
	}
	putc('>', tracef);
	putc(' ', tracef);
}

/*VARARGS*/
ptrace(fmt, a1, a2, a3, a4, a5, a6)
	char	*fmt;
{
	fprintf(tracef, fmt, a1, a2, a3, a4, a5, a6);
	putc('\n', tracef);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'sched.s'
then
	echo shar: will not over-write existing file "'sched.s'"
else
cat << \SHAR_EOF > 'sched.s'
.data
.data
_rcsid:.long	0x61654824
.long	0x3a726564
.long	0x68637320
.long	0x632e6465
.long	0x3320762c
.long	0x3820322e
.long	0x31312f36
.long	0x2033302f
.long	0x333a3231
.long	0x37303a35
.long	0x6c696720
.long	0x70784520
.long	0x2420
.comm	_runq,4
.comm	_waitq,4
.comm	_freeq,4
.comm	_proctable,32768
.comm	_tracef,4
.comm	_proc,4
.comm	_wdummy,128
.comm	_rdummy,128
.comm	_fdummy,128
.comm	_kmode,4
.text
LL0:.align	1
.globl	_nextrun
.set	L41,0x0
.data
.text
_nextrun:.word	L41
subl2	$4,sp
movl	_runq,r0
movl	44(r0),-4(fp)
jneq	L45
calls	$0,_Deadlock
L45:movl	-4(fp),r0
ret
.align	1
.globl	_swtch
.data	1
L57:.ascii	"start %d with kmode %d\12\0"
.text
.data	1
L61:.ascii	"switching to %s\0"
.text
.set	L48,0x800
.data
.text
_swtch:.word	L48
subl2	$4,sp
clrl	-4(fp)
calls	$0,_nextrun
movl	r0,r11
cmpl	r11,_proc
jneq	L52
ret
L52:tstl	_proc
jeql	L53
pushl	_proc
calls	$1,_save
tstl	r0
jeql	L53
pushl	-4(fp)
subl3	$_proctable,_proc,r0
divl3	$128,r0,-(sp)
pushal	L57
calls	$3,_debug
ret
L53:jlbc	_tracer,L58
pushl	$1
calls	$1,_pflg
pushl	r11
calls	$1,_Pinfo
pushl	r0
pushal	L61
calls	$2,_ptrace
L58:pushl	r11
calls	$1,_resume
ret
.align	1
.globl	_save
.set	L63,0x0
.data
.text
_save:.word	L63
movl	4(ap),r0
movl	_kmode,108(r0)
addl3	$52,4(ap),-(sp)
calls	$1,_SetJmp
ret
.align	1
.globl	_resume
.data	1
L72:.ascii	"resuming %d pc %x\12\0"
.text
.set	L68,0x0
.data
.text
_resume:.word	L68
movl	4(ap),r0
pushl	104(r0)
subl3	$_proctable,r0,r0
divl3	$128,r0,-(sp)
pushal	L72
calls	$3,_debug
movl	4(ap),_proc
addl3	$120,_proc,-(sp)
calls	$1,_SetStack
movl	4(ap),r0
movl	108(r0),_kmode
pushl	$0
calls	$1,_sigsetmask
addl3	$52,4(ap),-(sp)
calls	$1,_LongJmp
ret
.align	1
.globl	_tick
.data	1
L83:.ascii	"kmode\72 %d\12\0"
.text
.set	L77,0x0
.data
.text
_tick:.word	L77
tstl	_kmode
jeql	L81
pushl	$0
calls	$1,_sigsetmask
ret
L81:incl	_kmode
pushl	$0
calls	$1,_resched
pushl	_kmode
pushal	L83
calls	$2,_debug
decl	_kmode
ret
.align	1
.globl	_resched
.set	L84,0x0
.data
.align	2
.globl	_DefaultStackSize
_DefaultStackSize:.long	8192
.text
_resched:.word	L84
tstl	_proc
jeql	L88
pushl	_proc
calls	$1,_timesync
pushl	_proc
calls	$1,_FreeMe
tstl	4(ap)
jeql	L91
pushl	_runq
pushl	_proc
calls	$2,_PriEnterMe
jbr	L88
L91:pushl	_runq
pushl	_proc
calls	$2,_EnterMe
L88:calls	$0,_swtch
ret
.align	1
.globl	_NewStack
.data	1
L104:.ascii	"alloc stack failed\12\0"
.text
.lcomm	L105,8
.set	L97,0x0
.data
.text
_NewStack:.word	L97
subl2	$8,sp
tstl	4(ap)
jneq	L101
movl	_DefaultStackSize,4(ap)
L101:pushl	4(ap)
calls	$1,_malloc
movl	r0,-4(fp)
tstl	r0
jneq	L102
pushal	L104
calls	$1,_panic
L102:movl	4(ap),-8(fp)
moval	-8(fp),r0
movab	L105,r1
movq	(r0),(r1)
movab	L105,r0
ret
.align	1
.globl	_FreeStack
.set	L107,0x0
.data
.text
_FreeStack:.word	L107
pushl	8(ap)
calls	$1,_free
ret
.align	1
.globl	_freeslot
.data	1
L118:.ascii	"no more process\12\0"
.text
.set	L113,0x800
.data
.text
_freeslot:.word	L113
movl	_freeq,r0
movl	44(r0),r11
jneq	L117
pushal	L118
calls	$1,_panic
L117:movl	_freeq,r0
movl	44(r11),44(r0)
clrl	44(r11)
clrl	48(r11)
movl	r11,r0
ret
.align	1
.globl	_newproc
.data	1
L128:.ascii	"create %d at 0x%x\0"
.text
.set	L120,0x800
.data
.text
_newproc:.word	L120
subl2	$8,sp
incl	_kmode
movl	_proc,-4(fp)
movl	-4(fp),r0
incl	12(r0)
calls	$0,_freeslot
movl	r0,-8(fp)
calls	$0,_genpid
movl	r0,*-8(fp)
movl	-8(fp),r0
movl	*-4(fp),4(r0)
movl	-8(fp),r0
movl	-4(fp),8(r0)
movl	-8(fp),r0
clrl	20(r0)
movl	-8(fp),r1
movl	20(r0),12(r1)
movl	-8(fp),r0
movl	12(r1),16(r0)
pushl	-4(fp)
calls	$1,_timesync
movl	-4(fp),r0
movl	-8(fp),r1
movl	24(r0),24(r1)
movl	-8(fp),r0
clrl	28(r0)
pushl	$0
calls	$1,_NewStack
addl3	$112,-8(fp),r1
movq	(r0),(r1)
addl3	$112,-8(fp),r0
addl3	$120,-8(fp),r1
movq	(r0),(r1)
addl3	$52,-8(fp),-(sp)
calls	$1,_SetJmp
movl	-8(fp),r0
movl	r0,r1
addl3	112(r1),116(r0),r0
subl2	$4,r0
movl	r0,88(r1)
movl	8(fp),  r11
movl	-8(fp),r0
movl	r11,92(r0)
movl	12(fp), r11
movl	-8(fp),r0
movl	r11,96(r0)
movl	-8(fp),r0
movl	r0,r1
addl3	112(r1),116(r0),r0
subl2	$68,r0
movl	r0,100(r1)
movl	-8(fp),r0
movl	4(ap),104(r0)
movl	-8(fp),r0
clrl	108(r0)
pushl	$64
movl	-8(fp),r0
movl	r0,r1
addl3	112(r1),116(r0),r0
subl3	$68,r0,-(sp)
movl	-4(fp),r0
movl	r0,r1
addl3	112(r1),116(r0),r0
subl3	$68,r0,-(sp)
calls	$3,_bcopy
pushl	-8(fp)
calls	$1,_timewrite
jbc	$1,_tracer,L127
pushl	$2
calls	$1,_pflg
pushl	4(ap)
pushl	*-8(fp)
pushal	L128
calls	$3,_ptrace
L127:pushl	-8(fp)
calls	$1,_setrun
decl	_kmode
ret
.align	1
.globl	_endproc
.data	1
L136:.ascii	"ended\0"
.text
.data	1
L137:.ascii	"endproc %d\12\0"
.text
.set	L131,0x0
.data
.text
_endproc:.word	L131
incl	_kmode
pushl	_proc
calls	$1,_timesync
jbc	$1,_tracer,L135
pushl	$2
calls	$1,_pflg
pushal	L136
calls	$1,_ptrace
L135:subl3	$_proctable,_proc,r0
divl3	$128,r0,-(sp)
pushal	L137
calls	$2,_debug
pushl	_proc
calls	$1,_FreeMe
movl	_proc,r0
tstl	8(r0)
jeql	L138
movl	8(r0),r0
decl	12(r0)
movl	_proc,r0
pushl	8(r0)
calls	$1,_WakePapa
L138:movl	_proc,r0
tstl	12(r0)
jgtr	L9999
tstl	16(r0)
jleq	L140
L9999:movl	_proc,r0
bisl2	$1,28(r0)
movl	_proc,r0
tstl	8(r0)
jeql	L142
movl	8(r0),r0
incl	16(r0)
jbr	L142
L9998:pushl	$0
pushl	_proc
calls	$2,_block
L142:movl	_proc,r0
tstl	12(r0)
jgtr	L9998
tstl	16(r0)
jgtr	L9998
tstl	8(r0)
jeql	L145
movl	8(r0),r0
decl	16(r0)
L145:movl	_proc,r0
pushl	8(r0)
calls	$1,_WakePapa
L140:pushl	_freeq
pushl	_proc
calls	$2,_EnterMe
movl	_proc,r0
subl2	$8,sp
movq	112(r0),(sp)
calls	$2,_FreeStack
clrl	_proc
calls	$0,_swtch
ret
.align	1
.globl	_setrun
.data	1
L150:.ascii	"setrun\72 %d\12\0"
.text
.set	L146,0x0
.data
.text
_setrun:.word	L146
subl3	$_proctable,4(ap),r0
divl3	$128,r0,-(sp)
pushal	L150
calls	$2,_debug
movl	4(ap),r0
movl	$2,40(r0)
pushl	_runq
pushl	4(ap)
calls	$2,_EnterMe
ret
.align	1
.globl	_WakePapa
.set	L151,0x0
.data
.text
_WakePapa:.word	L151
tstl	4(ap)
jeql	L155
movl	4(ap),r0
movl	_proc,r1
cmpl	20(r0),24(r1)
jleq	L9997
movl	20(r0),r0
jbr	L9996
L9997:movl	_proc,r0
movl	24(r0),r0
L9996:movl	4(ap),r1
movl	r0,20(r1)
movl	4(ap),r0
tstl	12(r0)
jneq	L155
pushl	$0
pushl	r0
calls	$2,_unblock
L155:ret
.align	1
.globl	_waitall
.set	L159,0x0
.data
.text
_waitall:.word	L159
incl	_kmode
pushl	_proc
calls	$1,_timesync
jbr	L163
L2000002:pushl	$0
pushl	_proc
calls	$2,_block
L163:movl	_proc,r0
tstl	12(r0)
jgtr	L2000002
movl	r0,r1
movl	20(r0),24(r1)
movl	_proc,r0
clrl	20(r0)
pushl	_proc
calls	$1,_timewrite
decl	_kmode
ret
.align	1
.globl	_genpid
.data
.align	2
L169:.long	1
.text
.set	L165,0x0
.data
.text
_genpid:.word	L165
movl	L169,r0
incl	L169
ret
.align	1
.globl	_initproc
.set	L172,0xc00
.data
.text
_initproc:.word	L172
incl	_kmode
pushl	$0
calls	$1,_NewStack
movq	(r0),_NextStack
movl	$1,r10
movzbl	$255,r11
jbr	L178
L2000004:addl3	$1,r10,r0
ashl	$7,r0,r0
addl2	$_proctable,r0
ashl	$7,r10,r1
movl	r0,_proctable+44(r1)
ashl	$7,r10,r0
addl2	$_proctable,r0
addl3	$1,r10,r1
ashl	$7,r1,r1
movl	r0,_proctable+48(r1)
incl	r10
L178:cmpl	r10,r11
jlss	L2000004
ashl	$7,r11,r0
clrl	_proctable+44(r0)
moval	_fdummy,_freeq
moval	_proctable+128,_fdummy+44
movl	_freeq,_proctable+176
clrl	_wdummy+48
movl	_wdummy+48,_wdummy+44
moval	_wdummy,_waitq
moval	_proctable,_proc
moval	_rdummy,_runq
movl	_proc,_rdummy+44
clrl	_rdummy+48
movl	_proc,r0
movl	_runq,48(r0)
decl	_kmode
ret
.align	1
.globl	_block
.data	1
L184:.ascii	"blocked, on %s\0"
.text
.data	1
L185:.ascii	"block %d\12\0"
.text
.set	L179,0x0
.data
.text
_block:.word	L179
jbc	$2,_tracer,L183
pushl	$4
calls	$1,_pflg
pushl	8(ap)
calls	$1,_BlockStat
pushl	r0
pushal	L184
calls	$2,_ptrace
L183:subl3	$_proctable,4(ap),r0
divl3	$128,r0,-(sp)
pushal	L185
calls	$2,_debug
movl	4(ap),r0
movl	8(ap),40(r0)
pushl	4(ap)
calls	$1,_FreeMe
pushl	_waitq
pushl	4(ap)
calls	$2,_EnterMe
cmpl	_proc,4(ap)
jneq	L186
calls	$0,_swtch
L186:ret
.align	1
.globl	_unblock
.data	1
L191:.ascii	"unblock %d\12\0"
.text
.data	1
L193:.ascii	"unblock %s, on %s\0"
.text
.set	L187,0x0
.data
.text
_unblock:.word	L187
subl3	$_proctable,4(ap),r0
divl3	$128,r0,-(sp)
pushal	L191
calls	$2,_debug
jbc	$2,_tracer,L192
pushl	$4
calls	$1,_pflg
pushl	8(ap)
calls	$1,_BlockStat
pushl	r0
pushl	4(ap)
calls	$1,_Pinfo
pushl	r0
pushal	L193
calls	$3,_ptrace
L192:movl	4(ap),r0
cmpl	40(r0),8(ap)
jneq	L194
pushl	r0
calls	$1,_timewrite
pushl	4(ap)
calls	$1,_FreeMe
pushl	4(ap)
calls	$1,_setrun
L194:ret
.align	1
.globl	_EnterMe
.data
.align	2
L207:.double	0d2.56000000000000000000e+02
.text
.set	L195,0xe00
.data
.text
_EnterMe:.word	L195
subl2	$8,sp
movl	8(ap),r10
jbr	L201
L2000006:movl	44(r10),r0
movl	4(ap),r1
cmpl	24(r0),24(r1)
jgeq	L200
movl	44(r10),r10
L201:tstl	44(r10)
jneq	L2000006
L200:movl	r10,r9
movl	$2,r11
jbr	L204
L2000008:movl	44(r10),r0
movl	4(ap),r1
cmpl	24(r0),24(r1)
jneq	L203
calls	$0,_random
movzbl	r0,r0
cvtld	r0,-8(fp)
cvtld	r11,r0
divd3	r0,L207,r2
cmpd	-8(fp),r2
jgeq	L202
movl	44(r10),r9
L202:movl	44(r10),r10
incl	r11
L204:tstl	44(r10)
jneq	L2000008
L203:movl	4(ap),r0
movl	44(r9),44(r0)
movl	4(ap),r0
movl	r9,48(r0)
tstl	44(r9)
jeql	L208
movl	44(r9),r0
movl	4(ap),48(r0)
L208:movl	4(ap),44(r9)
ret
.align	1
.globl	_PriEnterMe
.set	L209,0x800
.data
.text
_PriEnterMe:.word	L209
movl	8(ap),r11
jbr	L215
L2000010:movl	44(r11),r0
movl	4(ap),r1
cmpl	24(r0),24(r1)
jgtr	L214
movl	44(r11),r11
L215:tstl	44(r11)
jneq	L2000010
L214:movl	4(ap),r0
movl	44(r11),44(r0)
movl	4(ap),r0
movl	r11,48(r0)
tstl	44(r11)
jeql	L216
movl	44(r11),r0
movl	4(ap),48(r0)
L216:movl	4(ap),44(r11)
ret
.align	1
.globl	_FreeMe
.set	L217,0x800
.data
.text
_FreeMe:.word	L217
movl	4(ap),r0
movl	44(r0),r11
tstl	48(r0)
jeql	L221
movl	48(r0),r0
movl	r11,44(r0)
L221:tstl	r11
jeql	L222
movl	4(ap),r0
movl	48(r0),48(r11)
L222:ret
.align	1
.globl	_Deadlock
.data	1
L228:.ascii	"deadlock\12\0"
.text
.data	1
L230:.ascii	"process terminated successfully\12\0"
.text
.set	L223,0x0
.data
.text
_Deadlock:.word	L223
movl	_waitq,r0
tstl	44(r0)
jeql	L227
pushal	L228
calls	$1,_panic
L227:pushal	L230
calls	$1,_printf
pushl	$0
calls	$1,_exit
ret
.align	1
.globl	_timesync
.data	1
L236:.ascii	"[%d] time %d\12\0"
.text
.set	L232,0x0
.data
.text
_timesync:.word	L232
movl	4(ap),r0
movl	r0,r1
addl3	112(r1),116(r0),r0
movl	-4(r0),24(r1)
movl	4(ap),r0
pushl	24(r0)
subl3	$_proctable,_proc,r0
divl3	$128,r0,-(sp)
pushal	L236
calls	$3,_debug
ret
.align	1
.globl	_timewrite
.set	L237,0x0
.data
.text
_timewrite:.word	L237
movl	4(ap),r0
movl	r0,r1
movl	r1,r2
addl3	112(r2),116(r1),r1
movl	24(r0),-4(r1)
ret

SHAR_EOF
fi # end of overwriting check
if test -f 'sysio.c'
then
	echo shar: will not over-write existing file "'sysio.c'"
else
cat << \SHAR_EOF > 'sysio.c'
static	char	*rcsid = "$Header: sysio.c,v 3.3 86/11/03 12:35:14 gil Exp $";
#include <stdio.h>
#include "conf.h"
#include "process.h"
#include "chan.h"
#include <sys/uio.h>
#include <sys/ioctl.h>
#include <sys/file.h>

chtime(chid) {

	Channel	*ch;

	ch = chanof(chid);
	ch->ch_flags = CH_TIME;
	time_ch = chid;
}

tread(ch, time)
	Channel	*ch;
	int	time;
{
	register IoVec	*iov;
	IoBlock		*blk;

	blk = ch->ch_read.b_next;

	for (iov = blk->b_data;
	     iov < &blk->b_data[blk->b_ndata];
	     iov++) {
		if (iov->io_len != sizeof(blk->b_proc->p_time))
			debug("time request is longword length\n");
		*(int *)iov->io_data = time;
		iov++;
	}
	ReadDone(ch, time);
	return 1;
}

#ifdef	S_SYS
/* allocate special time channel */
chassign(chid, fd, mode)
{
	Channel	*ch;
	
	ch = chanof(chid);
	ch->ch_flags = CH_SYS;
	ch->ch_fd = fd;
	if(isatty(fd))
		ch->ch_flags := CH_DEV;
}

SysWrite(ch, time)
	Channel	*ch;
{
	IoBlock		*wblk;
	IoVec		*vv;
	int		l;
	register 	i = 0, m;
	int		len;

	wblk = ch->ch_write.b_next;
	vv = wblk->b_data;
	len = wblk->b_ndata;
	
	for(i = 0; i < len; i++, vv++) {
		m = vv->io_len;
		vv->io_len = (int) vv->io_data;
		vv->io_data = (char *) m;
	}
	if(writev(ch->ch_fd, wblk->b_data, len) < 0)
		perror("writev");
	NTRACE(TRACE_IO,
	       ("[%d] write %d blocks, from %s (UNIX fd=%d)", chidof(ch),
	        len, Pinfo(wblk->b_proc), ch->ch_fd));

	WriteDone(ch, time);
}

SysRead(ch, time)
	Channel	*ch;
{
	IoBlock		*rblk;
	IoVec		*vv;
	int		l;
	register 	i = 0, m;
	int		len;

	rblk = ch->ch_read.b_next;
	vv = rblk->b_data;
	len = rblk->b_ndata;
	
	if(IsSpecialDevice(ch)) {
		l = 0;
		
		while(vv->io_len > 0 && l <= 0) {
			ioctl(ch->ch_fd, FIONREAD, &l);
			if(l <= 0)
				swtch();
			while(l > 0) {
				m = min(l, vv->io_len);
				read(ch->ch_fd, vv->io_data, m);
				vv->io_data += m;
				vv->io_len -= m;
				l -= m;
				if(vv->io_len == 0)
					if(++i == len)
						break;
					else
						vv++;
			}
		}
		return;
	}

	for(i = 0; i < len; i++, vv++) {
		m = vv->io_len;
		vv->io_len = (int) vv->io_data;
		vv->io_data = (char *) m;
	}
	if(readv(ch->ch_fd, rblk->b_data, len) < 0)
		perror("readv");
	NTRACE(TRACE_IO,
	       ("[%d] read %d blocks, to %s (UNIX fd=%d)", chidof(ch),
	        len, Pinfo(rblk->b_proc), ch->ch_fd));

	ReadDone(ch, time);
}

SpecialSelect() {
	debug("Not implemented yet");
	return 0;
}

#endif S_SYS
SHAR_EOF
fi # end of overwriting check
cd ..
#	End of shell archive
exit 0

----------end of sim.shar----------

-- 
-
-	Terry Torkelson				Internet: ttork%ewu@uunet.uu.net
-	Eastern Washington University		uucp: 	  uunet!isc-br!ewu!ttork
-						tellynet: 509-359-6016
Technical Details
Message-ID: <1338@ewu.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rutgers!apple!olivea!oliveb!isc-br!ewu!ttork

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rutgers!apple!olivea!oliveb!isc-br!ewu!ttork
From: ttork@ewu.UUCP (Terry Torkelson)
Newsgroups: comp.sys.transputer
Subject: Unix Occam Compiler
Keywords: Occam
Message-ID: <1338@ewu.UUCP>
Date: 14 Nov 90 19:39:46 GMT
Distribution: usa
Organization: Eastern Washington Univ. Cheney WA
Lines: 3113