.TITLE MEMORY memory partition control .IDENT /01.09/ ; ; This file provides control structures and routines for maintaining ; memory partitions. ; ; routines provided: ; M$INIT initializes the memory partition table, adding two entries: ; one from location 0 to location END, named GRUMPF and typed SYS ; another for location END through (MAXMEM), named UNUSED and ; typed FRE ; M$CALL registers memory control system calls ; M$ALLO creates a new memory partition by using part or all of a FRE- ; typed partition. NAME, START, TYPE and SIZE must be provided, a ; pointer to the beginning of the partition is returned in R0. ; If START is zero, the new partition will be allocated from the ; first FRE partition that contains at least SIZE bytes. ; M$INFO prints the memory partition table on the console terminal. ; M$FREE frees a partition identified by its start address ; M$KILL frees all partitions belonging to a job ; ; control structure: ; PARTBL partition table, each entry consisting of 6 words ; P$NAME two words that should contain RAD50 values for the name ; P$TYPE one word containing a RAD50 string identifying the type ; P$JOB one word containing a pointer to the JOBTBL entry to which ; this partition belongs ; P$ADDR start address of the partition ; P$SIZE size of the partition (bytes) ; ; The type FRE is special, it indicates a partition that is not used ; otherwise and will be used for allocating space for new partitions. ; It is not enforced that P$NAME and P$TYPE actually contain RAD50 ; strings. Partition names need not to be unique. ; ; 11-MAY-2005 H. Rosenfeld fix bug in M$ALLO (PARCNT increment on exact ; fit) ; 03-MAY-2005 H. Rosenfeld use system call priorities ; 22-APR-2005 H. Rosenfeld adapt to change of POOL system ; 17-APR-2005 H. Rosenfeld fixed bug in M$ALLO, after allocating a ; partition from the middle of a FRE-partition, ; moving the partition table used the wrong count ; 11-APR-2005 H. Rosenfeld added M$FREE and M$KILL ; 09-APR-2005 H. Rosenfeld reworked M$ALLO to allow specifiying the start ; of the partition to allocate, adapt to change of ; POOL system ; 24-JAN-2005 H. Rosenfeld add calling convention library & .MCALLs ; 29-NOV-2004 H. Rosenfeld use contents of END instead of value of END ; 07-OCT-2004 H. Rosenfeld ; .LIST ME .NLIST CND .ENABL REG .LIBRARY /CALL.SML/ .LIBRARY /UTIL.SML/ .LIBRARY /MEMORY.SML/ .LIBRARY /JOBCTL.SML/ .LIBRARY /SYSCLL.SML/ .MCALL $SYS,$REGSYS .MCALL .CALL,.ENTRY,.RETRN .MCALL .SYSPUT,.OCTAL,.RADDEC .MCALL .P$ALLO,.P$FREE,.P$ERR .MCALL .JOBCTL NPAR=40 P$TYPE=0 P$ADDR=2 P$SIZE=4 P$JOB=6 P$NAME=10 .GLOBL MAXMEM,END,CURJOB .JOBCTL .CSECT ; M$INIT, memory system initialization ; clear memory partition table, register system partition, make rest FRE .MACRO .M$INIT .GLOBL M$INIT .CALL M$INIT .ENDM M$INIT::.ENTRY MOV #PARTBL,R0 MOV #^RSYS,P$TYPE(R0) ; system partition CLR P$ADDR(R0) ; starting at loc 0 MOV END,P$SIZE(R0) ; ending at loc END MOV CURJOB,P$JOB(R0) ; belonging to CURJOB (which is SYSJOB) MOV #^RGRU,P$NAME(R0) ; named "GRUMPF" MOV #^RMPF,P$NAME+2(R0) ADD #14,R0 ; next entry MOV #^RFRE,P$TYPE(R0) ; free partiton MOV END,P$ADDR(R0) ; beginning at loc END MOV MAXMEM,P$SIZE(R0) ; size MAXMEM-END SUB END,P$SIZE(R0) CLR P$JOB(R0) ; belonging to no job CLR P$NAME(R0) ; without a name CLR P$NAME+2(R0) MOV #2,PARCNT ; we have 2 partitons .RETRN ; M$CALL, register memory system calls .MACRO .M$CALL .GLOBL M$CALL .CALL M$CALL .ENDM M$CALL::.ENTRY $REGSYS #^RM$A,#^RLLO,#M$ALLO,#340 $REGSYS #^RM$F,#^RREE,#M$FREE,#340 .RETRN ; M$INFO, print memory partition table .MACRO .M$INFO .GLOBL M$INFO .CALL M$INFO .ENDM M$INFO::.ENTRY .P$ALLO #120 ; we need a buffer for output strings BCC 2$ ; continue if no error .P$ERR .RETRN 2$: MOV R0,R2 ; save buffer address MOV PARCNT,R3 ; get partition count .SYSPUT #HDLINE ; print a headline .SYSPUT #CRLF .SYSPUT #UDLINE ; and an underline .SYSPUT #CRLF MOV #PARTBL,R4 1$: MOV R2,R0 .RADDEC P$NAME(R4),R0 ; print partition name .RADDEC P$NAME+2(R4),R0 MOVB #11,(R0)+ .RADDEC P$TYPE(R4),R0 ; print partition type MOVB #11,(R0)+ MOV P$JOB(R4),R1 ; get partition owner BEQ 4$ ; no owner, skip printing MOV R1,-(SP) .RADDEC J$NAME(R1),R0 ; print owners name MOV (SP)+,R1 .RADDEC J$NAME+2(R1),R0 4$: MOVB #11,(R0)+ .OCTAL P$ADDR(R4),R0 ; print partition address MOVB #11,(R0)+ .OCTAL P$SIZE(R4),R0 ; print partition size .SYSPUT R2 .SYSPUT #CRLF ADD #14,R4 ; next entry DEC R3 BNE 1$ ; continue until all partitions are printed .P$FREE R2,#120 ; free output buffer .RETRN ; M$ALLO, allocate memory partition ; input: start address of partition (or 0 if start address doesn't matter), ; size of partition, type of partition, name of partition ; output: partition created in partition table if possible ; return: carry set on error, clear otherwise ; R0 start address of partition .MACRO .M$ALLO START SIZE TYPE NAM1 NAM2 .GLOBL M$ALLO .CALL M$ALLO,START,SIZE,TYPE,NAM1,NAM2 .ENDM .MACRO $M$ALLO START SIZE TYPE NAM1 NAM2 .MCALL $SYS $SYS #^RM$A,#^RLLO,START,SIZE,TYPE,NAM1,NAM2 .ENDM M$ALLO::.ENTRY MOV 6(R5),R0 ; first argument: start address of partition INC R0 BIC #1,R0 ; make it word-aligned MOV R0,6(R5) ; save for later reuse MOV 10(R5),R0 ; second argument: size of partiton INC R0 BIC #1,R0 ; make ist word-aligned MOV R0,10(R5) ; save for later reuse MOV PARCNT,R3 ; get partition count CMP R3,#NPAR ; partition table full? BEQ 6$ ; yea, error MOV #PARTBL,R4 1$: CMP P$TYPE(R4),#^RFRE ; partition free? BNE 5$ ; nay, get next partition MOV 6(R5),R0 ; get start of partition MOV 10(R5),R1 ; get size of partition TST R0 ; zero start address? BEQ 7$ ; yea, don't compare CMP P$ADDR(R4),R0 BHI 5$ ; entry is out of range, try next ADD R0,R1 ; calculate end of partition SUB P$ADDR(R4),R1 ; calculate minimum size of entry 7$: CMP P$SIZE(R4),R1 ; does it fit? BHIS 8$ ; yea, this is the one 5$: ADD #14,R4 ; next entry SOB R3,1$ ; continue until no entries left 6$: SEC .RETRN 8$: MOV 10(R5),R1 ; get size of partition TST R0 ; zero address? BEQ 2$ ; yeah, just use address of free partition CMP P$ADDR(R4),R0 ; does the address match? BEQ 2$ ; yea, use it MOV P$SIZE(R4),-(SP); save old size MOV R0,P$SIZE(R4) ; calculate remaining lower size SUB P$ADDR(R4),P$SIZE(R4) MOV (SP)+,R1 ; restore old size SUB P$SIZE(R4),R1 ; calculate remaining higher size ADD #14,R4 ; get next entry MOV R4,-(SP) ; save for reuse MOV R1,-(SP) ; save remaining higher size for inserting MOV CURJOB,-(SP) ; save CURJOB for inserting MOV R0,-(SP) ; save address of partiton for inserting MOV R3,R2 ; save remaining partition count BR 3$ ; branch to insert 2$: MOV R4,-(SP) ; save current entry MOV R1,-(SP) ; save size of new partition for inserting MOV CURJOB,-(SP) ; save CURJOB for inserting MOV P$ADDR(R4),-(SP); save address of new partition for inserting ADD R1,P$ADDR(R4) ; adjust address of entry SUB R1,P$SIZE(R4) ; adjust size of entry BEQ 4$ ; skip inserting on exact fit 3$: MOV (SP),R0 ; get new address from stack MOV P$ADDR(R4),(SP) ; store old address in stack MOV R0,P$ADDR(R4) ; store new address in entry MOV 16(R5),R0 ; get new second part of name MOV P$NAME+2(R4),16(R5) ; store old second part of name MOV R0,P$NAME+2(R4) ; store new second part of name MOV 14(R5),R0 ; get new first part of name MOV P$NAME(R4),14(R5) ; store old first part of name MOV R0,P$NAME(R4) ; store new first part of name MOV 12(R5),R0 ; get new partition type MOV P$TYPE(R4),12(R5) ; store old partition type MOV R0,P$TYPE(R4) ; store new partition type MOV 4(SP),R0 ; get new partiton size from stack MOV P$SIZE(R4),4(SP); store old partition size in stack MOV R0,P$SIZE(R4) ; store new partition size MOV 2(SP),R0 ; get new partition owner from stack MOV P$JOB(R4),2(SP) ; store old partition owner in stack MOV R0,P$JOB(R4) ; store new partition owner ADD #14,R4 ; get the next entry SOB R3,3$ ; continue until no partitions left INC PARCNT ; increment partition count 4$: MOV (SP)+,P$ADDR(R4); store partition address MOV (SP)+,P$JOB(R4) ; store partition owner MOV (SP)+,P$SIZE(R4); store partition size MOV 16(R5),P$NAME+2(R4) ; store second part of partition name MOV 14(R5),P$NAME(R4) ; store first part of partition name MOV 12(R5),P$TYPE(R4) ; store partition type MOV (SP)+,R4 ; restore new partition entry CMP P$SIZE(R4),10(R5) ; size matching? BEQ 9$ ; yea, we're done CMP PARCNT,#NPAR ; still partition slots left? BEQ 9$ ; no, so we're done MOV R4,-(SP) ; save entry for reuse MOV P$SIZE(R4),R1 SUB 10(R5),R1 ; calculate remaining size MOV 10(R5),P$SIZE(R4) ; store new size of entry MOV R1,-(SP) ; store remaining size for insert MOV P$ADDR(R4),R1 ADD P$SIZE(R4),R1 ; calculate new address of entry SUB #14,R4 ; rewind to previous entry MOV P$JOB(R4),-(SP) ; store owner of previous entry for insert MOV P$NAME(R4),14(R5) ; store name of previous entry MOV P$NAME+2(R4),16(R5) MOV P$TYPE(R4),12(R5) ; store type of previous entry MOV R1,-(SP) ; store new address for insert ADD #30,R4 ; skip to next entry MOV R2,R3 ; restore remaining partition count BR 3$ ; insert again 9$: MOV P$ADDR(R4),R0 ; return partition address CLC .RETRN ; M$FREE, free memory partition ; input: partition start address ; output: partition is made FRE, adjacent FRE partitions are concatenated ; return: none .MACRO .M$FREE START .GLOBL M$FREE .CALL M$FREE,START .ENDM .MACRO $M$FREE START $SYS #^RM$F,#^RREE,START .ENDM M$FREE::.ENTRY MOV 6(R5),R0 ; argument: start address of partition INC R0 BIC #1,R0 ; make it word-aligned MOV #PARTBL,R1 MFPS -(SP) MTPS #340 ; we do not want to be interrupted MOV PARCNT,R2 1$: CMP P$ADDR(R1),R0 ; does address match? BEQ 2$ ; yea, go on ADD #14,R1 ; try next entry SOB R2,1$ ; until no entries are left MTPS (SP)+ .RETRN 2$: CLR P$NAME(R1) ; free partitions have no name CLR P$NAME+2(R1) CLR P$JOB(R1) ; they don't have an owner, too MOV #^RFRE,P$TYPE(R1) ; and they are of type FRE JSR PC,CONCAT ; concatenate adjacent free partitions MTPS (SP)+ .RETRN ; M$KILL, kill memory partitions ; input: job that owns partitions to be killed ; output: partitions are made FRE, adjacent FRE partitions concatenated ; return: none .MACRO .M$KILL JOB .GLOBL M$KILL .CALL M$KILL,JOB .ENDM M$KILL::.ENTRY MOV 6(R5),R0 ; argument: owner of partitions to kill INC R0 BIC #1,R0 ; make it word-aligned MOV #PARTBL,R1 MFPS -(SP) MTPS #340 ; we do not want to be interrupted MOV PARCNT,R2 1$: CMP P$JOB(R1),R0 ; check owner BNE 2$ ; these are not the droids you are looking for CLR P$JOB(R1) ; no job CLR P$NAME(R1) ; and no name CLR P$NAME+2(R1) MOV #^RFRE,P$TYPE(R1) ; so this is a FRE partition 2$: ADD #14,R1 ; next entry SOB R2,1$ ; until no entries left JSR PC,CONCAT ; concatenate adjacent free partitions MTPS (SP)+ .RETRN ; CONCAT is a helper routine for M$FREE and M$KILL. It will search the PARTBL ; for adjacent FRE partitions and concatenate them. CONCAT must be called with ; interrupts blocked. CONCAT: MOV #PARTBL+14,R0 ; we start with the second entry MOV PARCNT,R1 DEC R1 ; therefore we do PARCNT-1 iterations 1$: CMP P$TYPE-14(R0),#^RFRE ; is the previous partition FRE? BNE 3$ ; nay, go on CMP P$TYPE(R0),#^RFRE ; is this partition FRE, too? BNE 3$ ; nay, go on ADD P$SIZE(R0),P$SIZE-14(R0); yea, concatenate MOV R0,R4 ; save entry for reuse MOV R1,R3 ; save remaining count for reuse 2$: MOV P$TYPE+14(R4),P$TYPE(R4); move next entry down MOV P$ADDR+14(R4),P$ADDR(R4) MOV P$SIZE+14(R4),P$SIZE(R4) MOV P$NAME+14(R4),P$NAME(R4) MOV P$NAME+16(R4),P$NAME+2(R4) MOV P$JOB+14(R4),P$JOB(R4) ADD #14,R4 ; go to next entry SOB R3,2$ ; continue moving DEC PARCNT ; we deleted an entry SOB R1,1$ ; continue concatenating RTS PC 3$: ADD #14,R0 ; skip to next entry SOB R1,1$ ; and try again RTS PC .PSECT DATA PARTBL::.BLKW 6*NPAR PARCNT::.BLKW 1 .PSECT CONST HDLINE: .ASCIZ /NAME TYPE JOB ADDR SIZE / CRLF: .ASCIZ <15><12> UDLINE: .ASCIZ /---------------------------------------/ .END