misc/060tsys/t15memory.s
;----------------------------------------------------------------
;
; メモリ管理ルーチン
;
;----------------------------------------------------------------
.include t01dos.equ
.include t02const.equ
.include t08debug.equ
;__DEBUG__ equ 1
.cpu 68060
;----------------------------------------------------------------
;ブロックの確保を行うルーチンのテーブル
malloc2Table::
.dc.l malloc20 ;下位から
.dc.l malloc21 ;必要最小ブロックから
.dc.l malloc22 ;上位から
.dc.l malloc23 ;最大ブロックから
;----------------------------------------------------------------
;ブロックの確保(下位から)
;<d2.l:確保するサイズ
;<d4.l:親プロセスのメモリ管理テーブル
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0=成功,$8xxxxxxx=確保できる最大のサイズ
;>a1.l:0=失敗,0以外=確保したブロックのユーザ領域の先頭
;*d0/a1
malloc20::
movem.l d1-d2/a2,-(sp)
debug '|malloc20 in (size,proc)=',2,d2,d4
cmp.l #LOGICAL_SIZE-1,d2 ;念のため
bls @f
move.l #LOGICAL_SIZE-1,d2
@@: move.l a4,d0 ;先頭のブロック
malloc20Loop:
cmp.l a5,d0
bcc malloc20Failed ;見つからなかった
movea.l d0,a2
tst.b (Tail,a2)
bmi malloc20Next ;ロックされている
bsr splitBlock ;分割してできるブロックのヘッダとサイズを求める
bmi malloc20Next ;分割できない
cmp.l d2,d1 ;サイズが足りているか
bhs malloc20Found ;見つかった
malloc20Next:
move.l (Next,a2),d0 ;次のブロックへ
bne malloc20Loop
malloc20Failed:
suba.l a1,a1
bsr getSize
;<d0.l:確保できるサイズの合計
;<d1.l:一度に確保できる最大のサイズ
move.l d1,d0 ;最大のサイズ
or.l #$80000000,d0 ;最上位ビットだけセットする
bra malloc20End
malloc20Found:
bsr insertHeader ;ヘッダを挿入する
lea.l (User,a1),a1 ;ユーザ領域の先頭
add.l a1,d2 ;ユーザ領域の末尾+1
move.l d2,(-User+Tail,a1) ;ユーザ領域の末尾+1
move.l d4,(-User+Proc,a1) ;親プロセスのメモリ管理テーブル
moveq.l #0,d0
malloc20End:
debug '|malloc20 out (err,ptr)=',2,d0,a1
movem.l (sp)+,d1-d2/a2
rts
;----------------------------------------------------------------
;ブロックの確保(必要最小ブロックから)
;<d2.l:確保するサイズ
;<d4.l:親プロセスのメモリ管理テーブル
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0=成功,$8xxxxxxx=確保できる最大のサイズ
;>a1.l:0=失敗,0以外=確保したブロックのユーザ領域の先頭
;*d0/a1
malloc21::
movem.l d1-d3/d5/a2-a4,-(sp)
debug '|malloc21 in (size,proc)=',2,d2,d4
cmp.l #LOGICAL_SIZE-1,d2 ;念のため
bls @f
move.l #LOGICAL_SIZE-1,d2
@@: move.l a4,d0 ;先頭のブロック
moveq.l #$FFFFFFFF,d3 ;見つかった最小のブロックのサイズ
moveq.l #0,d5 ;見つかった最小のブロック
malloc21Loop:
cmp.l a5,d0
bcc malloc21Last ;見つからなかった
movea.l d0,a2
tst.b (Tail,a2)
bmi malloc21Next ;ロックされている
bsr splitBlock ;分割してできるブロックのヘッダとサイズを求める
bmi malloc21Next ;分割できない
cmp.l d2,d1 ;サイズが足りているか
blo malloc21Next ;足りない
cmp.l d3,d1 ;これまでに見つかったブロックのサイズより小さいか
bhs malloc21Next ;大きいか等しい
move.l d1,d3 ;最小のブロックのサイズを更新
movea.l a1,a3 ;ヘッダを作れる位置を更新
move.l a2,d5 ;見つかったブロックのヘッダを更新
malloc21Next:
move.l (Next,a2),d0 ;次のブロックへ
bne malloc21Loop
malloc21Last:
move.l d5,d0 ;見つかった最小のブロック
beq malloc21Failed ;見つからなかった
movea.l a3,a1 ;新しいヘッダ
movea.l d5,a2 ;見つかったブロックのヘッダ
bsr insertHeader ;ヘッダを挿入する
lea.l (User,a1),a1 ;ユーザ領域の先頭
add.l a1,d2 ;ユーザ領域の末尾+1
move.l d2,(-User+Tail,a1) ;ユーザ領域の末尾+1
move.l d4,(-User+Proc,a1) ;親プロセスのメモリ管理テーブル
moveq.l #0,d0
malloc21End:
debug '|malloc21 out (err,ptr)=',2,d0,a1
movem.l (sp)+,d1-d3/d5/a2-a4
rts
malloc21Failed:
suba.l a1,a1
bsr getSize
;<d0.l:確保できるサイズの合計
;<d1.l:一度に確保できる最大のサイズ
move.l d1,d0 ;最大のサイズ
or.l #$80000000,d0 ;最上位ビットだけセットする
bra malloc21End
;----------------------------------------------------------------
;ブロックの確保(上位から)
;<d2.l:確保するサイズ
;<d4.l:親プロセスのメモリ管理テーブル
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0=成功,$8xxxxxxx=確保できる最大のサイズ
;>a1.l:0=失敗,0以外=確保したブロックのユーザ領域の先頭
;*d0/a1
malloc22::
movem.l d1-d2/a2-a4,-(sp)
debug '|malloc22 in (size,proc)=',2,d2,d4
cmp.l #LOGICAL_SIZE-1,d2 ;念のため
bls @f
move.l #LOGICAL_SIZE-1,d2
@@: move.l a4,d0 ;先頭のブロック
suba.l a3,a3
malloc22Loop:
cmp.l a5,d0
bcc malloc22Last ;見つからなかった
movea.l d0,a2
tst.b (Tail,a2)
bmi malloc22Next ;ロックされている
bsr splitBlock ;分割してできるブロックのヘッダとサイズを求める
bmi malloc22Next ;分割できない
cmp.l d2,d1 ;サイズが足りているか
blo malloc22Next ;足りない
movea.l a2,a3 ;最後に見つかったブロックのヘッダを更新
malloc22Next:
move.l (Next,a2),d0 ;次のブロックへ
bne malloc22Loop
malloc22Last:
move.l a3,d0 ;最後に見つかったブロック
beq malloc22Failed ;見つからなかった
movea.l a3,a2 ;見つかったブロックのアドレス
move.l (Next,a2),d1 ;末尾+1
beq 1f
cmp.l a5,d1
bls 2f
1: move.l a5,d1
2: sub.l d2,d1
moveq.l #$FFFFFFF0,d0
and.l d0,d1 ;ユーザ領域の先頭
add.l d0,d1 ;新しいヘッダ
movea.l a2,a1 ;分割するブロックのヘッダ
lea.l (User,a2),a3 ;分割するブロックのユーザ領域の先頭
cmp.l a1,d1
beq malloc22FreeBlock ;分割するブロックの長さが0になるとき分割しない
movea.l d1,a1
bsr insertHeader ;ヘッダを挿入する
malloc22FreeBlock:
lea.l (User,a1),a1 ;ユーザ領域の先頭
add.l a1,d2 ;ユーザ領域の末尾+1
move.l d2,(-User+Tail,a1) ;ユーザ領域の末尾+1
move.l d4,(-User+Proc,a1) ;親プロセスのメモリ管理テーブル
moveq.l #0,d0
malloc22End:
debug '|malloc22 out (err,ptr)=',2,d0,a1
movem.l (sp)+,d1-d2/a2-a4
rts
malloc22Failed:
suba.l a1,a1
bsr getSize
;<d0.l:確保できるサイズの合計
;<d1.l:一度に確保できる最大のサイズ
move.l d1,d0 ;最大のサイズ
or.l #$80000000,d0 ;最上位ビットだけセットする
bra malloc22End
;----------------------------------------------------------------
;ブロックの確保(最大ブロックから)
;<d2.l:確保するサイズ
;<d4.l:親プロセスのメモリ管理テーブル
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0=成功,$8xxxxxxx=確保できる最大のサイズ
;>a1.l:0=失敗,0以外=確保したブロックのユーザ領域の先頭
;*d0/a1
malloc23::
movem.l d1-d3/d5/a2-a4,-(sp)
debug '|malloc23 in (size,proc)=',2,d2,d4
cmp.l #LOGICAL_SIZE-1,d2 ;念のため
bls @f
move.l #LOGICAL_SIZE-1,d2
@@: move.l a4,d0 ;先頭のブロック
moveq.l #0,d3 ;見つかった最大のブロックのサイズ
moveq.l #0,d5 ;見つかった最大のブロック
malloc23Loop:
cmp.l a5,d0
bcc malloc23Last ;見つからなかった
movea.l d0,a2
tst.b (Tail,a2)
bmi malloc23Next ;ロックされている
bsr splitBlock ;分割してできるブロックのヘッダとサイズを求める
bmi malloc23Next ;分割できない
cmp.l d2,d1 ;サイズが足りているか
blo malloc23Next ;足りない
cmp.l d3,d1 ;これまでに見つかったブロックのサイズより大きい
bls malloc23Next ;小さいか等しい
move.l d1,d3 ;最大のブロックのサイズを更新
movea.l a1,a3 ;ヘッダを作れる位置を更新
move.l a2,d5 ;見つかったブロックのヘッダを更新
malloc23Next:
move.l (Next,a2),d0 ;次のブロックへ
bne malloc23Loop
malloc23Last:
move.l d5,d0 ;見つかった最大のブロック
beq malloc23Failed ;見つからなかった
movea.l a3,a1 ;新しいヘッダ
movea.l d5,a2 ;見つかったブロックのヘッダ
bsr insertHeader ;ヘッダを挿入する
lea.l (User,a1),a1 ;ユーザ領域の先頭
add.l a1,d2 ;ユーザ領域の末尾+1
move.l d2,(-User+Tail,a1) ;ユーザ領域の末尾+1
move.l d4,(-User+Proc,a1) ;親プロセスのメモリ管理テーブル
moveq.l #0,d0
malloc23End:
debug '|malloc23 out (err,ptr)=',2,d0,a1
movem.l (sp)+,d1-d3/d5/a2-a4
rts
malloc23Failed:
suba.l a1,a1
move.l d3,d0 ;最大のサイズ
or.l #$80000000,d0 ;最上位ビットだけセットする
bra malloc23End
;----------------------------------------------------------------
;ブロックの開放
;<d2.l:開放するブロックのユーザ領域の先頭
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0=成功,-1=ヘッダが見つからない
;*d0
free::
movem.l d2/a1-a2,-(sp)
debug '|free in (ptr)=',1,d2
moveq.l #$FFFFFFF0,d0
add.l d0,d2 ;ヘッダ
bsr searchBlock2 ;ヘッダを探す
bmi freeEnd ;見つからない
;<a2.l:ヘッダ
bsr deleteHeader ;ヘッダを削除する
freeDone:
moveq.l #0,d0
freeEnd:
debug '|free out (err)=',1,d0
movem.l (sp)+,d2/a1-a2
rts
;----------------------------------------------------------------
;特定のプロセスが確保したブロックの開放
; 子プロセスが確保したブロックも開放する
;<d4.l:開放するブロックを確保したプロセスのメモリ管理テーブル
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0(常に成功する)
;*d0
psfree::
movem.l d1/a2,-(sp)
debug '|psfree in (proc)=',1,d4
move.l a4,d0 ;先頭のブロック
psfreeLoop:
cmp.l a5,d0
bcc psfreeEnd ;終わり
movea.l d0,a2
tst.b (Tail,a2)
bmi psfreeNext ;ロックされている
move.l (Next,a2),d1 ;直後
cmp.l (Proc,a2),d4 ;確保したプロセス
bne psfreeNext ;該当しない
bsr deleteHeader ;ヘッダを削除する
move.l d2,-(sp)
move.l d1,-(sp)
move.l a2,d2 ;子プロセス
bsr psfree ;子プロセスが確保したブロックを開放
move.l (sp)+,d1
move.l (sp)+,d2
psfreeNext:
move.l d1,d0
bne psfreeLoop
psfreeEnd:
moveq.l #0,d0
debug '|psfree out (err)=',1,d0
movem.l (sp)+,d1/a2
rts
;----------------------------------------------------------------
;ブロックのサイズ変更
; ブロックは移動しない
; 新しいサイズが0ならばブロックを開放する
;<d2.l:サイズを変更するブロックのユーザ領域の先頭
;<d3.l:新しいサイズ(0=ブロックを開放する)
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0=成功,-1=ヘッダが見つからない,$8xxxxxxx=確保できる最大のサイズ
;*d0
resizeOrFree::
tst.l d3 ;サイズが0ならばブロックを開放する
beq free
;----------------------------------------------------------------
;ブロックのサイズ変更
; ブロックは移動しない
;<d2.l:サイズを変更するブロックのユーザ領域の先頭
;<d3.l:新しいサイズ
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0=成功,-1=ヘッダが見つからない,$8xxxxxxx=確保できる最大のサイズ
;*d0
resize::
movem.l d1-d3/a1-a2,-(sp)
debug '|resize in (ptr,size)=',2,d2,d3
moveq.l #$FFFFFFF0,d0
add.l d0,d2 ;ヘッダ
bsr searchBlock2 ;ヘッダを探す
bmi resizeEnd ;見つからない
;<a2.l:ヘッダ
cmp.l #LOGICAL_SIZE-1,d3 ;オーバーフローさせないため
bls @f
move.l #LOGICAL_SIZE-1,d3
@@: lea.l (User,a2,d3.l),a1 ;新しいユーザ領域の末尾+1
move.l (Next,a2),d0 ;ユーザ領域の末尾+1の最大値
beq 1f
cmp.l a5,d0
bls 2f
1: move.l a5,d0
2: cmpa.l d0,a1 ;入り切るか
bhi resizeFailed ;入り切らない
move.l a1,(Tail,a2) ;ユーザ領域の末尾+1
moveq.l #0,d0
resizeEnd:
debug '|resize out (err)=',1,d0
movem.l (sp)+,d1-d3/a1-a2
rts
resizeFailed:
lea.l (User,a2),a2 ;ユーザ領域の先頭
sub.l a2,d0 ;ヘッダを含まない最大のサイズ
or.l #$80000000,d0 ;最上位ビットだけセットする
bra resizeEnd
;----------------------------------------------------------------
;ブロックのサイズ変更
; ブロックが移動することがある
; 移動するとき新しいブロックは下位から確保する
; 移動してもブロックを確保したプロセスは変化しない
; 新しいサイズが0ならばブロックを開放する
;<d2.l:サイズを変更するブロックのユーザ領域の先頭
;<d3.l:新しいサイズ(0=ブロックを開放する)
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0=成功,-1=ヘッダが見つからない,$8xxxxxxx=確保できる最大のサイズ
;>a1.l:0=失敗,0以外=移動後のブロックのユーザ領域の先頭
;*d0/a1
reallocOrFree::
tst.l d3 ;サイズが0ならばブロックを開放する
beq free
;----------------------------------------------------------------
;ブロックのサイズ変更
; ブロックが移動することがある
; 移動するとき新しいブロックは下位から確保する
; 移動してもブロックを確保したプロセスは変化しない
;<d2.l:サイズを変更するブロックのユーザ領域の先頭
;<d3.l:新しいサイズ
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0=成功,-1=ヘッダが見つからない,$8xxxxxxx=確保できる最大のサイズ
;>a1.l:0=失敗,0以外=移動後のブロックのユーザ領域の先頭
;*d0/a1
realloc::
movem.l d1-d4/a2-a3,-(sp)
debug '|realloc in (ptr,size)=',2,d2,d3
moveq.l #$FFFFFFF0,d0
add.l d0,d2 ;ヘッダ
bsr searchBlock2 ;ヘッダを探す
bmi reallocEnd ;見つからない
;移動せずにサイズを変えてみる
;<d3.l:新しいサイズ
;<a2.l:サイズを変更するブロックのユーザ領域の先頭
cmp.l #LOGICAL_SIZE-1,d3 ;オーバーフローさせないため
bls @f
move.l #LOGICAL_SIZE-1,d3
@@: lea.l (User,a2,d3.l),a1 ;新しいユーザ領域の末尾+1
move.l (Next,a2),d0 ;ユーザ領域の末尾+1の最大値
beq 1f
cmp.l a5,d0
bls 2f
1: move.l a5,d0
2: cmpa.l d0,a1 ;入り切るか
bhi reallocPrevious ;入り切らない
move.l a1,(Tail,a2) ;ユーザ領域の末尾+1
bra reallocDone
;<d3.l:新しいサイズ
;<a2.l:サイズを変更するブロックのユーザ領域の先頭
reallocPrevious:
movea.l a2,a3 ;サイズを変更するブロックのヘッダ
;<a3.l:サイズを変更するブロックのヘッダ
cmpa.l a4,a3
beq reallocFirstBlock ;先頭のブロック
;手前に伸ばしてみる
;<a3.l:サイズを変更するブロックのヘッダ
movea.l (Prev,a3),a2 ;直前のブロックの未使用の領域を求める
;<a2.l:手前のブロック
bsr splitBlock
bmi reallocOtherPlace ;手前にはまったく伸ばせない
;<a1.l:手前のブロックを分割してできるブロックのヘッダ(フリーブロックのときは元のヘッダ)
lea.l (User,a1),a1 ;手前に伸ばした場合のユーザ領域の先頭
move.l (Next,a3),d0 ;サイズを変更するブロックの末尾+1
beq 1f
cmp.l a5,d0
bls 2f
1: move.l a5,d0
2: sub.l a1,d0 ;手前に伸ばした場合のサイズ
cmp.l d3,d0 ;入り切るか
blo reallocOtherPlace ;入り切らない
lea.l (-User,a1),a1 ;手前に伸ばした場合のヘッダ
bsr insertHeader ;新しいヘッダを挿入する
move.l (Proc,a3),(Proc,a1) ;親プロセス
lea.l (User,a1),a1 ;手前に伸ばした場合のユーザ領域の先頭
;<a1.l:新しいブロックのユーザ領域の先頭
;<a3.l:サイズを変更するブロックのヘッダ
bra reallocDelete
;別の場所に移動する
;<d3.l:新しいサイズ
;<a3.l:サイズを変更するブロックのヘッダ
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
reallocOtherPlace:
reallocFirstBlock:
move.l d3,d2 ;新しいサイズ
move.l (Proc,a3),d4 ;親プロセス
bsr malloc20 ;別の場所にブロックを確保する(下位から)
;<d0.l:0=成功,$8xxxxxxx=確保できる最大のサイズ
;<a1.l:0=失敗,0以外=確保したブロックのユーザ領域の先頭
bmi reallocEnd ;確保できない
;元のブロックのヘッダを削除する
;<a1.l:新しいブロックのユーザ領域の先頭
;<a3.l:サイズを変更するブロックのヘッダ
reallocDelete:
move.l a1,d2
;<d2.l:新しいブロックのユーザ領域の先頭
moveq.l #$FFFFFFF0,d4
add.l (Tail,a3),d4
sub.l a3,d4 ;移動するデータのサイズ
;<d4.l:移動するデータのサイズ
movea.l a3,a2
bsr deleteHeader ;元のブロックのヘッダを削除する
;データをコピーする
;<d2.l:新しいブロックのユーザ領域の先頭
;<d4.l:移動するデータのサイズ
;<a3.l:サイズを変更するブロックのヘッダ
tst.l d4 ;移動するデータのサイズ
beq reallocFreeBlock ;移動すべきデータがない
lea.l (User,a3),a3 ;移動元のデータの先頭
movea.l d2,a2 ;移動先のデータの先頭
subq.l #1,d4
lsr.l #4,d4 ;(サイズ-1)/16=(サイズ+15)/16-1
swap.w d4
reallocCopy1:
swap.w d4
reallocCopy0:
move.l (a3)+,(a2)+ ;手前に移動して重なることがあるので順序に注意
move.l (a3)+,(a2)+
move.l (a3)+,(a2)+
move.l (a3)+,(a2)+
dbra d4,reallocCopy0
swap.w d4
dbra d4,reallocCopy1
reallocFreeBlock:
movea.l d2,a1
lea.l (a1,d3.l),a2
move.l a2,(-User+Tail,a1)
reallocDone:
moveq.l #0,d0
reallocEnd:
debug '|realloc out (err,ptr)=',2,d0,a1
movem.l (sp)+,d1-d4/a2-a3
rts
;----------------------------------------------------------------
;確保できるサイズの取得
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:確保できるサイズの合計
;>d1.l:一度に確保できる最大のサイズ
;*d0-d1
getSize::
movem.l d2-d3/a1-a2,-(sp)
debug '|getsize in (top,btm)=',2,a4,a5
moveq.l #0,d2 ;確保できるブロックのサイズの合計
moveq.l #0,d3 ;確保できる最大のブロックのサイズ
move.l a4,d0 ;先頭のブロック
getSizeLoop:
cmp.l a5,d0
bcc getSizeEnd ;終わり
movea.l d0,a2
tst.b (Tail,a2)
bmi getSizeNext ;ロックされている
bsr splitBlock ;分割してできるブロックのヘッダとサイズを求める
bmi getSizeNext ;分割できない
tst.l d1
beq getSizeNext
add.l d1,d2 ;確保できるブロックのサイズの合計を更新
cmp.l d3,d1 ;これまでに見つかった最大のブロックより大きいか
bls getSizeNotLargest ;小さいか等しい
move.l d1,d3 ;最大のブロックのサイズを更新
getSizeNotLargest:
getSizeNext:
move.l (Next,a2),d0 ;次のブロックへ
bne getSizeLoop
getSizeEnd:
move.l d2,d0 ;合計サイズ
move.l d3,d1 ;最大のサイズ
debug '|getsize out (ttl,max)=',2,d0,d1
movem.l (sp)+,d2-d3/a1-a2
rts
;----------------------------------------------------------------
;ヘッダを探す
; ロックされているブロックは検索しない
;<d2.l:ヘッダ
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0=先頭のブロック,1=先頭以外のブロック,-1=失敗
;>a2.l:0=失敗,0以外=ヘッダ
;*d0/a2
searchBlock2::
bsr searchBlock
bmi searchBlock2End ;見つからない
tst.b (Tail,a2)
bpl searchBlock2Done
suba.l a2,a2 ;ロックされている
moveq.l #-1,d0
searchBlock2Done:
tst.l d0
searchBlock2End:
rts
;----------------------------------------------------------------
;ヘッダを探す
; ロックされているブロックも検索する
;<d2.l:ヘッダ
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0=先頭のブロック,1=先頭以外のブロック,-1=失敗
;>a2.l:0=失敗,0以外=ヘッダ
;*d0/a2
searchBlock::
cmp.l a4,d2
bcs searchBlockFailed ;範囲外
cmp.l a5,d2
bcc searchBlockFailed ;範囲外
move.l a4,d0 ;先頭のブロック
searchBlockLoop:
cmp.l a5,d0
bcc searchBlockFailed ;見つからなかった
movea.l d0,a2
tst.b (Tail,a2)
bmi searchBlockNext ;ロックされている
cmpa.l d2,a2
beq searchBlockFound ;見つかった
searchBlockNext:
move.l (Next,a2),d0 ;次のブロックへ
bne searchBlockLoop
searchBlockFailed:
suba.l a2,a2 ;失敗
moveq.l #-1,d0
bra searchBlockEnd
searchBlockFound:
moveq.l #0,d0
cmpa.l a4,a2
beq searchBlockEnd ;先頭のブロック
moveq.l #1,d0
searchBlockEnd:
rts
;----------------------------------------------------------------
;分割してできるブロックのヘッダとサイズを求める
;<a2.l:分割するブロックのヘッダ(無効なアドレスは指定不可)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;>d0.l:0=フリーブロックなので分割しない,1=フリーブロックではないので分割する,-1=失敗
;>d1.l:0=失敗,0以外=分割してできるブロックのサイズ
;>a1.l:0=失敗,0以外=分割してできるブロックのヘッダ(フリーブロックのときは元のヘッダ)
;*d0-d1/a1
splitBlock::
debug '|splitBlock in (header,limit)=',2,a2,a5
lea.l (User,a2),a1 ;ユーザ領域の先頭
move.l (Tail,a2),d0
sub.l a1,d0 ;ユーザ領域のサイズ
bne splitBlockUsed
;フリーブロックのとき
move.l (Next,a2),d1 ;末尾+1
beq 1f
cmp.l a5,d1
bls 2f
1: move.l a5,d1
2: sub.l a1,d1 ;確保できるサイズ
ble splitBlockFailed ;確保できない
movea.l a2,a1
moveq.l #0,d0
debug '|splitBlock out (split,size,header)=',3,d0,d1,a1
rts
;フリーブロックではないとき
splitBlockUsed:
lea.l (15,a1,d0.l),a1 ;ユーザ領域の末尾+1+15
move.l a1,d1
moveq.l #$FFFFFFF0,d0
and.w d0,d1
movea.l d1,a1 ;新しいヘッダ
move.l (Next,a2),d1 ;末尾+1
beq 1f
cmp.l a5,d1
bls 2f
1: move.l a5,d1
2: sub.l a1,d1 ;ヘッダを含めたサイズ
ble splitBlockFailed ;ヘッダも入らない
add.l d0,d1 ;確保できるサイズ
beq splitBlockFailed ;ヘッダしか入らない
moveq.l #1,d0
debug '|splitBlock out (split,size,header)=',3,d0,d1,a1
rts
splitBlockFailed:
suba.l a1,a1
moveq.l #0,d1
moveq.l #-1,d0
debug '|splitBlock out (split,size,header)=',3,d0,d1,a1
rts
;----------------------------------------------------------------
;ヘッダを挿入する
; ブロックを分割してヘッダを作りリストに挿入する
; ユーザ領域のサイズは設定しない
; 親プロセスは設定しない
; 新しいヘッダが分割するブロックのヘッダと同じならば何もしない
;<a1.l:新しいヘッダ
;<a2.l:分割するブロックのヘッダ
;?d0
insertHeader::
cmpa.l a2,a1
beq insertHeaderFreeBlock
move.l a2,(Prev,a1) ;直前を設定
move.l (Next,a2),d0
move.l a1,(Next,a2) ;分割するブロックを縮める
move.l d0,(Next,a1) ;直後を設定
beq insertHeaderLastBlock
exg.l d0,a2
move.l a1,(Prev,a2) ;直後のブロックの直前を設定
exg.l d0,a2
insertHeaderLastBlock:
insertHeaderFreeBlock:
rts
;----------------------------------------------------------------
;ヘッダを削除する
; 確保したプロセスを0にする
; フリーブロックにする
; 先頭のブロックでなければヘッダをリストから取り除く
;<a2.l:削除するヘッダのアドレス(先頭のブロックのヘッダは削除しない)
;<a4.l:メモリ空間の先頭(先頭のブロック)
;?d0/a1
deleteHeader::
clr.l (Proc,a2) ;確保したプロセスを0にする
lea.l (User,a2),a1
move.l a1,(Tail,a2) ;フリーブロックにする
cmpa.l a4,a2
beq deleteHeaderFirstBlock ;先頭のブロック
move.l (Prev,a2),a1 ;直前
move.l (Next,a2),d0 ;直後
move.l d0,(Next,a1) ;直前のブロックの直後を設定
beq deleteHeaderLastBlock
exg.l d0,a2
move.l a1,(Prev,a2) ;直後のブロックの直前を設定
exg.l d0,a2
deleteHeaderLastBlock:
deleteHeaderFirstBlock:
rts
;----------------------------------------------------------------
;自分以外の連続メモリ型サブスレッドのすべてのブロックをロックする
;<a0.l:自分のサブスレッドのスレッド管理テーブル,通常は[$1C54.w].l
lockBlocks::
movem.l d0-d4/a2-a5,-(sp)
move.w $1C58.w,d1 ;スレッド数-1=サブスレッド数
beq lockBlocksEnd ;サブスレッドが存在しない
moveq.l #$80,d2
movea.l $1C50.w,a3 ;メインスレッドのスレッド管理テーブル
move.l (tMemStart,a3),d3 ;メインスレッドのメモリ空間の先頭
move.l (tMemStart,a0),d4 ;自分のメモリ空間の先頭
;<d1.w:スレッド数-1=サブスレッド数(>0)
;<d2.b:$80
;<d3.l:メインスレッドのメモリ空間の先頭
;<d4.l:自分のメモリ空間の先頭
;<a0.l:自分のサブスレッドのスレッド管理テーブル
;<a3.l:メインスレッドのスレッド管理テーブル
subq.w #1,d1 ;サブスレッド数-1
lockBlocksThreadLoop:
lea.l (tSize,a3),a3
;<a3.l:スレッド管理テーブル
tst.l (tProcess,a3)
beq lockBlocksNextThread ;未使用のスレッド
cmpa.l a0,a3
beq lockBlocksNextThread ;自分はロックしない
movea.l (tMemStart,a3),a4
movea.l (tMemEnd,a3),a5
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
cmpa.l d3,a4
beq lockBlocksNextThread ;メインスレッドと同じメモリ空間なのでロックしない
cmpa.l d4,a4
beq lockBlocksNextThread ;自分と同じメモリ空間なのでロックしない
moveq.l #(.not.LOGICAL_MASK)>>24,d0
and.b (Proc,a4),d0
cmp.b #$C0,d0 ;先頭のブロックにサブスレッドのフラグがあれば連続メモリ型
bne lockBlocksNextThread ;サブメモリ型サブスレッドのメモリ空間なのでロックしない
move.l a4,d0
lockBlocksSubLoop:
cmp.l a5,d0
bcc lockBlocksNextThread
movea.l d0,a2
or.b d2,(Tail,a2) ;ロックする
move.l (Next,a2),d0
bne lockBlocksSubLoop
lockBlocksNextThread:
dbra d1,lockBlocksThreadLoop
;
lockBlocksEnd:
movem.l (sp)+,d0-d4/a2-a5
rts
;----------------------------------------------------------------
;ブロックのロックを解除する
; メインスレッドのメモリ空間にあるブロックについてロックされていたら解除する
unlockBlocks::
movem.l d0-d2/a2-a5,-(sp)
move.w $1C58.w,d1 ;スレッド数-1
beq lockBlocksEnd ;サブスレッドが存在しない
moveq.l #$7F,d2
movea.l $1C50.w,a3 ;メインスレッドのスレッド管理テーブル
movea.l (tMemStart,a3),a4
movea.l (tMemEnd,a3),a5
;<a4.l:メインスレッドのメモリ空間の先頭
;<a5.l:メインスレッドのメモリ空間の末尾+1
move.l a4,d0
unlockBlocksLoop:
cmp.l a5,d0
bcc unlockBlocksEnd
movea.l d0,a2
and.b d2,(Tail,a2) ;ロックを解除する
move.l (Next,a2),d0
bne unlockBlocksLoop
unlockBlocksEnd:
movem.l (sp)+,d0-d2/a2-a5
rts
;----------------------------------------------------------------
;実行中のプロセスのメモリ管理テーブルを得る
;>d4.l:実行中のプロセスのメモリ管理テーブル
;*d4
getProc::
move.l ([$1C28.w]),d4 ;実行中のプロセスのメモリ管理テーブル
rts