;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;›;›; FORK.ACT - Foreground/background›; multi-tasking for ACTION!›;›;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;››; by Mark Rose›; this version: 4/25/85››; Usage: Call the ACTION! procedure›; Fork with the address of the›; background routine you want to›; run as the parameter. The Switch›; procedure will be invoked as a›; vertical blank interrupt routine›; to schedule between the two›; processes. By default, each›; routine will get 10 jiffies of›; time before swapping will occur.›; If you want to change these times,›; set the appropriate value in the›; TimeSlice array.››; Restrictions: Both processes can›; NOT perform I/O at the same time›; since operating system device›; handlers are not reentrant. Also,›; neither process can monopolize›; too much stack space, or one›; process will crash. The latter›; should not be a problem since›; ACTION! is non-recursive. Also,›; the fore- and background routines›; CANNOT call common ACTION! sub-›; routines, except the cartridge›; library. The reason is that any›; parameters to ACTION! PROCs and›; FUNCs are not saved by the Switch›; routine, so the subroutine may›; get confused.››››;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;›;›; Global variables and definitions:›;›;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;››DEFINE MainPid = "0", ; Process ID of foreground routine.› ForkPid = "1" ; " " " background routine.››BYTE CurPid, ; ID of currently executing routine.› Done, ; Flag to indicate background is finished.› Timer, ; Jiffy timer for context switch.› SaveSP ; Temp to hold stack pointer of sleeping process.››; Definitions of temps to save and›; storage for them.››BYTE ARRAY Temps(16) = $A0,› Ptrs(16) = $80,› MathTemps(16) = $C0,› SaveTemps( 16 ),› SavePtrs( 16 ),› SaveMath( 16 )››; Number of jiffies in each time slice›; for foreground and background processes.››BYTE ARRAY TimeSlice(2)=› [ 10 10 ]››; Deferred VBI vector and temp to›; save old value.››CARD VBIVec = $224,› OldVBI››; Critical I/O flag (non-zero = critical)››BYTE Critic=$42››››;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;›;›; Switch - Decrement jiffy timer and›; switch contexts to alternate›; process, if time slice is over.›; If contexts are switched, swap›; the contents of the 3 temporary›; areas for ACTION! with the saved›; values for the other process.›;›;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;››PROC Switch()› [› ; Do we need to change context?› $CE Timer ; dec Timer› $F0 3 ; beq *+3› $6C OldVBI ; jmp (OldVBI)›› ; Yes, change context by swapping› ; stack pointers and temps.› $BA ; tsx› $8A ; txa› $AE SaveSP ; ldx SaveSP› $9A ; txs› $8D SaveSP ; sta SaveSP›› $A2 15 ; ldx #15›› $B5 Temps ;l1: lda Temps,x› $A8 ; tay› $BD SaveTemps ; lda SaveTemps,x› $95 Temps ; sta Temps,x› $98 ; tya› $9D SaveTemps ; sta SaveTemps,x›› $B5 Ptrs ; lda Ptrs,x› $A8 ; tay› $BD SavePtrs ; lda SavePtrs,x› $95 Ptrs ; sta Ptrs,x› $98 ; tya› $9D SavePtrs ; sta SavePtrs,x›› $B5 MathTemps ; lda MathTemps,x› $A8 ; tay› $BD SaveMath ; lda SaveMath,x› $95 MathTemps ; sta MathTemps,x› $98 ; tya› $9D SaveMath ; sta SaveMath,x›› $CA ; dex› $10 $D9 ; bpl l1›› ; If running process was background› ; routine, and Done flag was set,› ; then stop this VBI routine, thus› ; giving foreground full CPU again.› $AC CurPid ; ldy CurPid› $F0 $11 ; beq l2› $AD Done ; lda Done› $F0 $0C ; beq l2› $AD OldVBI ; lda OldVBI› $8D VBIVec ; sta VBIVec› $AD OldVBI+1 ; lda OldVBI+1› $8D VBIVec+1 ; sta VBIVec+1›› $98 ;l2 tya› $49 1 ; eor #1› $8D CurPid ; sta CurPid›› ; Set next time slice› $A8 ; tay› $B9 TimeSlice ; lda TimeSlice,y› $8D Timer ; sta Timer›› $6C OldVBI ; jmp (OldVBI)› ]››››;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;›;›; StartFork - Begin execution of the›; background process. Set the Done›; flag when that routine returns.›;›;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;››PROC ForkVec()››PROC StartFork()› ForkVec()› Done = 1› Timer = 1›DO OD››››;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;›;›; Fork - Invoke a background process.›; The parameter is the name of the›; ACTION! routine which is to be›; executed in the background.›; Remember, the foreground and›; background processes cannot›; perform I/O at the same time.›;›;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;››PROC Fork( CARD address )› CARD temp› BYTE status, i,› addrLow = temp,› addrHi = temp+1› BYTE ARRAY sysStack(0)=$100›› ; Get current stack level and status.› [› $BA ; tsx› $8E SaveSP ; stx SaveSP› $08 ; php› $68 ; pla› $8D status ; sta status› ]›› temp = StartFork› ForkVec = address›› ; Leave 100 bytes free for main process› SaveSP ==- 100›› ; and push background process address› ; (StartFork) on stack with current› ; status value.› sysStack(SaveSP+5) = addrLow› sysStack(SaveSP+6) = addrHi› sysStack(SaveSP+4) = status›› ; Get current values of temps as› ; initial values for background› ; process.› FOR i = 0 TO 15› DO› SaveTemps(i) = Temps(i)› SavePtrs(i) = Ptrs(i)› SaveMath(i) = MathTemps(i)› OD›› ; Set initial context and time-slice› ; (foreground), and set background› ; status to NOT COMPLETED.›› CurPid = MainPid› Timer = TimeSlice(0)› Done = 0›› ; Now set up scheduler as VBI routine.› Critic = 1› OldVBI = VBIVec› VBIVec = Switch› Critic = 0›RETURN››MODULE›