 lib environment
 sttl Memory management routines
 pag
 name memman
 global getpag,givpag,makmem,fremem
 global asnmem,grows,growd,unmemd
 global mktxt,frtxm,exsdt,frems,tstmax,unmems

*
* getpag
*
* Get one segment of memory.  Return segment
* number in machine dependent form in reg b.
* Return 'eq' status if no memory available.
*

getpag pshs x
 tst corcnt memory left?
 beq getpa6
 tst MAXMAP any memory maps?
 beq 00f
 inc urelod set reload flag
00 ldx memfst point to first avail
 ldb 0,x+ get a segment
 dec corcnt dec the count
 cmpx lstmem end of list?
 bne getpa2
 ldx #memtab point back to beginning
getpa2 stx memfst save new first
getpa4 puls x,pc return
getpa6 ldx #memufl point to message
 jmp blowup blowup system!


*
* givpag
*
* Give the memory segment in b back to the system
* list of available memory.  Blowup system if
* overflow the memory table (this can't happen).
*

givpag pshs x
 cmpb WHTHOL is it 'whitehole'
 beq givpa3
 ldx memlst get tail pointer
 tst corcnt is list empty?
 beq givpa1
 cmpx memfst table overflow?
 beq givpa4
givpa1 stb 0,x+ save segment
 cmpx lstmem end of table?
 bne givpa2
 ldx #memtab rap around
givpa2 stx memlst rest new pointer
 inc corcnt bump avail count
 tst MAXMAP multiple memory maps?
 beq givpa3
 inc urelod set reload flag
givpa3 puls x,pc return
givpa4 ldx #memofl point to message
 jmp blowup blow up system!


 pag

*
* makmem
*
* Build the systems available memory table.  This
* routine is only called once during system init.
*

makmem ldx #memtab point to begin of table
 stx memlst set tail ptr
 stx memfst set head ptr
 rts return

 pag

*
* fremem
*
* Free the memory associated with the current
* user task.
*

fremem lda usized get data size
 adda usizes add to stack size
 pshs a save it
 clr usizes zero out size info
 clr usized
 ldx #umem+NBLKS point to mem map
freme2 ldb 0,-x get a segment number
 cmpb BLKHOL is it valid?
 beq freme2
 bsr givpag free up the segmant
 dec 0,s dec the seg count
 bne freme2 are we done?
 tst rdytgo swapper need memory?
 beq freme4
 pshs y save ptr
 ldy #rdytgo point to event
 clr 0,y zero flag
 jsr wakeup
 puls y reset ptr
freme4 puls a,pc return

*
* asnmem
*
* Assign memory to a new task.  A has text size
* and B has data size.
*

asnmem pshs d save size data
 ldx #umem point to memory map
 ldb #USRHIP set count
 lda BLKHOL set no mem byte
asnme2 sta 0,x+ fill map with no memory
 decb dec the counter
 bne asnme2
 ldd 0,s get data count
 cmpb corcnt enough memory?
 bhi asnme7
 stb usized set data size
 beq asnme6 no data?
 ldx utask point to task
 addb tssize,x adjust swap image size
 stb tssize,x
 puls a get text size
 ldx #umem point to map beginning
 leax a,x move past text part
asnme4 jsr clrpag get a cleared out segment
 stb 0,x+ save segment number
 dec 0,s dec the seg count
 bne asnme4
 puls a,pc return
asnme6 puls d,pc return
asnme7 clra set text size to 0 (6-18-81)
 jsr exsdt expand swap for data mem
 lda #1 set for memory free
 jsr exsdtx go swap
 lda 0,s get text size (rest added 6-18-81)
 beq asnme6 if 0 - exit
 ldb 1,s get data size
 ldx #umem point to mem map
 leax b,x
asnme8 ldb 0,-x move data up by text size
 stb a,x
 dec 1,s dec the data count
 bne asnme8
 leax a,x
 ldb BLKHOL replace cell with blackhole
asnme9 stb 0,-x fill text with blackholes
 cmpx #umem finished?
 bne asnme9
 puls d,pc return to exec

 pag

*
* grows
*
* Grow stack by the number of segments in B.
*

grows tstb is request 0?
 bne grows1
 rts return - no grow
grows1 pshs b save count
 jsr tstmax too many segments needed?
 bne grows8 if so - error
 puls b get count
 cmpb corcnt have enough core?
 bhi grows6
 lda usizes get current size
 pshs b save count
 adda 0,s find new total size
 ldx #umem+NBLKS point to memory map
 nega
 leax a,x point to new stack bottom
 ldy utask point to task entry
grows4 lda 0,x get current segment
 cmpa BLKHOL it should be void
 bne grows8 if not, error
grows5 jsr clrpag get a new segment
 stb 0,x+ save new segment
 inc usizes bump stack size count
 inc tssize,y bump swap size too
 dec 0,s dec grow count
 bne grows4
 puls a,pc return
grows6 pshs b save count
 ldx #umem+NBLKS point to end of map
 lda usizes get stack size
 adda 0,s find new size
 sta usizes save new size
 nega
 leax a,x point to new stack start in map
 lda WHTHOL set up 'whitehole' constant
 ldb 0,s get count
grows7 sta 0,x+ set in map
 decb dec the count
 bne grows7
 puls b get count
 lda #1 set for free mem
 jmp exsdtx go expand - swap
grows8 lda #ESTOF set overflow error
 sta uerror
 puls a,pc return


 pag

*
* growd
*
* Grow the data portion of the address space.  This
* is only called from the 'break' system call.
* On entry, a has total stack & data size, and B
* has new segment number needed.
*

growd pshs d save data
 subb 0,s calc how many segments needed
 pshs b save count
 jsr tstmax too many needed?
 bne growd8 if so - error
 puls b reset count
 cmpb corcnt have enough core?
 bhi growd6
 pshs b save as counter
 ldx #umem point to mem map
 lda 1,s get end of current data
 leax a,x point to it
 ldy utask point to task entry
growd2 lda 0,x get cell contents
 cmpa BLKHOL is it empty?
 bne growd8 if not, error!
growd3 jsr clrpag get new segment
 stb 0,x+ set seg in map
 inc usized bump size info
 inc tssize,y bump swap size too
 dec 0,s dec the count
 bne growd2 repeat?
 leas 3,s clean off stack
 rts return
growd6 puls a get text and data size
 leas 1,s fix stack
 jsr exsdt do swap - expand
 lda #1 set for free mem
 jmp exsdtx go swap
growd8 lda #EDTOF set overflow error
 sta uerror set in error
 leas 3,s clean stack
 rts return


 pag

*
* unmemd, unmems
*
* Release memory as requested by 'break' and 'stack'.
*

unmemd pshs b save release count
 lda usized get data size
 suba 0,s dec data count
 sta usized
 ldy utask point to task entry
 lda tssize,y get swap size
 suba 0,s subtract free count
 sta tssize,y
unmmd2 ldb 0,-x get a byte
 lbsr givpag release the segment
 ldb BLKHOL fill in hole
 stb 0,x
 dec 0,s dec the seg counter
 bne unmmd2 repeat?
 bra unmms4
*
unmems pshs b save release count
 lda usizes adjust stack seg count
 suba 0,s
 sta usizes
 ldy utask point to task
 lda tssize,y get swap size
 suba 0,s subtrack free count
 sta tssize,y save new
unmms2 ldb 0,x get seg
 lbsr givpag release it
 ldb BLKHOL fill hole
 stb 0,x+
 dec 0,s finished?
 bne unmms2
unmms4 tst rdytgo swapper need mem?
 beq unmms6
 pshs x,y save regs
 ldy #rdytgo set event
 jsr wakeup wakeup swapper
 puls x,y
unmms6 puls b,pc return


 pag

*
* mktxt
*
* Make text segment map.  Swap out if not enough memory.
*

mktxt cmpb corcnt enough memory?
 bls mktxt2
 sts umark2 save stack level
 ldb WHTHOL set up white hle
 lda usizet move text size to data
 adda usized for the expansion - swap
 sta usized
 ldx utask point to task entry
 lda usizet get text size
 adda tssize,x add to swap size
 sta tssize,x
 ldx #umem point to mem map
 lda usizet get text size
 clr usizet set it to zero
mktxt1 stb 0,x+ fill up map
 deca dec the count
 bne mktxt1
 ldx utask get task pointer
 ldb #1 set for free mem
 jsr swpout swap out task
 lda tsmode,x get modes
 ora #TSWAPO set swapped bit
 sta tsmode,x save new modes
 jmp change change tasks
mktxt2 pshs b,x,y save info
 leax txmap,x point to text map
 ldy #umem point to user memory
mktxt3 jsr getpag get a segment
 stb 0,x+ save in map
 stb 0,y+ set in user map
 dec 0,s dec count
 bne mktxt3 finished?
 puls b
 ldd #0 return 0 to show no swap
 puls x,y,pc return

*
* frtxm
*
* Free the memory in a text segment.
*

frtxm pshs x,y save regs
 ldb txsiz,y get text size
 beq frtxm4 none there?
 leax txmap,y point to map
 pshs b save count
frtxm2 ldb 0,x+ get a segment
 lbsr givpag free the segment
 dec 0,s dec the count
 bne frtxm2 finished?
 puls b reset stack
 tst rdytgo swapper need memory?
 beq frtxm4
 ldy #rdytgo wake him up
 jsr wakeup
frtxm4 puls x,y,pc reset regs & return

 pag

*
* exsdt
*
* Expand memory image and swap task.
*

exsdt pshs b save expansion count
 ldx #umem point to map
 leax a,x skip text
 lda WHTHOL set up 'whitehole' constant
exsdt2 sta 0,x+ set in map
 decb dec the count
 bne exsdt2
 ldb 0,s get count
 addb usized adjust data size
 stb usized
 puls b,pc get count
exsdtx ldx utask point to task
 addb tssize,x adjust image size
 stb tssize,x save new
 sts umark2 save stack position
 tfr a,b set to free memory
 jsr swpout swap out task
 lda tsmode,x get modes
 ora #TSWAPO set swapped
 sta tsmode,x
 jmp change go change tasks

*
* frems
*
* Free memory after swap.  A has count, U points to task.
*

frems pshs a save count
 lda tsutop,u get user top page
 jsr mapxbf map in to XBUFFER
 ldx #XBUFFR+(umem-USRLOC<<12)
 leax NBLKS,x point to end of mem map
 jmp freme2 go free memory


 pag

*
* tstmax
*
* Test for too many segments needed for grows and growd.
* Count in B.
*

tstmax pshs b save count
 addb usizes find new total
 addb usized
 addb usizet
 cmpb #NBLKS physically too many?
 bhi tstma4
 cmpb umxmem is this max mem?
 bls tstma2
 stb umxmem set new max
tstma2 ldx uuid check for super user
 beq tstma4
 cmpb smxm system max limit?
 bhi tstma4
 sez set ok status
tstma4 puls b,pc return
