Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!apple!olivea!oliveb!isc-br!ewu!ttork From: ttork@ewu.UUCP (Terry Torkelson) Newsgroups: comp.sys.transputer Subject: Unix Occam Compiler Keywords: Occam Message-ID: <1338@ewu.UUCP> Date: 14 Nov 90 19:39:46 GMT Distribution: usa Organization: Eastern Washington Univ. Cheney WA Lines: 3113 ----------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 #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 #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 #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 #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 #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 #include "conf.h" #include "process.h" #include "chan.h" #include #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 #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 #include #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 #include #include #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 #include "conf.h" #include "process.h" #include "chan.h" #include #include #include 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