//processb.bc - Lampson&Metcalfe Process Primitives - BCPL // get "PROCSYMS" // PROCSYMS - Symbols for process handling in BCPL //Define process control block structure (PCB) structure PCB: [ //Dummy frame at base of process's stack DummyF word 2 //Dummy frame at top of process's stack //Interrupts come here directly for context switch Save3 word //Instruction to save ac 3 below JSRProcessSave word //Go to shared context switch code //State of process if not running Saved0 word //Machine context Saved1 word Saved2 word Saved3 word SavedCarry word SavedPC word SavedStackMinimum word //Saved stack minimum SavedInterruptsActive word //PCB pointer for process interrupted by ours PreviousPCBPointer word Previous3 word //Used during context switch Previous2 word //Address of shared context switching code AdrProcessSave word //Points to shared context switch code StackLow word //Will contain lowest stack pointer yet ProcessNumber word State word //0 running, 1 suspended, 2 blocked PCBPointer word LinkPointer word //For stringing PCB's ] manifest PCBSize=((size PCB)+15)/16 manifest StackMinimum=#335 manifest msb=#100000 //Define BCPL frame structure for following manipulations structure Frame: [ CallersF word SavedReturn word Temp word ExtraArgs word Formals word ] //Queue stuff structure Queue: [ Head word //Pointer to first item Tail word //Pointer to last item ] //Scheduler stuff structure Schedule: [ LinkPointer word //For SchedQueue Predicate word //Called with S, boolean returned Action word //If predicate true, called with S Arg1 word //Arguments to Predicate and Action Arg2 word Arg3 word ] // Outgoing externals external [ BeginProcessInit; BCPLStackHandler ] // Incoming externals external [ GetStackPointer BMOVE SWAT ] // Incoming statics external [ PCBTemplate ProcessSave ] //Create process context and return running in it let BeginProcessInit(ProcNum,Stack,Size)=valof [ //Compute and check space provided is enough for now let MyF=GetStackPointer() let CallersF=MyF>>Frame.CallersF let CallersFSize=(CallersF>>Frame.CallersF)-CallersF if (Size ls (CallersFSize+PCBSize)) then SWAT("PCB and starting frame no fit") //Move process control block template into space let NewPCB=Stack+Size-PCBSize //Process Control Block BMOVE(PCBTemplate,NewPCB,PCBSize-1) //Copy frame of caller for initial process context let ProcessF=NewPCB-CallersFSize //A copy BMOVE(CallersF,ProcessF,CallersFSize-1) //Link copied frame to dummy in new PCB let PCBF=lv (NewPCB>>PCB.DummyF) //Frame in PCB ProcessF>>Frame.CallersF=PCBF PCBF>>Frame.CallersF=CallersF //For EndProcessInit PCBF>>Frame.SavedReturn=SWAT-1 //SWAT if process returns //Finish setting up new PCB NewPCB>>PCB.PCBPointer=NewPCB //For CurrentPCB NewPCB>>PCB.SavedStackMinimum=Stack NewPCB>>PCB.Saved2=ProcessF //Context is copied frame NewPCB>>PCB.AdrProcessSave=ProcessSave NewPCB>>PCB.ProcessNumber=ProcNum NewPCB>>PCB.SavedInterruptsActive=(1 lshift ProcNum)-1 NewPCB>>PCB.StackLow=-1 //Mark unrecorded NewPCB>>PCB.State=2 //Mark process blocked NewPCB>>PCB.PreviousPCBPointer=0 //No previous (yet) if PCBTemplate>>PCB.ProcessNumber eq 0 then [ PCBTemplate>>PCB.PCBPointer=PCBTemplate //For CurrentPCB PCBTemplate>>PCB.ProcessNumber=-1 PCBTemplate>>PCB.StackLow=-1 //Mark unrecorded PCBTemplate>>PCB.State=0 //Mark process running PCBTemplate>>PCB.PreviousPCBPointer=0 //None PCBTemplate>>PCB.AdrProcessSave=SWAT-1 //Never blocks ] //Switch to process's context for initalization MyF>>Frame.CallersF=ProcessF //Process's context NewPCB>>PCB.SavedStackMinimum=@StackMinimum @StackMinimum=Stack //So init can call things resultis lv (NewPCB>>PCB.Save3) //Int vec ] and BCPLStackHandler() be [ manifest [ AdrGetFrame=#370] manifest [ CallSWAT=#77400] @((@AdrGetFrame)+30)=CallSWAT ]