.title PDPMEM memory managemanet for PDP-11 version of 'C' ted ; Edits: ; ; 16-JAN-1986 12:23 Brian Nelson ; ; (1) Raise region size to 18KW ; (2) Give window 1 4KW for index ; (3) Add MAPMAC() to map macro buffers to the region ; ; 02-Jul-86 17:02:33 Brian Nelson ; ; (1) Add second region for buffering work file if I/D task ; This is selected by GBLDEF=IDSPAC:1 ; (2) Reduce size of first region by 4KW if we use two regions. .psect winmap ,rw,d,lcl,rel,con .psect wincod ,ro,i,lcl,rel,con EXTEND = 0 .if eq ,EXTEND .ift .mcall rdbdf$ ,wdbdf$ .mcall atrg$s ,craw$s ,crrg$s ,map$s ,umap$s ,exit$s .mcall feat$s ,tfea$s .MACRO TFEA$S FEAT,ERR .MCALL MOV$,DIR$ MOV$ FEAT MOV (PC)+,-(SP) .BYTE 209.,2. DIR$ ,ERR .ENDM FE$FMP = 73 T4$FMP = 50 rdbdf$ wdbdf$ .psect winmap fmap: .word 0 ; If fast mapping is available mapcnt::.word 0 ; Stats highmap:.word 0 ; where in region are we mapped at? indcre: .byte 0,0,0,0 fmt: .asciz /MAP error %d/<12> craw: .asciz /%o %o/<12> .even ; KW, number of Kwords to allocate in region ; 4KW for workfile cacheing ; 8KW for window 0 index ; 4KW for window 1 index ; 2KW for macro buffers KW = 4 + <2*4> + 4 + 2 KWID = KW - 4 regdsc: .word 0 ; region id returned .word 40*KW ; 18 kw for now .word 0 ; noname for region .word 0 ; noname for region .word 0 ; same parition .word 0 ; same parition .word RS.RED!RS.WRT!RS.ATT ; attach + read + write .word ^C377 ; no world or group access windsc: .byte 0 ; return the window id .byte 5 ; apr 5 please (120000-140000) .word 0 ; base virtual address returned .word 40*4 ; 4kw window size .word 0 ; fill in region id .word 0 ; offset into region .word 40*4 ; map all of it .word WS.MAP!WS.EXT!WS.WRT!WS.RED ; read, extend and write .word 0 ; sen/receive buffer address idregd: .word 0 ; region id returned .word 40*4 ; 4 kw for now .word 0 ; noname for region .word 0 ; noname for region .word 0 ; same parition .word 0 ; same parition .word RS.RED!RS.WRT!RS.ATT ; attach + read + write .word ^C377 ; no world or group access idwind: .byte 0 ; return the window id .byte 4 ; apr 6 please (140000-160000) .word 0 ; base virtual address returned .word 40*4 ; 4kw window size .word 0 ; fill in region id .word 0 ; offset into region .word 40*4 ; map all of it .word WS.MAP!WS.EXT!WS.WRT!WS.RED ; read, extend and write .word 0 ; sen/receive buffer address .psect wincod crewin::feat$s #FE$FMP ; Will fast mapping work? bcs 10$ ; No cmpb @#$DSW ,#IS.SET ; Is this supported? bne 10$ ; No tfea$s #T4$FMP ; Do have have fast mapping here? bcs 10$ ; No cmpb @#$DSW ,#IS.SET ; Yes, but is it enabled? bne 10$ ; No, ignore mov sp ,fmap ; Yes, say so. 10$: tst #idspac ; I/D space version? beq 20$ ; No crrg$s #idregdsc ; Yes, create the region please bcs 90$ ; It's dedicated to buffering mov r.gid+idregdsc,w.nrid+idwindsc craw$s #idwindsc bcs 90$ ; failed, exit please mov r.gid+idregdsc,w.nrid+idwindsc mov #WS.WRT ,w.nsts+idwindsc; do a map next (redundant) clr w.noff+idwindsc ; offset zero from region start mov #40*4 ,w.nlen+idwindsc; amount to map map$s #idwindsc ; do it please bcs 90$ ; exit mov #40*KWID,regdsc+2 ; Reset the other region's size ; 20$: crrg$s #regdsc ; create the region please bcs 90$ ; failed mov r.gid+regdsc,w.nrid+windsc craw$s #windsc bcs 90$ ; failed, exit please mov #WS.WRT ,w.nsts+windsc ; do a map next (redundant) mov #-1 ,highmap ; no index mapped yet map$s #windsc ; do it please bcs 90$ ; exit inc mapcnt ; Stats mov #1 ,r0 return 90$: movb @#$DSW ,r0 return mapcac::tst #idspac ; I/D space version? bne 10$ ; Yes, don't need to map it. mov #-1 ,highmap mov r.gid+regdsc,w.nrid+windsc mov #WS.WRT ,w.nsts+windsc ; do a map next (redundant) clr w.noff+windsc ; offset zero from region start mov #40*4 ,w.nlen+windsc ; amount to map map$s #windsc ; do it please bcs 90$ ; oops inc mapcnt ; Stats 10$: mov #1 ,r0 ; success, exit return ; bye 90$: movb @#$DSW ,r0 ; error, return the error code return unmapc::tst #idspac ; I/D space version. If so, we bne 20$ ; Yes, exit. mov r.gid+regdsc,w.nrid+windsc ; don't need to remap. mov #WS.WRT ,w.nsts+windsc ; do a map next (redundant) mov #40*4 ,w.noff+windsc ; offset 4kw from region start mov #40*4 ,w.nlen+windsc ; amount to map clr highmap ; indicate which part of index mapped tst fmap ; Will fast mapping function? beq 10$ ; No mov #100050 ,r0 ; Yes, setup for fast mapping mov #40*4 ,r1 ; Offset mov #40*4 ,r2 ; Size iot ; Try it out tst r0 ; Successful? bpl 20$ ; Yes. ; 10$: map$s #windsc ; do it please bcs 90$ ; oops inc mapcnt ; Stats 20$: mov #1 ,r0 ; success, exit return ; bye 90$: movb @#$DSW ,r0 ; error, return the error code jmp maperr ;*********** TEMP return .endc ; if EQ, EXTEND .sbttl allocate memory for index .if eq ,EXTEND ; mapping to a region for buffering .ift mapmac::mov r1 ,-(sp) ; save it cmp highmap ,#3 ; Mapped already? beq 10$ ; Yes, don't bother then mov #3 ,highmap ; Not mapped to index anymore mov #40*2 ,w.nlen+windsc ; amount to map mov #40*20 ,w.noff+windsc ; offset 16kw from region start tst #idspac ; I/D space? beq 5$ ; No mov #40*14 ,w.noff+windsc ; Yes,offset 12kw from region start 5$: map$s #windsc ; do it please bcs maperr ; oops inc mapcnt ; Stats 10$: mov 4(sp) ,r1 ; macro buffer number mul #1000 ,r1 ; buffers are 512 bytes in size mov #120000 ,r0 ; base address of the window add r1 ,r0 ; offset into the window mov (sp)+ ,r1 ; pop saved r1 return ; back to caller now mapwin::mov 2(sp) ,r0 ; get offset into index to return tst w ; which window are we working on? beq 20$ ; file window number zero cmp highmap ,#2 ; already mapped correctly? beq 10$ ; yes, skip the remap mov #40*4 ,w.nlen+windsc ; amount to map mov #40*14 ,w.noff+windsc ; offset 12kw from region start tst #idspac ; I/D space? beq 5$ ; No mov #40*10 ,w.noff+windsc ; Yes,offset 8kw from region start 5$: map$s #windsc ; do it please bcs maperr ; oops inc mapcnt ; Stats mov #2 ,highmap ; show that we are not mapped to low 10$: br 50$ ; and return the address 20$: cmp r0 ,#3777 ; is there room for this in first 4kw? blos 40$ ; yes sub #4000 ,r0 ; no, map up to next 4kw boundary cmp highmap ,#1 ; already mapped here ? beq 30$ ; yes, skip the remap mov #40*4 ,w.nlen+windsc ; amount to map mov #40*10 ,w.noff+windsc ; offset 8kw from region start tst #idspac ; I/D space? beq 35$ ; No mov #40*4 ,w.noff+windsc ; Yes, offset 4kw from region start 35$: map$s #windsc ; do it please inc mapcnt ; Stats mov #1 ,highmap ; show that we are not mapped to low 30$: br 50$ ; and return the address 40$: tst highmap ; mapped to the low 4kw of index ? beq 50$ ; yes mov #40*4 ,w.noff+windsc ; no, remap to the low 4k area of index mov #40*4 ,w.nlen+windsc ; amount to map tst #idspac ; I/D space version? beq 45$ ; No clr w.noff+windsc ; Yes, start mapping at the start. 45$: map$s #windsc ; do it please inc mapcnt ; Stats clr highmap ; say we are already mapped 50$: asl r0 ; each entry is 2 words in size asl r0 add #120000 ,r0 return maperr: movb @#$DSW ,r0 mov r0 ,-(sp) mov #fmt ,-(sp) call xprintf exit$s getvm:: clr r0 ; failure (?) mov 4(sp) ,r1 ; window number to allocate tstb indcre(r1) ; already cbeen called ? bne 100$ ; yes, die tst r1 ; which window are we doing beq 10$ ; main one mov #<4000*4>/4,@6(sp) ; alternate index br 20$ 10$: mov #<4000*10>/4,@6(sp) ; size of index (8kw) 20$: mov #120000 ,r0 ; base of apr5 mapping incb indcre(r1) ; remember that we were called already 100$: return allbuf::mov #4*4 ,@2(sp) mov #120000 ,r0 tst #idspac beq 100$ mov #100000 ,r0 100$: return .endc ; if eq, EXTEND .sbttl allocate memory for index .if ne ,EXTEND .ift ; Note: Old method via extk$s ; ; char *getvm(size_of_block,block_number,&amount_allocated) ; ; Request size is in number of index blocks. Each index block ; is 4 bytes for the PDP-11. .mcall extk$s ,gtsk$s .save .psect rwdata .even vmbase: .word 0 vmtop: .word 0 vmalloc:.word 0 .psect index ,rw,d,gbl,rel,ovr windex::.word 0,0 ; extra at top of task .restore getvm:: tst vmbase ; do we have anything yet ? bne 10$ ; yes sub #40 ,sp ; no, do a gtsk$s to find it out mov sp ,r1 ; point to the buffer gtsk$s r1 ; get task info mov g.tsts(r1),r1 ; get task image size bic #1 ,r1 ; insure even mov #windex ,vmbase ; save base address of this then mov r1 ,vmtop ; save top address also add #40 ,sp ; pop buffer 10$: mov 2(sp) ,r1 ; number of entries to allocate sub vmalloc ,r1 ; less what we already allocated mul #4 ,r1 ; size of allocation in bytes ash #-6 ,r1 ; size of allocation in 32 word chunks bic #^c77 ,r1 ; drop any bits propagated over extk$s r1 ; request from exec bcs 90$ ; it failed ash #6 ,r1 ; convert back to number of bytes all clr r0 ; and convert back to number of entries div #4 ,r0 ; and return the count mov r0 ,@6(sp) ; send it back to caller add r0 ,vmalloc ; keep track of allocation so far mov vmbase ,r0 ; return base address also br 100$ ; exit 90$: clr r0 ; error exit, return address of zero 100$: return ; exit .endc ; if ne, EXTEND .sbttl allocate buffering for the work file .if ne ,EXTEND .ift ; char *allbuffer(&n_allocated,min_number,max_number) ; ; Allocate cache for disk workfile buffering. At some point ; later we will create a dynamic region (if a free apr is ; around) and write a new cacher to dynamically map things. ; It returns the number of 512 byte blocks allocated. .save .psect rwdata cache: .blkb 1000*4 .restore allbuffer:: mob #4 ,@2(sp) mov #cache ,r0 return mapcache:: unmapcache:: mapwin:: return .endc ; if ne, EXTEND .end