📄 gwinterf.asm
字号:
;*
;* COW : Character Oriented Windows
;*
;* gwinterf.asm : Global memory allocator - Windows interface procs
.xlist
include kernel.inc
include galloc.inc
.list
IFDEF DEBUG
CheckHeap MACRO n
local ok
cmp fCheckCwHeap,0
je ok
cCall CheckGlobalHeap
or ax,ax
jz ok
push ax
push dx
cCall <far ptr PrintGlobalHeap> ;*!! look at heap on exit
pop dx
pop ax ;* restore ax to see why we died
cCall CowAssertFailed
DB "&n"
DB ":invalid global heap$"
ok:
ENDM
ELSE
CheckHeap MACRO n
ENDM
ENDIF
sBegin DATA
externW <hGlobalHeap,pGlobalHeap>
IFNDEF NOPCODE
externW <$q_mpsnq> ;* HandleTable - 2
ENDIF ;!NOPCODE
IFDEF DEBUG
staticB szThunkFormat, <"Thunk %x: sf=%x, ow=%x, sz=%x, nx=%x",0dh,0ah,0>
globalB fCheckCwHeap,1
ENDIF ;DEBUG
IFDEF WINDOWS_OLD_APP
externW <fWoaPresent>
ENDIF ; WINDOWS_OLD_APP
IFDEF DUAL
IFDEF DEBUG
externW fProtectMode
ENDIF ;DEBUG
ENDIF ;DUAL
sEnd DATA
IFDEF WINDOWS_OLD_APP
externFP <WoaRelease> ;* User supplied
ENDIF ; WINDOWS_OLD_APP
IFDEF DEBUG
externFPublic <_dprintf> ;* in assertsw.c
ENDIF ;DEBUG
sBegin KERNEL
assumes CS,KERNEL
assumes DS,NOTHING ;* DS usually points to MOB
assumes SS,DATA ;* get variables from here
externNP <PatchStackMoved, PatchStackDiscarded>
externNP <PatchThunkMoved, PatchThunkDiscarded> ;* ldthunk.asm
IFDEF DEBUG
externNP <CheckGlobalHeap> ;* lddebug.asm
ENDIF ;DEBUG
IFDEF KEEP_SYMDEB_CODE
externNP <DebugMovedSegment, DebugFreeSegment> ;* lddebug.asm
ENDIF ; KEEP_SYMDEB_CODE
;* * low level subroutines
externNP <galloc,grealloc> ; GMEM.ASM
externNP <gfree> ; GMEM.ASM
externNP <gdref,ghandle,galign> ; GMEM.ASM
externNP <gfindfree> ; GALLOC.ASM
externNP <gcompact> ; GCOMPACT.ASM
externNP <halloc,hthread> ; HANDLE.ASM
PUBLIC genter
PUBLIC gnotify
PUBLIC ghexpand
PUBLIC xhandle
IFDEF DEBPUB
PUBLIC gavail, gbtop
PUBLIC gmemfail, gmemcheck
ENDIF ;DEBPUB
SUBRS PROC NEAR
; Subroutine to enter a critical region for the global heap.
;
; Output: DS:DI = address of GlobalInfo for global heap
;* * NOTE : gi_lrulock is not needed due to simplified LRU
;* * and accordingly gleave is not needed !
;
genter:
mov ds,pGlobalHeap
xor di,di
ret
; Subroutine to convert a 32-bit byte count to a 16-bit paragraph count.
;
; Inputs: AX = allocation flags or -1 if called from GlobalCompact
; BX = stack address of 32-bit unsigned integer
; DX = handle being reallocated or zero
; DS:DI = address of GlobalInfo for global heap
;
; Outputs: AX = updated allocation flags
; BX = #paragraphs needed to contain that many bytes
; CX = owner value to use
; DX = handle being reallocated or zero
;
gbtop:
push dx
mov dx,ss:[bx+2]
mov bx,ss:[bx]
mov cx,4
add bx,15
adc dx,0
jnc gbtop1
dec dx
dec bx
gbtop1:
shr dx,1
rcr bx,1
loop gbtop1
pop dx
inc ax
jz gbtopx ; All done if called from GlobalCompact
dec ax
mov [di].gi_cmpflags,al ; Save flags for gcompact
test dl,GA_FIXED ; Are we reallocating a fixed handle?
jnz gbtop4 ; Yes, then go allocate low
or dx,dx ; Reallocating a moveable handle?
jnz gbtop3a ; Yes, allocate high
test al,GA_MOVEABLE ; Is this a moveable request?
jz gbtop4 ; No, then go allocate low
gbtop3a:
or al,GA_ALLOCHIGH ; Yes, allocate high
cmp [di].gi_reserve,di ; Reserve area for code?
je gbtop4 ; No, all moveable allocated high
test al,GA_DISCCODE ; Yes, is this discardable code?
jnz gbtop4 ; Yes, then allocate high
xor al,GA_ALLOCHIGH ; No, then allocate low
gbtop4:
test ah,HE_DISCARDABLE ; Discard level?
jz gbtop4a
and ah,not HE_DISCARDABLE ; Yes, convert to boolean value
or ah,GA_DISCARDABLE
gbtop4a:
mov cl,GA_SEGTYPE ; Copy segment type bits to handle
and cl,al
or ah,cl ; table flags
;* * Figure out the owner field
or dx,dx ;* reallocating ?
mov cx,ownerData ;* owner for all global data
jz gbtopx ;* new block => global data
;* * use the old owner field
xchg dx,si
mov cx,[si].he_address ;* owner or ps
test [si].he_flags,HE_DISCARDED
jnz owner_discarded ;* owner in cx
;* * we must get ga_owner field from resident block
mov es,cx
mov cx,es:[di].ga_owner ;* old owner field
owner_discarded:
xchg dx,si ;* restore si/dx
gbtopx:
ret
; Subroutine to get the available memory.
;
gavail:
mov byte ptr [di].gi_cmpflags,0
call gcompact
or dx,dx
jz gavail1
jmp gcsize
gavail1:
push dx ; No max yet
mov es,[di].hi_first
gcstat:
cmp es:[di].ga_sig,GA_ENDSIG ; Last block?
je gcstat3 ; Yes all done
mov es,es:[di].ga_next ; Next block
cmp es:[di].ga_owner,di ; Free?
je gcstat0 ; Yes
mov si,es:[di].ga_handle
or si,si ; Fixed?
jz gcstat ; Yes, next block
cmp [si].he_count,0 ; Locked?
jne gcstat ; Yes, next block
test [si].he_flags,GA_DISCARDABLE ; Discardable?
jz gcstat ; No, next block
test es:[di].ga_flags,GA_DISCCODE; No, discardable code?
jnz gcstat ; Yes, next block
gcstat0:
push es ; Save starting point
mov ax,es:[di].ga_size ; Use this size
mov cx,[di].hi_count
gcstat0a:
mov es,es:[di].ga_next ; Next block
cmp es:[di].ga_owner,di ; Free?
je gcstat1 ; Yes, include size
cmp es:[di].ga_sig,GA_ENDSIG ; End of arena?
je gcstat0b ; Yes, handle reserve area
mov si,es:[di].ga_handle
or si,si ; Fixed?
jz gcstat2 ; Yes, stop looking
cmp [si].he_count,0 ; Locked?
jne gcstat2 ; Yes, stop looking
test [si].he_flags,GA_DISCARDABLE ; Discardable?
jz gcstat1a ; No, dont include in count then
test es:[di].ga_flags,GA_DISCCODE; Yes, discardable code?
jz gcstat1 ; No, include in count then
gcstat0b:
mov si,es ; Yes, see if we are trying
sub si,[di].hi_last ; to steal some of the reserve area
neg si
sub si,[di].gi_reserve
inc ax ; add in one arena header
add ax,si ; Adjust amount by reserve area
jz gcstat2
dec ax ; remove one arena header
jmp short gcstat2
gcstat1: ; Free or Discardable
add ax,es:[di].ga_size ; Increase availabe space
inc ax ; by size of this block
gcstat1a: ; Moveable
loop gcstat0a
gcstat2:
pop es ; Back to starting point
cmp ax,dx ; Did we find a bigger block?
jbe gcstat ; No, then look again
mov dx,ax ; Yes, remember size
pop ax
push es ; ...and block
jmp gcstat
gcstat3:
pop es
mov ax,dx
gcsize:
or ax,ax ; zero mem available?
jz gcfinal ; yes, return 0
dec ax ; Dont be too exact
jz gcfinal
dec ax
gcfinal:
and al,GA_MASK ; round down to nearest alignment
xor dx,dx
ret
;********** gnotify **********
; Subroutine to update all info if a global object moved / discarded
;
; Inputs: AL = message code (GN_MOVE, GN_DISCARD)
; BX = handle
; CX = optional argument (new ps, discard flags)
;* DX = original owner field
;* DS = pGlobalHeap
;
; Outputs: n/a
;
; Destroys: AX,BX,CX,DX,ES
;
gnotify:
IFDEF DEBUG
;* * Test for valid owner
or dh,dh
jz ok_notify_owner ;* code segment
cmp dx,ownerData
jz ok_notify_owner ;* data segment
cmp dx,-1
jz ok_notify_owner ;* master object
bad_notify_owner:
cCall CowAssertFailed
DB "gnotify : bad owner$"
ok_notify_owner:
ENDIF ;DEBUG
xor ah,ah
push si
push di
IFNDEF NOPCODE
Save <ax,bx,cx,dx>
cCall FixHandleTable
ENDIF ;NOPCODE
mov di,cx ;* di = new ps / discard flags
mov cx,dx ;* cx = owner
AssertReset bl,GA_FIXED ;* MUST BE MOVEABLE
;* never discard FIXED objects
mov si,[bx].he_address
AssertNe si,0 ;* the old block must exist
Assert <GN_MOVE EQ 1>
dec ax
jnz notify_discard
;* * MOVING :
AssertNe di,0 ;* di = new destination ps
mov [bx].he_address,di ;* update handle address
IFDEF KEEP_SYMDEB_CODE
Save <cx>
cCall DebugMovedSegment,<si,di>
ENDIF ; KEEP_SYMDEB_CODE
;* * Test to see if we moved a code segment
or ch,ch ;* upper byte zero for CODE
jnz notify_move_data
;* * moving code
Save <cx>
cCall PatchThunkMoved,<cx,di>
cCall PatchStackMoved,<cx,si,di>
jmp short notify_exit
notify_move_data:
;* * Test to see if MOB moved
mov ax,ds
cmp ax,si ; Did we move DS?
jne notify_exit ; No, continue
;* * We have moved the Master Object
push di ; update DS pointer.
pop ds
mov pGlobalHeap,ds ;* and the master object pointer
jmp short notify_exit
notify_discard:
Assert <GN_DISCARD EQ 2>
AssertEq ax,1
;* * DISCARDING :
mov [bx].he_address,0 ;* discarded
IFDEF KEEP_SYMDEB_CODE
Save <cx>
cCall DebugFreeSegment,<si>
ENDIF ; KEEP_SYMDEB_CODE
or ch,ch ;* upper byte zero for CODE
jnz notify_exit ;* discarding data
;* * Discarding code
Save <cx>
cCall PatchThunkDiscarded,<cx>
cCall PatchStackDiscarded,<cx,si>
notify_exit:
pop di
pop si
ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -