; Contextml.asm ; L. Stewart, December 8, 1982 4:13 PM ; modified to maintain _stackLimit, L. Stewart, October 5, 1982 12:51 PM ; directly manipulated wakeup disable counter ; November 8, 1982 3:06 PM, use osstatics.c ; November 10, 1982 3:49 PM, add max runtime stuff ; December 8, 1982 4:13 PM, remove blken ; February 23, 1983 3:10 PM, remove osstatics ; March 3, 1983 2:42 PM, access to statics $INCLUDE(Lark.d) C_CODE SEGMENT CTXNext EQU 0 ; link field CTXsp EQU 2 ; saved stack pointer CTXBase EQU 4 ; stack limit CTXpc EQU 6 ; initial PC CTXnm EQU 8 ; string name of context CTXmr EQU 10 ; maxrun CTXcl EQU 12 ; caller who ran maxrun lenCTX EQU 30 ; bytes, leave space for RPC and system C_DATA SEGMENT EXTRN _stackLimit:WORD EXTRN _wdc:WORD ; following statics must stay in order for GetCtxData to work _CtxRunning DW 0 _ctxCal DW 0 _startT DW 0 dummyC DW 0 DW ? dummySL DW ? DW ? dummynm DW ? DW ? DW ? C_DATA ENDS ASSUME CS:C_CODE, DS:C_DATA, ES:C_DATA EXTRN _Zero:NEAR EXTRN _CallDebugger:NEAR _CurrentContext PROC NEAR MOV BX,_CtxRunning RET _CurrentContext ENDP _InitCtxPkg PROC NEAR MOV _ctxCal,0 MOV DI,OFFSET dummyC CLD MOV _CtxRunning, DI XOR AX,AX STOSW STOSW MOV AX,_stackLimit STOSW XOR AX,AX STOSW MOV AX,"noContext" STOSW RET _InitCtxPkg ENDP ; struct ctx *InitNContext(name, region, length, proc) ; char *name; /* string */ ; char *region; /* base of available space */ ; int length; /* length in words of available space */ ; int proc(); /* proc to call on first invocation */ ; returns ; struct RPCCtx * see context.h _InitNContext PROC NEAR PUSH BP MOV BP,SP MOV AX,[4+BP] ; region PUSH AX CALL _InitContext POP AX ; dump arguement MOV AX,[6+BP] ; fetch name MOV [CTXnm+BX],AX ; put into context MOV SP,BP POP BP RET _InitNContext ENDP ; struct ctx *InitContext(region, length, proc) ; char *region; /* base of available space */ ; int length; /* length in words of available space */ ; int proc(); /* proc to call on first invocation */ ; returns ; struct RPCCtx * see context.h ; InitContext puts the context structure at the top of the region ; because the stack grows downwards. The initial value of the ; frame pointer will be 0 when proc is called. This is a clue to ; stack tracers that it is the first frame. _InitContext PROC NEAR PUSH BP MOV BP,SP ; zero it PUSH CX PUSH BX MOV BX,CX ; length MOV CX,[4+BP] ; region CALL _Zero POP BX POP CX ; continue MOV SI,[4+BP] ; region MOV DI,SI ; copy it ADD DI,CX ; add length *2 ADD DI,CX SUB DI,lenCTX ; construct pointer to base of ctx MOV WORD PTR [CTXNext+DI], 0 MOV [CTXBase+DI],SI ; set stackbase MOV WORD PTR [CTXnm+DI], 0 ; name MOV [CTXpc+DI],BX ; proc LEA BX,[DI-2] ; addr of first frame word on stack MOV [CTXsp+DI],BX ; set initial sp to just below ctx MOV WORD PTR [BX],0 ; initial frame pointer MOV BX,DI ; return context MOV SP,BP POP BP RET _InitContext ENDP ; CallContext(c) ; struct ctx *c; _CallContext LABEL NEAR PUSH BP PUSH _stackLimit ; save stackLimit PUSH _ctxCal ; save previous ctxCal PUSH _CtxRunning ; save running context MOV _ctxCal,SP ; save this ctxCal JMP nxtCtx ; jump into Block code _Block LABEL NEAR MOV BX,_CtxRunning ; pick up current context PUSH BP ; save frame pointer MOV [CTXsp+BX],SP ; save stack pointer ; measure runtime MOV SI,clklo MOV AX,[SI] ; get new time SUB AX,_startT ; subtract start time CMP AX,[CTXmr+BX] ; new record? JNA blkb MOV [CTXmr+BX],AX MOV SI,SP MOV AX,[2+SI] MOV [CTXcl+BX],AX blkb: MOV BX,[CTXNext+BX] ; next context to try ; here to resume next context on list nxtCtx: OR BX,BX ; check for end of list ; or 0 arg to CallContext JZ donCtx ; none left MOV _CtxRunning,BX ; save new context runCtx: MOV BX,clklo MOV AX,[BX] MOV _startT,AX CMP _wdc,0 JNZ _BADBLK CLI ; fast IWDC MOV BX,_CtxRunning MOV SP,[CTXsp+BX] ; load saved stack pointer MOV AX,[CTXBase+BX] ; load saved stack limit ADD AX,018H ; 24 byte cushion MOV _stackLimit,AX ; checked by StkChk CMP _wdc,0 ; fast DWDC JNZ iwasoff STI iwasoff: POP BP ; load saved frame pointer OR BP,BP ; if frame==0, call proc JZ firstRun RET ; return from Block in new process firstRun: MOV AX,[CTXpc+BX] CALL AX ; call procedure with ctx as arg JMP _Block ; if it returns, call again _BADBLK: ; musn't block with ints disabled MOV BX,08765H CALL _CallDebugger donCtx: MOV AX,_ctxCal ; restore stack of ctxCal OR AX,AX JZ notCtx ; Block called from outside MOV SP,AX POP _CtxRunning POP _ctxCal POP _stackLimit POP BP RET ; return from CallContext ; If Block is called from outside any CallContext, it just returns notCtx: MOV BX,_CtxRunning JMP runCtx _GetCtxData PROC NEAR MOV BX,OFFSET _CtxRunning RET _GetCtxData ENDP PUBLIC _CtxRunning PUBLIC _ctxCal PUBLIC _InitCtxPkg PUBLIC _Block PUBLIC _CurrentContext PUBLIC _InitNContext ; PUBLIC _InitContext PUBLIC _CallContext PUBLIC _GetCtxData C_CODE ENDS END