📄 gmem.asm
字号:
xchg ax,si ; Return original handle
; Set back link to handle in new block
dec si
mov es,si
mov ES:[di].ga_handle,ax
and ch,GA_SEGTYPE
mov ES:[di].ga_flags,ch ; Copy segment type flags to ga_flags
racreate0:
jmp raexit
racreate1:
jmp rafailmem1
raokay:
mov si,bx
add bx,ax ; Compute address of new next header
call galign ; assuming there is room.
; Here if not trying to realloc this block to zero
; ES:0 = arena header of current block
; AX:0 = client address of current block
; CH = lock count of current block
; DX:0 = new next block, based on new requested size
; SI = new requested size of block
mov bx,ES:[di].ga_next ; Get address of current next header
cmp dx,bx ; Are we growing or shrinking?
ja ragrow ; We are growing
rashrink: ; We are shrinking
; Here to shrink a block
; ES:0 = arena header of current block
; BX:0 = arena header of next block
; DX:0 = new next block, based on new requested size
mov si,dx ; SI = new next block
inc dx ; Test for small shrinkage
inc dx
errnz <GA_ALIGN-1>
cmp dx,bx ; Is there enough room from for free block?
jae raoverflow ; No, then no change to make
; Yes, ES:DI = current block, SI=new block
call gsplice ; splice new block into the arena
mov es,si ; ES:DI = new free block
call gmarkfree ; Mark it as free
rasame:
mov ax,h ; Return the same handle
rax: jmp raexit ; All done
raoverflow:
test byte ptr rflags,GA_ZEROINIT ; Zero file extension?
jz rasame ; No, continue
mov cx,bx ; Next heap header
dec cx ; Last paragraph for us
mov bx,si ; Where the new block would have started
call gzero ; zero fill extension
jmp short rasame
; Here to try to grow the current block
; AX:0 = client address of current block
; CH = lock count of current block
; ES:0 = arena header of current block
; BX:0 = arena header of next block
; DX:0 = new next block, based on new requested size
; SI = new requested size of block
ragrow:
mov al,1 ;* first time through
ragrowagain: ;* al == 0 => don't retry
push es ; Save current block address
mov es,bx ; ES = next block address
cmp ES:[di].ga_owner,di ; Is next block free?
jne ragrow1 ; No, can't fit it in
sub dx,bx ; Yes, compute how much of it we need
push si ; See if free block is big enough
push ax ;* save flag
call gcheckfree
pop ax
pop si
jb ragrow2 ; No, can't fit it in
add dx,bx ; Yes, restore new next block address
pop cx ; Discard saved value (gjoin returns it)
mov cx,es ; Yes, save free block address in CX
call gjoin ; and attach to end of current block
test byte ptr rflags,GA_ZEROINIT ; Zero fill extension?
jz ranz ; No, continue
mov bx,cx ; Yes, BX = first paragraph to fill
mov cx,dx ; compute last paragraph to fill
dec cx ; into CX
call gzero ; zero fill extension
ranz:
mov bx,ES:[di].ga_next ; Pick up new next block address
jmp rashrink ; Now shrink block to correct size
ragrow2:
add dx,bx ;* restore dx
; Here to try to move the current block (or grow fixed block in place)
; BX:0 = arena header of next block
; CH = lock count of current block
; DX:0 = new next block, based on new requested size
; (on stack) ES:0 = arena header of current block
; SI = new requested size of block
ragrow1:
pop es ; Recover current block address
push bx
push dx ;* save flags in case we must retry
mov dx,rflags ; get the passed in flags
AssertReset dl,GA_DISCCODE ;* you can not grow fixed code !
mov bx,GA_MOVEABLE ; Determine if okay to move this guy
jcxz ramove1 ; Continue if this handle not locked
test dx,bx ; Locked. Did they say move anyway?
jnz ramove1 ; Yes, go do it
;* * Can't move (i.e. fixed or locked)
jmp short ragrowfixed ;* force grow in place
ramove1:
or dx,bx ; make sure moveable bit set
test h,GA_FIXED ; Is this a moveable handle?
jz ramove2 ; Yes, okay to move
xor dx,bx ; No, clear moveable flag in arg to gsearch
test rflags,bx ; Did they say it's okay to move?
jnz ramove2 ; Yes, proceed
ragrowfixed:
or al,al
jz rafailmem ;* try maximum of twice
push ax
push si
push es
IFDEF REALLOC_FIXED
mov dx,si ;**** over size request M00BUG
cCall gfixedCompact
ELSE ; REALLOC_FIXED
xor dx,dx ; No, get size of largest free block
call gcompact ; AX = size of largest free block
ENDIF ; REALLOC_FIXED
pop es
pop si
pop ax
xor al,al ;* last chance
;* * block can not be moved, but gcompact may have freed sufficient
;* * space.
pop dx
pop bx ;* restore everything to look like ragrow
jmp ragrowagain
rafailmem:
mov bx,h
test bl,GA_FIXED
jnz rafail2
mov bx,[bx].he_address
rafail2: ; BX = client data address
dec bx
mov es,bx ; ES = arena header address
mov ax,es:[di].ga_size ; AX = size of current block
mov es,es:[di].ga_next ; Check following block
cmp es:[di].ga_owner,di ; Is it free?
jne rafailmem0 ; No, continue
add ax,es:[di].ga_size ; Yes, then include it as well
inc ax
rafailmem0:
cmp ax,dx ; Chose the larger of the two
jbe rafailmem1
mov dx,ax
rafailmem1:
xor ax,ax
jmp rax
ramove2:
pop ax
pop ax ;* ignore 2 saved values from ragrow1
mov ax,dx ; AX = allocation flags
mov bx,si ; BX = size of new block
mov cx,si ; CX = owner (use size for now)
call gsearch ; Find block big enough
jz racantmove ; Cant find one, grow in place now?
mov si,h
mov cx,ax
test si,GA_FIXED
jnz ramove3
mov cx,si
mov si,[si].he_address ; SI = old client data address
ramove3:
dec ax
mov es,ax ; ES = destination arena
dec si ; SI = source arena
call gmovebusy ; Call common code to move busy block
mov ax,cx ; Return new handle
raexit:
mov cx,ax
mov sp,bp
pop bp
ret
racantmove:
mov bx,h
test bl,GA_FIXED
jnz racmove1
mov bx,[bx].he_address
racmove1: ; BX = client data address
mov ax,bx
dec bx
mov es,bx ; ES = arena header address
mov bx,rsize
add bx,ax ; Compute address of new next header
call galign ; assuming there is room.
mov bx,ES:[di].ga_next ; Get address of current next header
mov es,bx ; ES = next block address
cmp ES:[di].ga_owner,di ; Is next block free?
jne racmove3 ; No, try to move the current block
sub dx,bx ; Yes, compute how much of it we need
call gcheckfree ; See if free block is big enough
jb racmove3 ; No, try to move the current block
add dx,bx ; Yes, restore new next block address
mov cx,es ; Yes, save free block address in CX
call gjoin ; and attach to end of current block
test byte ptr rflags,GA_ZEROINIT ; Zero fill extension?
jz racmove2 ; No, continue
mov bx,cx ; Yes, BX = first paragraph to fill
mov cx,dx ; compute last paragraph to fill
dec cx ; into CX
call gzero ; zero fill extension
racmove2:
mov bx,ES:[di].ga_next ; Pick up new next block address
jmp rashrink ; Now shrink block to correct size
racmove3:
xor dx,dx ; No, get size of largest free block
call gcompact
mov dx,ax ; DX = size of largest free block
jmp rafailmem
; GFREE - procedure to free a global object
;
; Inputs: DX = global memory object handle
; CX = owner field value to match or zero if dont care
; DS:DI = address of global heap info
;
; Outputs: AX = zero it successful or handle if not
; CX = AX
;
gfree:
push cx
call gdref
pop dx
jz gf2 ; Free handle if object discarded
or dx,dx
jnz gf3
gf1:
call gmarkfree ; No, free the object
gf2:
call hfree ; Free handle
gfx:
mov cx,ax
ret
gf3:
cmp ES:[di].ga_owner,dx
je gf1
mov ax,-1
jmp short gfx
; GLOCK - procedure to increment the lock count of an object
;
; Inputs: BX = handle to global object
; CX = handle table flags and lock count for moveable objects
; DX = segment address of object
; DS:DI = address of master object
;
; Outputs: Updated lock count in handle table entry and CX
; Z flag set if count overflowed.
;
glock:
inc ch ; Increment lock count
jz gl2 ; All done if overflow
mov [bx].he_count,ch ; Update lock count
gl2:
ret
; GUNLOCK - procedure to deccrement the lock count of an object
;
; Inputs: BX = handle to global object
; CX = handle table flags and lock count for moveable objects
; DX = segment address of object
; DS:DI = address of master object
;
; Outputs: CX = 0 if handle already unlocked. non-zero o.w.
; Updated lock count in handle table entry and CX
; Z flag set if count underflowed.
;
gunlock:
dec ch ; Decrement usage count
cmp ch,0FFh-1 ; ff -> fe, 0 -> ff
jae gul1 ; Return if pinned, or was already zero
dec [bx].he_count ; Non-zero update lock count
jnz gul2 ; All done if still non-zero
test cl,GA_DISCARDABLE ; Is this a discardable handle?
jz gul1 ; No, all done
gul1:
xor cx,cx
gul2:
ret ; Non-zero lock count. Return true
SUBRS ENDP
sEnd KERNEL
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -