title PASPSI ;This here is a set of routines for using the PSI system in PASCAL. ;Each condition established is assigned an "index". Internally this ;is the index into various tables. As far as the user is concerned it ;is simply a small non-negative integer. The user is assumed to have ;read the writeup on PSI in the monitor calls manual. ;WARNING: The interrupt handler is not reentrant. This means that we ;are in big trouble if the user does a PSIADD specifying that interrupts ;remain enabled when at interrupt level. If you want to make it ;reentrant, consider: ; use some AC other than 17 in the dispatch process, so the stack is ; always valid ; see if the code around INTMOD is reentrant ; figure out a way to make the critical section stuff support multiple ; levels of interrupts. Probably they would have to be stacked. ; change code so no variables in low seg are used. Do everything on ; the stack ;edit history ;2 - make LH of saved procedure addr be zero, since use it for indirection ; From J Hammer at CSL len==20 ;assembly parameter: maximum no. of conditions active ;(i.e. all values of index must be less than len) search uuosym a=1 b=2 ;first argument c=3 d=4 e=5 f=6 p=17 entry psiadd,psirem,psiini,psion,psioff,psiclr %i=0 vector: ;This is the main vector for the psi system repeat len,< disp+2*%i ;new PC - entry point for interrupt 0 ;old PC 1b2 ;indicates no more interrupts until debreak 0 ;status %i=%i+1 > dispt: block len ;pascal routine to call on interrupt disp: ;This is the place where interrupt handling begins repeat len,< movem 17,apracs+17 jsp 17,intmod > pisys: block 3*len ;this contains argument blocks for PISYS. apracs: block 20 ;place to store ac's index: block 1 ;place to store index on entry resume: block 1 ;stores addr of appropriate OLD PC word in vector when ;resuming a critical section intmod: ;This is the main interrupt processor and dispatcher movem 17,index ;tells us which place we came from (index*2) skipge in.crt## ;in critical section? jrst docrit ;yes - resume it movei 17,apracs blt 17,apracs+16 move 17,apracs+17 ;we need to use the pdl pointer! hrrz b,index ;this is pointer into disp. subi b,disp+2 ;this gives index into disp lsh b,-1 ;divide by 2 arg1 = "index" move f,b ;f will be index*4, pointer into vector imuli f,4 move c,vector+.psvop(f) ;arg2 = "old PC" hrrz d,vector+.psvfl(f) ;arg3 = "reason" move e,vector+.psvis(f) ;arg4 = "status" ;The following assumes that we can start our stack above the ;main program's. This will work unless we have interrupted a ;call of a procedure with more than 5 words of parameters. In ;that case stuff is put above the top of stack pointer. ;I don't have a general solution, but for any given program ;you can easily find out the maximum offset it uses above the ;stack and use that in the following line instead of the 200. ;200 should be enough except if big arrays are being passed by ;value. hrri p,200(p) ;give us some space, just for luck caig 15,40(p) jsp 1,corerr## ;get more core if needed movei f,tty## ;save state of TTY system push p,2(f) push p,36(f) push p,37(f) push p,43(f) movei f,ttyout## push p,43(f) push p,1(p) ;routine will garbage p-1 pushj p,@dispt(b) ;go to SAIL routine. note it can look at a,b,c pop p,0(p) movei e,ttyout## pop p,43(e) movei e,tty## pop p,43(e) pop p,37(e) pop p,36(e) pop p,2(e) movem 15,apracs+15 ;use new value of 15 if it changed hrlzi 17,apracs ;now restore the world blt 17,17 debrk. ;will return to interrupted thing halt . halt . ;index = psiadd(type,reasonbits,proc,control) ; Adds a condition. Does not turn on PSI system. Also makes like INTMAP. ; type - code for type of interrupt ; reasonbits - condition for I/O interrupts, 0 otherwise ; proc - procedure to call for immediate interrupt ; control - for setting LH of word 3 of vector ; Returns index, or -1 if table full psiadd: setz a, ;a will be index ;compute index for new entry psia1: skipn dispt(a) ;is this entry in use? jrst psia2 ;no - use it caige a,len-1 ;yes - last one checked? aoja a,psia2 ;no - try again setom 1(p) ;table full - return -1 popj p, ;set up what will happen at interrupt psia2: hrrzm 4,dispt(a);[2] dispatch addr ;set up block at vector move d,a ;d = a*4, offset into vector lsh d,2 hrlz 5,5 ;flag bits go in lh movem 5,vector+.psvfl(d) ;set up block for pisys. move e,a ;e = a*3, offset into pisys imuli e,3 hrl c,d ;vector offset in LH - reason in RH movem c,pisys+1(e) movem 2,pisys(e);type setzm pisys+2(e);must be zero ;do the pisys movsi b,(ps.fac) hrri b,pisys(e) pisys. b, halt . movem a,1(p) ;return index popj p, ;psirem(index) ; removes a condition set up by psiadd, and clears table entries ; index - return from psimap psirem: move a,b ;save index imuli b,3 ;index into pisys movei b,pisys(b) hrli b,(ps.frc) ;turn off condition pisys. b, halt . setzm dispt(a) ;release the entry popj p, ;psiclr(index) ; clears all pending interrupts for one condition ; index - return from psiadd for the condition psiclr: imuli b,3 ;index into pisys movei b,pisys(b) hrli b,(ps.fcs) ;clebr bll interrupts pisys. b, halt . popj p, ;psiini ; Must be done before any psion or psioff. Mainly does PIINI. ; no arguments psiini: movei a,vector piini. a, halt . setzm dispt ;clear old interrupts move a,[dispt,,dispt+1] blt a,dispt+len-1 popj p, ;psion ; Turns on PSI system ;psioff ; Turns off PSI system psion: skipa a,[ps.fon] psioff: movsi a,(ps.fof) pisys. a, halt . popj p, subttl Critical section code entry enterc,leavec ;Here from INTMOD when interrupted in critical section - go back to user docrit: hrrz 17,17 ;get addr only of place in dispt subi 17,disp+2 ;compute index in vector lsh 17,1 ;now have index * 4 movei 17,vector+.psvop(17) ;now get addr of OLD PC word tlo 17,(Z @) ;make it indirect movem 17,resume ;and save it for resuming code sos in.crt ;make incrit be -2 move 17,apracs+17 ;now return to user jrstf @resume ;Here from LEAVEC when leaving an critical section that was resumed by ;DOCRIT. Go back and handle the interrupt conint: hrrzs resume ;clear indirect bit in RESUME pop p,@resume ;put return PC into OLD PC word setzm in.crt ;no longer in critical section movem 17,apracs+17 ;now simulate interrupt dispatch move 17,index jrst intmod ;ENTERC - called by user to enter critical section enterc: setom in.crt ;say in critical section popj p, ;LEAVEC - called by user at end of critical section, to resume interrupts leavec: aosge in.crt ;clear flag unless an interrupt happened pushj p,conint ;interrupt happened, continue it popj p, end