; Context.asm -- CONTEXT -- Assembly Code ; Copyright Xerox Corporation 1979 ; Last modified November 4, 1977 5:24 PM .ent CallContextList .ent Block .ent Yield .ent CtxCaller .ent CtxRunning .ent CtxSwitch ; Offsets into CTX structure: CTXNext=0 CTXStack=1 CTXStackMin=2 ; Bcpl runtime information StkMin=335 .srel CallContextList: .CallContextList Block: .Block Yield: .Block ; Yield same as Block initially CtxCaller: 0 CtxRunning: dummyCtx CtxSwitch: 0 ; Used by ContextSched .nrel ; CallContextList(ctx) ; Successively resumes each context on the list starting at ctx ; until it executes Block(). Returns after the last context on ; the list has blocked. .CallContextList: sta 3 1 2 ; Save return in normal spot lda 1 @lvCtxCaller ; Save CtxCaller in frame sta 1 2 2 lda 1 @lvCtxRunning ; Save CtxRunning in frame sta 1 3 2 lda 1 StkMin ; Save StkMin below frame (yes, this is safe!) sta 1 -1 2 sta 2 @lvCtxCaller ; Establish new CtxCaller frame jmp nxtCtx ; Go resume first context ; Here when the resumed context executes Block() .Block: inc 3 3 ; Generate real return address sta 3 1 2 ; Save in canonical spot block1: lda 3 @lvCtxRunning ; Get current context sta 2 CTXStack 3 ; Save our stack pointer lda 1 StkMin ; Save our StkMin sta 1 CTXStackMin 3 lda 0 CTXNext 3 ; Find next context to try ; Here to resume next context on list nxtCtx: mov 0 3 snr jmp donCtx ; No more on list to run sta 3 @lvCtxRunning ; Record context about to be run lda 1 CTXStackMin 3 sta 1 StkMin ; Stack bounds runCtx: sta 3 @lvCtxSwitch ; Note that contexts have switched lda 2 CTXStack 3 ; Get the stack to run it in jsr @1 2 ; And return from its Block(). 1 ; On first call, arg is context jmp block1 ; If he returns, call him again ; Here when no more contexts on list donCtx: lda 2 @lvCtxCaller ; Get stack for CallContextList snz 2 2 jmp notCtx ; Block called outside of context lda 0 -1 2 ; Restore previous StkMin sta 0 StkMin lda 0 3 2 ; Restore previous CtxRunning sta 0 @lvCtxRunning lda 0 2 2 ; Restore previous CtxCaller sta 0 @lvCtxCaller lda 3 1 2 jmp 1 3 ; Return from CallContextList ; What happens if Block() is called outside of any context notCtx: lda 3 @lvCtxRunning ; Just re-run the dummy context jmp runCtx lvCtxCaller: CtxCaller lvCtxRunning: CtxRunning lvCtxSwitch: CtxSwitch dummyCtx: 0 ; The dummy context has "next" of zero .blk 2 ; Clobbered by Stack and StackMin .end