;processa.sr - Lampson&Metcalfe Process Primitives - ALTOASM ;**some of this was cut out by Factory because dup in BFSML.A ;External links .bext GetStackPointer,PCBTemplate,ProcessSave .bext Block,DisableInterrupts,EnableInterrupts .bext EndProcessInit,CurrentPCB,WakeUpBits .bext GetProcessNumber,Noop,TruePredicate,FalsePredicate .bext CLoad .srel GetStackPointer: .GetStackPointer PCBTemplate: .PCBTemplate ProcessSave: .ProcessSave Block: .Block WakeUpBits: .WakeUpBits CLoad: .CLoad ;Just to find it, no use yet EndProcessInit: .EndProcessInit GetProcessNumber: .GetProcessNumber Noop: .Noop TruePredicate: .TruePredicate FalsePredicate: .FalsePredicate CurrentPCB: .PCBTemplate ;Template is PCB for main .nrel callswat=77400 ;Trap to SWAT ;Template for process control block ;Must be consistent with definitions in PROCESS.BC ;Used to store state of "main process" .PCBTemplate: PCB: ;Dummy frame at base of process's stack DummyF: 0 ;pointer to self, by EndProcessInit 0 ;To be filled in with SWAT-1 ;Interrupts come here directly for context switch Save3: sta 3 Previous3 JSRProcessSave: jsr@ AdrProcessSave ;State of machine at time of (last) interrupt Base: Saved0: 0 Saved1: 0 Saved2: 0 Saved3: 0 SavedCarry: 0 SavedPC: 0 SavedStackMinimum: 0 SavedInterruptsActive: 0 PreviousPCBPointer: 0 ;PCB of interrupted process Previous3: 0 ;Used during context switch only Previous2: 0 AdrProcessSave: 0 ;Address of shared context-switching code StackLow: 0 ;Lowest value reached by stack (unused) ProcessNumber: 0 ;0-14 are interrupt processes State: 0 ;0 running, 1 suspended, 2 blocked PCBPointer: 0 ;Holds pointer to this PCB LinkPointer: 0 ;For stringing PCB's together .PCBTemplateEnd: PCBSize=.PCBTemplateEnd-.PCBTemplate ;ProcessSave - saved machine state in PCB off ac 3 InterruptPC: 500 ;PC stashed here at interrupt time InterruptsActive: 453 ;1 if interrupt can happen WakeUpsWaiting: 452 ;1 means interrupt pending StckMin=335 ;Address of word holding stack minimum AdrCurrentPCB: CurrentPCB ;Pointer to static .ProcessSave: ;Finish saving state of previously running process sta 2 Previous2-Base,3 ;Tuck his 2 for now lda 2 @AdrCurrentPCB ;Get his PCB mov 2 2 snr ;PCB must be non-zero callswat sta 2 PreviousPCBPointer-Base,3 ;Tell whom to resume sta 0 Saved0-PCB,2 ;Tuck his 0 in his PCB sta 1 Saved1-PCB,2 lda 0 Previous3-Base,3 ;Get back his 3 sta 0 Saved3-PCB,2 ;Put in his PCB lda 0 Previous2-Base,3 ;Get back his 2 sta 0 Saved2-PCB,2 movl 0 0 ;Carry sta 0 SavedCarry-PCB,2 ;His carry lda 0 @InterruptPC sta 0 SavedPC-PCB,2 ;His PC lda 0 StckMin ;Current stack minimum sta 0 SavedStackMinimum-PCB,2 lda 1 @InterruptsActive sta 1 SavedInterruptsActive-PCB,2 lda 0 State-PCB,2 ;Get his state, better be running mov 0 0 szr ;0 is running callswat subzl 0 0 ;make a 1 sta 0 State-PCB,2 ;mark suspended lda 0 PCBPointer-Base,3 ;PCB for new process ;Load context of process, PCB in ac0 ;Restriction of interrupts in ac1 ;Interrupts off .CLoad: mov 0 3 snr ;Check and move to index callswat ;Swat if restoring with zero PCB lda 0 State-PCB,3 ;Get state of new process mov 0 0 snr ;better not be running callswat sub 0 0 ;make a 0 sta 0 State-PCB,3 ;mark running sta 3 @AdrCurrentPCB ;New guy now lda 0 SavedInterruptsActive-PCB,3 and 1 0 ;Allow only if already allowed sta 0 @InterruptsActive lda 0 SavedStackMinimum-PCB,3 sta 0 StckMin lda 0 SavedPC-PCB,3 sta 0 @InterruptPC lda 0 SavedCarry-PCB,3 movr 0 0 lda 0 Saved0-PCB,3 lda 1 Saved1-PCB,3 lda 2 Saved2-PCB,3 lda 3 Saved3-PCB,3 bri ;start us up with interrupts on now ;Block - Give processor up, done running .Block: ;Store state required to unBlock at next WAKEUP inc 3 1 ;Point at where to wakeup lda 3 @AdrCurrentPCB ;Find out who we are mov 3 3 snr ;Check callswat lda 0 PreviousPCBPointer-PCB,3 ;Whom to start dir ;Disable interrupts sta 1 SavedPC-PCB,3 ;Just save PC and AC2 sta 2 Saved2-PCB,3 adc 1 1 ;all interrupts previous ok now lda 2 Block2 ;This process now blocked sta 2 State-PCB,3 ;Mark us blocked jmp .CLoad Block2: 2 ;State of a blocked process ;GetStackPointer - Returns current stack pointer .GetStackPointer: mov 2 0 ;return as value jmp 1,3 ;return ;EndProcessInit - Leave process context after initialization ;One arg is initial code pointer for process .EndProcessInit: ;Get back to main context, fix up dummy to itself lda 2 0,2 ;Point at PCB dummy frame sta 0 SavedPC-PCB,2 ;stash intial PC in PCB lda 1 SavedStackMinimum-PCB,2 ;Saved by BeginProcessInit lda 0 StckMin sta 1 StckMin sta 0 SavedStackMinimum-PCB,2 ;Ready to run lda 0 0,2 ;Get initializers original frame sta 2 0,2 ;Dummy frame should really point to itself mov 0 2 ;Now running over original jmp 1,3 ;return ;WakeUpBits - Or bits into WakeUps waiting ;One arg is bit pattern to be ORed (usually only 1 on) .WakeUpBits: dir ;no interrupts just now lda 1 @WakeUpsWaiting com 0 0 ;inclusive or and 0 1 adc 0 1 sta 1 @WakeUpsWaiting eir ;interrupts ok now jmp 1,3 ;return ;GetProcessNumber - Returns process number ;-1 means no PCB so no process number ;If an arg, use as PCB instead of current .GetProcessNumber: sta 3 1,2 ;stash return pc lda 3 0,3 ;number of args mov 3 3 szr ;skip if none, if use current mov 0 3 skp ;assume 1 arg, PCB in ac0 lda 3 @AdrCurrentPCB mov 3 3 snr adc 0 0 skp ;no pcb, return -1 lda 0 ProcessNumber-PCB,3 lda 3 1,2 ;restore return pc jmp 1,3 ;Noop - Just returns, does nothing .Noop: jmp 1,3 ;TruePredicate - Just returns true .TruePredicate: adc 0 0 ;-1 jmp 1,3 ;return ;FalsePredicate - Just returns false .FalsePredicate: sub 0 0 ;0 jmp 1,3 ;return ; miscellaneous machine code ; frame callersFrame=0 savedPC=1 temp=2 extraArguments=3 ; machine code for messing with frames .srel Null: pNull .bext CoCall,CallFrame,GotoFrame,CoReturn,Null .nrel pNull: jmp 1,3 .srel prototypeStream: .prototypeStream .bext prototypeStream .nrel ; this must agree with the ST declaration .bext SYSERR .prototypeStream: 0 Null ; open Null ; close SYSERR ; gets SYSERR ; puts Null ; reset SYSERR ; putback SYSERR ; error FalsePredicate ; endof FalsePredicate ; stateof 0 0 0 0 0 .end