🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.sys.transputer
1 messages
1 total messages Started by Terry Torkelson Wed, 14 Nov 1990 19:39
Unix Occam Compiler
#1101
Author: 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
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads