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