MiniUnix/usr/source/salloc/alloc3.s
.globl flag
.globl b1, w1, u1, b1s, b1e
/ here to allocate a new block
/
/
/ mov ...,r0
/ jsr pc,allocate
/ mov r1,...
/
/ requested size in bytes in r0
/ pointer to header of allocated block returned in r1
/ r0 is preserved
/
/ convert to words, adjust for header, round up
/ to a power of two
/
/ each block has a four-word header
/ W - write ptr (also used as link ptr in frlist)
/ R - read ptr
/ A - pointer to head of data
/ L - ptr to (end+1) of data
hsz=1024.
numb=4.
numb2=2*numb
w=0
r=2
a=4
l=6
/
allocate:
mov r0,-(sp)
mov r2,-(sp)
mov r3,-(sp)
tst stats
bne 1f
jsr pc,initl
1:
inc stats
dec r0
bmi 1f
jsr pc,log2
inc r0
1: asl r0
mov r0,-(sp)
/
/ look on free list for block of required size
/
zzz:
mov (sp),r0
tst frlist(r0)
beq xxx
/
/ found it, allocate and return
/
mov frlist(r0),r1
add $hblk,r1
mov (r1),frlist(r0)
mov a(r1),r0
mov r0,w(r1)
mov r0,r(r1)
tst (sp)+
mov (sp)+,r3
mov (sp)+,r2
mov (sp)+,r0
/ jsr pc,whead
rts pc
/
/ no block of required size
/ look for larger block
/
xxx:
tst (r0)+
cmp r0,$frend-frlist
bhis www
tst frlist(r0)
bne yyy
br xxx
/
/ there are no larger blocks; must garbage collect
/
www: jsr pc,collect
tst r0
bne zzz
/
/ out of space
/
mov $1,r0
sys write; 1f; 2f-1f
4
1: <Out of space.\n>
2: .even
/
/ split larger block into two smaller pieces and
/ link together as smaller blocks in the free list.
/
yyy:
mov hblk,r3 /get free header block
beq www
mov frlist(r0),r1
add $hblk,r1
mov w(r1),frlist(r0)
mov r3,w(r1)
add $hblk,r3
mov exp2-2(r0),r2
add a(r1),r2
mov w(r3),hblk
mov l(r1),l(r3)
mov r2,l(r1) /L
mov r2,a(r3)
clr w(r3) /W'
mov r1,r2
sub $hblk,r2
mov r2,frlist-2(r0)
br zzz
/
/
/ here to release a block
/
/ mov ...,r1
/ jsr pc,release
/
/ pointer to block in r1
/
release:
/
/ discover that this is a plausible pointer
/
mov r0,-(sp)
jsr pc,preposterous
/
/ find free list index and link block to that entry
/
inc stats+2
mov frlist(r0),w(r1)
clr r(r1)
sub $hblk,r1
mov r1,frlist(r0)
clr r1 /self-defense
/ jsr pc,whead
mov (sp)+,r0
rts pc
/
/
/ jsr pc,collect
/
/ coalesce free storage by rejoining paired blocks
/ on the free list.
/ zero is returned in r0 if no paired blocks were found.
/
collect:
mov r1,-(sp)
mov r2,-(sp)
mov r3,-(sp)
mov r4,-(sp)
clr useful
inc stats+4.
clr r0 /start with smallest blocks
/r0 contains frlist index
loop1: mov $frlist,r1
add r0,r1
/
/ try next list member at this level
/
loop2: mov (r1),r3
beq advance /list is empty
add $hblk,r3
tst (r3) /W
beq advance /only one list element
/
/ calculate address of buddy
/
mov a(r3),r4
sub headsz,r4
bit exp2(r0),r4
beq 2f
bic exp2(r0),r4
br 1f
2: bis exp2(r0),r4
1: add headsz,r4
/
/ and search for him
/
loop3:
cmp a(r3),r4
beq coal
mov r3,r2
mov w(r3),r3
tst r3
beq nocoal
add $hblk,r3
br loop3
/
/ have found a pair; remove both blocks from list,
/ coalesce them, and put them on next higher list
/
coal: inc useful
mov w(r3),w(r2) /remove him from list
mov (r1),r2
add $hblk,r2
mov r3,r4
mov w(r2),w(r1) /remove other one
cmp a(r2),a(r4)
bgt 1f
mov r2,-(sp)
mov r4,r2
mov (sp)+,r4
1: mov hblk,(r2)
clr r(r2)
mov headsz,a(r2)
mov headsz,l(r2)
sub $hblk,r2
mov r2,hblk
add exp2(r0),l(r4) /L
clr r(r4)
mov frlist+2(r0),w(r4)
sub $hblk,r4
mov r4,frlist+2(r0)
br loop2
/
/ no buddy found, try next block on this list
/
nocoal:
mov (r1),r1
add $hblk,r1
br loop2
/
/ advance to next free list
/
advance:
tst (r0)+
cmp r0,$frend-frlist
blo loop1
mov useful,r0
/
/ restore registers and return
/
mov (sp)+,r4
mov (sp)+,r3
mov (sp)+,r2
mov (sp)+,r1
rts pc
/
/ routine to find integer part of log2(x)
/
/ jsr pc,log2
/
/ r0 = log2(r0)
/
log2:
mov $15.,-(sp)
tst r0
beq 2f
1:
asl r0
bcs 2f
dec (sp)
br 1b
2:
mov (sp)+,r0
rts pc
/
0
exp2:
1;2;4;10;20;40;100;200;400;1000;2000;4000;
10000;20000;40000;100000
/
/ routine to discover whether r1 points to
/ a plausible header - to avoid ruination.
/
/ r1 is preserved and r0 gets a suitable index for frlist
/
/ jsr pc,preposterous
/
plausible:
cmp r1,$strbuf
blo botch
cmp r1,$strend
bhis botch
rts pc
/
/
botch:
mov r0,-(sp)
mov $1,r0
sys write; 1f; 2f-1f
4
1: <Error in allocator.\n>
2: .even
/
/
preposterous:
cmp r1,$strbuf
blo botch
cmp r1,$strend
bhis botch
cmp a(r1),headsz /A
blo botch
cmp l(r1),datadr /L
bhi botch
mov l(r1),r0 /L
sub a(r1),r0 /A
mov r0,-(sp)
jsr pc,log2
asl r0
cmp exp2(r0),(sp)
bne botch
mov r0,(sp)
mov frlist(r0),r0
1: beq 1f
add $hblk,r0
cmp r0,r1
beq botch
mov (r0),r0
br 1b
1: mov (sp)+,r0
rts pc
/
/
whead:
mov r0,-(sp)
mov afout,r0
sys seek;0;0 /write pointer to 0
sys write;hblk;hsz
mov (sp)+,r0
rts pc
/
datasz: 16384.
headsz: hsz
nbuf: numb
nbuf2: numb2
b1s: .=.+numb2
b1e: .=.+ numb2
w1: .=.+ numb2
u1: .=.+ numb2
b1 = .
/
initl:
mov r0,-(sp)
mov r2,-(sp)
sys open;asmem; 1 /open for write
bec 2f
sys creat;asmem; 606
bes err2
2:
mov r0,afout
1:
sys open; asmem; 0 /open for read
bes err2
mov r0,afi
1:
br gargs
/
err2:
mov $1,r0
sys write; 1f; 2f-1f
4
1: <cannot open output file\n>
2:
asmem:
<alloc.d\0>
.even
/
gargs:
mov $headers,r2
mov r2,r0
sub $hblk,r0
mov r0,hblk
1:
add $8,r0
mov r0,(r2)
add $8,r2
cmp r2,$strend-8.
blo 1b
clr -8(r2)
/
mov headsz,datadr
add datasz,datadr
/
mov $frlist,r0
1: clr (r0)+
cmp r0,$frend
blo 1b
mov hblk,r2
add $hblk,r2
mov (r2),hblk
clr w(r2)
mov headsz,a(r2)
mov datadr,l(r2)
mov datasz,r0
jsr pc,log2
asl r0
cmp r0,$frend-frlist
blo 9f; 4; 9:
sub $hblk,r2
mov r2,frlist(r0)
/
/ install plausible pointers to make octal dumps look ok
/
mov $hblk,r1
1: mov (r1),r1
beq 1f
add $hblk,r1
mov headsz,a(r1)
mov headsz,l(r1)
br 1b
/
1: mov afout,r0
sys write;hblk;hsz
jsr pc,reset
mov (sp)+,r2
mov (sp)+,r0
rts pc
. = b1 + [512.*numb]
/
.bss
flag: .=.+2
stats: .=.+18.
useful: .=.+2
afi: .=.+2
afout: .=.+2
datadr: .=.+2
hblk: .=.+2 /must remain here - pointer to free header
frlist: .=hblk+34.
frend:
headers:
strbuf: .=hblk+hsz
strend:
nchar: .=.+2
end: