; ContextSched.asm -- Simple time-slicing scheduler for contexts ; Copyright Xerox Corporation 1979 .ent SchedInterrupt .ent SchedYield .ent SchedFinish .ent schedSavedUFP .ent schedMask .bext Block .bext CtxSwitch .bext lvUserFinishProc .srel SchedInterrupt: .SchedInterrupt SchedYield: .SchedYield SchedFinish: .SchedFinish schedSavedUFP: 0 schedMask: 0 .nrel ; Yield() ; Same as Block() except that if the current context has not yet ; run for a full time slice (17 ms), Yield returns immediately ; at a cost of only 3 instructions. ; This procedure is plugged into the Yield procedure's static ; by InitContextSched. .SchedYield: lda 0 @lvCtxSwitch ; Time slice expired? sz 0 0 jmp 1 3 ; No, continue this context lda 0 @lvBlock ; Yes, run other contexts sta 0 1 2 jmp @1 2 ; Interrupt routine executed every 17 ms to update the CtxSwitch ; flag. The flag is handled in the following way: ; When contexts are actually switched (by Block or Yield), ; the Context package sets CtxSwitch to some value other than ; 0 or -1. At the next 17 ms interrupt, CtxSwitch is set to -1 ; as an indication that a time slice has begun. If CtxSwitch ; is still -1 at the next 17 ms interrupt, then we know the ; current context has run for between 17 and 34 ms, so it is ; time to switch to another context. This is signalled by setting ; CtxSwitch to 0, which tells Yield to do a Block next time it ; is called rather than returning immediately. .SchedInterrupt: sta 0 save0 lda 0 @lvCtxSwitch ; Get context switch flag mov# 0 0 snr ; Switch already requested? jmp .+4 ; Yes, done com 0 0 szr ; Any switch in last slice? adc 0 0 ; Yes, request switch after next sta 0 @lvCtxSwitch ; Update the flag lda 0 save0 bri lvCtxSwitch: CtxSwitch lvBlock: Block save0: 0 ; User finish procedure -- turns off scheduler interrupt .SchedFinish: sta 3 1 2 lda 0 @lvSchedMask com 0 0 lda 1 @lvDisplayInterrupt and 0 1 sta 1 @lvDisplayInterrupt lda 1 @lvActive and 0 1 sta 1 @lvActive lda 0 @lvSchedSavedUFP lda 3 @lvLvUserFinishProc sta 0 0 3 lda 3 1 2 jmp 1 3 lvSchedMask: schedMask lvDisplayInterrupt: 421 lvActive: 453 lvSchedSavedUFP: schedSavedUFP lvLvUserFinishProc: lvUserFinishProc .end