TITLE GMEM - Register interface to global memory allocator .xlist include kernel.inc include tdb.inc include protect.inc .list externFP SetSelectorLimit DataBegin externB fBooting ;externW curTDB ;externW pGlobalHeap externW SelTableStart externW SelTableLen ifdef WOW globalB fInAlloc, 0 globalW UserSelArray, 0 globalW SelectorFreeBlock, 0 endif DataEnd sBegin CODE assumes CS,CODE externNP DPMIProc DPMICALL MACRO callno mov ax, callno call DPMIProc ENDM ;externW gdtdsc externNP gsplice externNP gjoin externNP gzero externNP gsearch externNP gmarkfree ;externNP gcheckfree externNP gmovebusy externNP gcompact externNP glruadd externNP glrudel externNP glrutop externNP gnotify externNP henum externNP is_there_theoretically_enough_space externNP can_we_clear_this_space externNP get_physical_address externNP set_physical_address externNP alloc_sel externNP alloc_data_sel_above externNP pdref externNP set_sel_limit externNP mark_sel_PRESENT externNP mark_sel_NP externNP free_sel externNP FreeSelArray externNP GrowSelArray externNP get_arena_pointer externNP get_temp_sel externNP get_blotto ;externNP get_sel externNP PreallocSel externNP AssociateSelector externNP GetAccessWord externNP SetAccessWord externFP set_discarded_sel_owner if ROM externNP IsROMObject endif if KDEBUG externNP CheckGAllocBreak endif ;-----------------------------------------------------------------------; ; galign ; ; ; ; Aligns the size request for a global item to a valid para boundary. ; ; ; ; Arguments: ; ; BX = #paras ; ; CF = 1 if #paras overflowed. ; ; ; ; Returns: ; ; DX = #paras aligned, to next higher multiple of 2 ; ; ; ; Error Returns: ; ; DX = FFFFh ; ; ; ; Registers Preserved: ; ; all ; ; Registers Destroyed: ; ; none ; ; Calls: ; ; nothing ; ; History: ; ; ; ; Mon Sep 22, 1986 03:14:56p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------; cProc galign, cBegin nogen jc align_error ; Overflow occur? lea dx,[bx+GA_ALIGN] ; No, add alignment amount and dl,GA_MASK ; ...modulo alignment boundary cmp dx,bx ; Test for overflow jnb align_exit ; Yes, continue align_error: mov dx,0FFFFh ; Return impossible size align_exit: ret cEnd nogen ;-----------------------------------------------------------------------; ; galloc ; ; ; ; Allocates global memory. ; ; ; ; Arguments: ; ; AX = allocation flags ; ; BX = #paragraphs ; ; CX = owner field ; ; DS:DI = address of global heap info ; ; ; ; Returns: ; ; AX = handle to object or zero ; ; BX = size of largest free block if AX = 0 ; ; CX = AX ; ; ; ; Error Returns: ; ; DX = 0 ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ; ; Calls: ; ; gsearch ; ; ghalloc ; ; glruadd ; ; gmarkfree ; ; History: ; ; ; ; Wed Jun 24, 1987 03:04:32a -by- David N. Weise [davidw] ; ; Added support for Global Notify. ; ; ; ; Mon Sep 22, 1986 02:38:19p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------; AccessWord dw DSC_DATA+DSC_PRESENT dw (DSC_DISCARDABLE SHL 8) + DSC_DATA+DSC_PRESENT dw DSC_CODE+DSC_PRESENT dw (DSC_DISCARDABLE SHL 8) + DSC_CODE+DSC_PRESENT dw DSC_DATA+DSC_PRESENT dw (DSC_DISCARDABLE SHL 8) + DSC_DATA+DSC_PRESENT dw DSC_DATA+DSC_PRESENT dw (DSC_DISCARDABLE SHL 8) + DSC_DATA+DSC_PRESENT cProc galloc, cBegin nogen if ROM and KDEBUG if 1 %out Remove me someday endif or cx,cx ; had trouble with owner == 0 jnz @f ; too many times! Debug_Out "ROMKRNL: galloc with owner = 0!" @@: endif if KDEBUG test al,GA_DISCCODE ; If discardable code, allow alloc jnz @F call CheckGAllocBreak jnc @F jmp gaerr @@: endif or bx,bx ; Allocating zero size? jnz @F jmp allocate_zero_size @@: ifdef WOW push ds SetKernelDS mov fInAlloc, 1 mov SelectorFreeBlock, 0 mov UserSelArray, 0 UnSetKernelDS pop ds endif call gsearch ; Search for block big enough jnz bleech mov cx, ax ifdef WOW push ds SetKernelDS mov fInAlloc, 0 mov SelectorFreeBlock, 0 mov UserSelArray, 0 UnSetKernelDS pop ds endif ret ; Done, if couldn't get enough bleech: mov es,ax push dx ifdef WOW push ds SetKernelDS mov fInAlloc, 0 mov SelectorFreeBlock, 0 mov ax, UserSelArray UnSetKernelDS pop ds or ax, ax jnz got_Sel mov ax, es old_path: endif mov bx,dx cCall get_physical_address, add ax,10h ; Calculate address of object adc dx,0 mov cx, ax ; in DX:CX and bx, ((GA_CODE_DATA+GA_DISCARDABLE) shl 8) + GA_DGROUP or bl, bh xor bh, bh shl bx, 1 mov ax, cs:AccessWord[bx] ; Pick up access rights for selector cCall alloc_sel, got_sel: pop dx or ax, ax jz short gaerr1 cCall AssociateSelector, test dl,GA_MOVEABLE ; Is this a moveable object? jnz moveable test dh, GA_DISCARDABLE ; We have a fixed block jnz not_moveable ; Not interested in discardable blocks mov bx, ax %out THIS IS WRONG!!! ifdef WOW ; the following dpmicall is basically a NOP. so just ; avoid the call altogether. ; - Nanduri Ramakrishna else mov ax, 4 ; Lock the WIN386 pages ;bugbugbugbug DPMICALL ax ; int 31h mov ax, bx endif jmps not_moveable moveable: mov es:[di].ga_count,0 ; Initialize lock count to 0 StoH al ; Mark as moveable block not_moveable: mov es:[di].ga_handle,ax ; Set handle in arena mov bx, ax ; AX and BX handle call glruadd ; Yes, Add to LRU chain mov cx, ax ret allocate_zero_size: test al,GA_MOVEABLE ; Yes, moveable? jz gaerr ; No, return error (AX = 0) mov bx, ax and bx, ((GA_CODE_DATA+GA_DISCARDABLE) shl 8) + GA_DGROUP or bl, bh ; Above bits are exclusive xor bh, bh shl bx, 1 mov ax, cs:AccessWord[bx] ; Pick up access rights for selector and al, NOT DSC_PRESENT ; These are NOT present xor dx, dx ; Base of zero for now cCall alloc_sel, or ax, ax jz gaerr cCall AssociateSelector, StoH al ; Handles are RING 2 mov bx,ax ga_exit: mov cx, ax ret gaerr1: xor si,si call gmarkfree gaerr: KernelLogError DBF_WARNING,ERR_GALLOC,"GlobalAlloc failed" xor dx,dx ; DX = 0 means NOT out of memory xor ax,ax ; Return AX = 0 to indicate error jmps ga_exit cEnd nogen ;-----------------------------------------------------------------------; ; grealloc ; ; ; ; Reallocates the given global memory object. ; ; ; ; Arguments: ; ; AX = allocation flags ; ; BX = #paragraphs for new size ; ; CX = new owner field value ; ; DX = existing handle ; ; DS:DI = address of global heap info ; ; ; ; Returns: ; ; AX = handle to object or zero ; ; DX = size of largest free block if AX = 0 ; ; CX = AX ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; SI ; ; ; ; Calls: ; ; ; ; History: ; ; ; ; Mon 05-Feb-1990 21:07:33 -by- David N. Weise [davidw] ; ; Got rid of the spagetti code. ; ; ; ; Mon Sep 22, 1986 10:11:48a -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------; cProc grealloc,, localW rflags localW hMem localW oldhMem localW owner localW rsize localW canmove localB locked localB mflags localW numsels cBegin mov rflags,ax mov hMem,dx mov oldhMem,dx mov owner,cx mov rsize,bx call pdref mov dx,bx ; save owner if discarded mov word ptr mflags,cx mov bx,rsize jnz handle_ok jmp racreate ; Do nothing with 0, free or discarded handles handle_ok: test byte ptr rflags,GA_MODIFY ; Want to modify table flags? jnz ramodify ; Yes go do it or bx,bx ; Are we reallocing to zero length? jz radiscard jmp ra_shrink_grow ; No, continue ;-----------------------------------------------------------------------; ; Here to discard object, when reallocating to zero size. This ; ; feature is only enabled if the caller passes the moveable flag ; ;-----------------------------------------------------------------------; radiscard: or ch,ch ; Is handle locked? jnz radiscard_fail test byte ptr rflags,GA_MOVEABLE ; Did they want to discard? jz radiscard_fail ; No, then return failure. mov al,GN_DISCARD ; AL = discard message code xor cx,cx ; CX = means realloc mov bx,hMem ; BX = handle push es call gnotify ; See if okay to discard pop es jz radiscard_fail ; No, do nothing call glrudel ; Yes, Delete handle from LRU chain cCall mark_sel_NP, xor si,si call gmarkfree ; Free client data mov ax,0 ; don't change flags jz @F ; Return NULL if freed a fixed block mov bx, si mov ax,hMem ; Return original handle, except @@: jmp raexit ; GlobalLock will now return null. radiscard_fail: KernelLogError DBF_WARNING,ERR_GREALLOC,"GlobalReAlloc failed" xor dx,dx xor ax,ax jmp raexit ;-----------------------------------------------------------------------; ; There are 2 attributes that can change: ; ; 1) Fixed -> moveable - added in 2.x, probably not used by many ; ; 2) nondiscardable <-> discardable ; ; 3) non-shared -> shared, i.e., the owner changes ; ;-----------------------------------------------------------------------; ramodify: if ROM cCall IsROMObject, ; If someone is trying to modify a jc ramod_done ; ROM object, just pretend it worked endif mov ax,rflags ; Get new flags mov dx,owner ; Get new owner field value or si,si ; Moveable object? jnz is_moveable ; yes, change discardability/owner test al,GA_MOVEABLE ; Make fixed into moveable? jz ra_mod_owner ; Fixed, can ONLY change owner push ax push cx mov ax, es:[di].ga_handle ; Turn selector into handle StoH al mov bx, ax mov es:[di].ga_handle, ax mov es:[di].ga_count, 0 ; 0 lock count for new movable obj pop cx pop ax mov si,bx ; fall through to code that makes [non]discardable and may change owner is_moveable: call glrudel ; Remove from lru chain, even though push bx mov bx, ax cCall GetAccessWord, and ah, not DSC_DISCARDABLE ; Clear discard bit test bh, GA_DISCARDABLE jz ra_notdiscardable or ah, DSC_DISCARDABLE ra_notdiscardable: cCall SetAccessWord, mov ax, bx pop bx test cl,HE_DISCARDED ; Is this a discarded handle? jz ramod1 ; No, continue test ah,GA_SHAREABLE ; Only change owner if making shared jz ramod_done push bx push es mov bx, si mov es, dx call set_discarded_sel_owner pop es pop bx jmps ramod_done ramod1: call glruadd ; only adds to list IF object is disc ra_mod_owner: test ah,GA_SHAREABLE ; Only change owner if making shared jz ramod_done mov es:[di].ga_owner,dx ; Set new owner value ramod_done: mov ax,hMem ; Return the same handle jmp raexit ; All done ;-----------------------------------------------------------------------; ; We are here to grow a 0 sized object up big. ; ;-----------------------------------------------------------------------; racreate: test cl,HE_DISCARDED ; Is this a discarded handle? jz racre_fail ; No, return error or bx,bx ; Are we reallocing to zero length? mov ax,hMem jz racre_done ; Yes, return handle as is. if KDEBUG test cl,GA_DISCCODE ; if discardable code, allow realloc jnz @F call CheckGAllocBreak jc racre_fail @@: endif mov ax,GA_MOVEABLE ; Reallocating a moveable object or ax,rflags ; ...plus any flags from the caller and cl,GA_SEGTYPE or al,cl mov cx,dx ; get owner push ds SetKernelDS ife ROM cmp fBooting, 1 ; Allocate high while booting je @F endif test al,GA_DISCCODE ; Discardable code segment? jz ranotcode @@: or al,GA_ALLOCHIGH ; Yes, allocate high ranotcode: pop ds UnSetKernelDS mov [di].gi_cmpflags,al ; Save flags for gcompact and [di].gi_cmpflags,CMP_FLAGS push si ; save handle call gsearch ; Find block big enough pop si ; restore existing handle jz racre_fail1 mov bx,ax ; save new block cCall mark_sel_PRESENT, ; sets a new set of sels if necessary or si,si jz racre_worst_case xchg ax,si ; Return original/new handle ; Set back link to handle in new block cCall AssociateSelector, mov es,si mov es:[di].ga_handle,ax mov es:[di].ga_count,0 call glruadd ; Add to LRU chain jmps racre_done racre_worst_case: mov es,bx ; Free block if no handles available. xor si,si call gmarkfree racre_fail: xor dx,dx racre_fail1: push dx KernelLogError DBF_WARNING,ERR_GREALLOC,"GlobalReAlloc failed" pop dx xor ax,ax ; Yes, return failure racre_done: jmp raexit ;-----------------------------------------------------------------------; ; This is what most would have thought is the guts of GlobalRealloc. ; ;-----------------------------------------------------------------------; ra_shrink_grow: if KDEBUG test es:[di].ga_flags,GA_DISCCODE jz ok INT3_WARN ; GlobalRealloc of discardable code! ok: endif cmp bx,es:[di].ga_size jz rasame add bx,1 ; add room for header, set carry bit jc ra_s_g_fail call galign ; assuming there is room. dec dx ; Exclude header again mov si,dx ; 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 = new requested size of block ; SI = new requested size of block mov bx,es:[di].ga_next ; Get address of current next header cmp si,es:[di].ga_size ; Are we growing or shrinking? ja raextend ; We are growing call rashrink rasame: mov ax,hMem ; Return the same handle jmp raexit ; All done raextend: test rflags,GA_DISCCODE ; Not allowed to grow a disccode seg jnz ra_s_g_fail if KDEBUG call CheckGAllocBreak jc ra_s_g_fail endif push ax call GrowSelArray mov numsels, cx ; Save how many to free just in case mov cx, ax pop ax jcxz ra_s_g_fail ; Didn't get selectors mov hMem, cx ; We have a new handle call ragrow jnc rasame test mflags,GA_DISCARDABLE ; if discardable, just stop now jz ramove ; since it might get discarded! ra_s_g_fail: KernelLogError DBF_WARNING,ERR_GREALLOC,"GlobalReAlloc failed" xor ax,ax ; Yes, return failure xor dx,dx jmp raexit ; Here to try to move the current block ; AX = client address of current block ; ES:0 = arena header of current block ; CH = lock count of current block ; SI = new requested size of block ramove: mov canmove, 1 mov dx,rflags ; get the passed in flags test dx,GA_MOVEABLE ; Did they say OK to move jnz ramove1 ; Yes, try to move even iflocked or fixed cmp locked, 0 ; Locked? jnz racompact ; Continue if this handle not locked ; yes, try to find space to grow in place or dx,GA_MOVEABLE ; If moveable, make sure bit set. test hMem,GA_FIXED ; Is this a moveable handle? jz ramove2 ; Yes, okay to move racompact: xor dx,dx ; No, get size of largest free block call gcompact jmps racantmove ramove1: test hMem, GA_FIXED jz ramove2 and dx, NOT GA_MOVEABLE ramove2: mov ax,dx ; AX = allocation flags mov bx,si ; BX = size of new block call PreAllocSel ; for gmovebusy later jz racantmove mov cx,bx ; CX = owner (use size for now) call gsearch ; Find block big enough jz racantmove ; Cant find one, grow in place now? mov cx,hMem push ax cCall get_arena_pointer, ;;; mov es,ax ;;; mov es,es:[di].ga_next ; get real arena header ;;; mov si,es:[di].ga_prev mov si, ax ; SI = source arena pop es ; ES = destination arena call gmovebusy ; Call common code to move busy block ; (AX destroyed) push bx push cx mov bx, es:[di].ga_size xor cx,cx REPT 4 shl bx,1 rcl cx,1 ENDM cCall set_sel_limit, pop cx pop bx mov ax,cx ; Return new handle raexit: mov cx,ax jcxz ra_done test hMem,GA_FIXED ; Is this a moveable object? jz ra_done ; no, don't lock mov bx, ax ifdef WOW ; the following dpmicall is basically a NOP. so just ; avoid the call altogether. ; - Nanduri Ramakrishna else mov ax, 4 ; Lock the WIN386 pages ; bugbugbugbug DPMICALL ax ; int 31h mov ax, bx endif jmps ra_done racantmove: mov dx, hMem call pdref mov bx,rsize add bx,1 ; add room for header, set carry bit call galign ; assuming there is room. dec dx ; Exclude header again mov si,dx mov bx,es:[di].ga_next ; Get address of current next header call ragrow jc racmove3 jmp rasame racmove3: xor dx,dx ; No, get size of largest free block call gcompact mov dx,ax ; DX = size of largest free block rafailmem: cCall get_arena_pointer, mov es,ax 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 ; Choose the larger of the two jbe rafailmem1 mov dx,ax rafailmem1: push dx ; Save DX KernelLogError DBF_WARNING,ERR_GREALLOC,"GlobalReAlloc failed" pop dx ; RestoreDX xor ax,ax jmps raexit ra_done: ; 3 feb 1990, this push ax ; is a last minute hack push bx push cx push dx mov bx,hMem mov cx,oldhMem ife RING-1 inc bx and bl,NOT 1 inc cx and cl,NOT 1 else or bl, 1 or cl, 1 endif cmp bx,cx ; was a new selector allocated? jz ra_really_done ; or ax,ax ; figure out if we suceeded jz ra_ra cCall FreeSelArray, ; free the original selector jmps ra_really_done ra_ra: cCall get_physical_address, cCall set_physical_address, cCall get_arena_pointer, INT3_ANCIENT cCall AssociateSelector, push ax mov cx, numsels mov ax, hMem fsloop: cCall free_sel, add ax, 8 loop fsloop pop es mov ax,oldhMem mov es:[ga_handle],ax cCall AssociateSelector, ra_really_done: pop dx pop cx pop bx pop ax cEnd ;-----------------------------------------------------------------------; ; rashrink ; ; ; ; Shrinks the given block ; ; ; ; Arguments: ; ; Here to shrink a block ; ; ES:0 = arena header of current block ; ; DX = new requested size of block ; ; SI = new requested size of block ; ; ; ; Returns: ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ALL but DS, DI ; ; ; ; Calls: ; ; gsplice ; ; gmarkfree ; ; ; ; History: ; ; ; ; Tue 06-Feb-1990 01:03:54 -by- David N. Weise [davidw] ; ; I got no clue what the history of this thing is, all I know is ; ; that I got to fix it fast to prevent selector leak. ; ;-----------------------------------------------------------------------; assumes ds,nothing assumes es,nothing cProc rashrink, cBegin nogen mov bx,si xor cx,cx REPT 4 shl bx,1 rcl cx,1 ENDM mov ax,es:[di].ga_handle or ax,ax jz ra_free ; !! the following was added Tue 06-Feb-1990 01:47:12 ; it doesn't belong here really but it is the only way to ; prevent selector leak. push bx push cx push si mov si,ax cCall GetAccessWord, mov bl, ah mov ax, si and bl, 0Fh ; Current hlimit inc bl ; number of selectors there now mov cx,dx add cx, 0FFFh rcr cx, 1 ; 17 bitdom shr cx, 11 sub bl, cl jbe ignore_this_shi xor bh,bh ; BX = number of selectors to free shl cx,3 .errnz SIZE DscPtr - 8 add cx,si ; CX = selector to start to free xchg bx,cx @@: cCall free_sel, add bx,SIZE DscPtr loop @B ignore_this_shi: pop si pop cx pop bx ; end of shi Handle_To_Sel al cCall set_sel_limit, ra_free: inc dx ; Test for small shrinkage inc dx .errnz GA_ALIGN - 1 cmp dx,es:[di].ga_size ; Enough room from for free block? ja rashrunk ; No, then no change to make ; !! why isn't the PreAllocSel done before the set_sel_limit? ; Because it belongs with the 'gsplice'. call PreallocSel ; Must be able to get selector jz rashrunk ; Yes, ES:DI = cur block, SI=new block inc si ; Include header in size of block call gsplice ; splice new block into the arena mov es,si ; ES:DI = new free block xor si,si call gmarkfree ; Mark it as free rashrunk: ret cEnd nogen ;-----------------------------------------------------------------------; ; ragrow ; ; ; ; Tries to grow the given global memory object in place ; ; ; ; Arguments: ; ; AX:0 = client address of current block ; ; ES:0 = arena header of current block ; ; BX:0 = arena header of next block ; ; DX = SI = new requested size of block ; ; ; ; Returns: ; ; CY = 0 Success ; ; ; ; CY = 1 Failed ; ; ES preserved ; ; DX contains free memory required ; ; ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ALL but DS, DI ; ; ; ; Calls: ; ; is_there_theoretically_enough_space ; ; can_we_clear_this_space ; ; gjoin ; ; gzero ; ; rashrink ; ; ; ; History: ; ; ; ; Mon 05-Sep-1988 20:10:15 -by- David N. Weise [davidw] ; ; Made ragrow be more intelligent by trying to extend into moveable ; ; blocks. ; ;-----------------------------------------------------------------------; cProc ragrow, cBegin nogen push si push es ; Save current block address sub dx, es:[di].ga_size ; compute amount of free space wanted mov es,bx ; ES = next block address mov cx,[di].hi_count push cx push es call is_there_theoretically_enough_space pop es pop cx cmp ax,dx jb ragx call can_we_clear_this_space jz ragx pop cx ; clear the stack pop si push si call gjoin ; and attach to end of current block pop si ; (will free a selector) test byte ptr rflags,GA_ZEROINIT ; Zero fill extension? jz ranz ; No, continue mov bx, dx ; number of paragraphs to fill mov dx, si ; New size of block sub dx, bx ; Old size of block inc dx ; Paragraph offset of where to zero cCall alloc_data_sel_above, push bx push ax ; set the limit really big push es cCall SetSelectorLimit, pop es pop ax pop cx ; Number of paragraphs to zero mov bx, ax ; Selector to fill call gzero ; zero fill extension cCall free_sel, ranz: mov dx, si mov bx,es:[di].ga_next ; Pick up new next block address call rashrink ; Now shrink block to correct size clc ret ragx: pop es ; Recover current block address pop si stc ret cEnd nogen ;-----------------------------------------------------------------------; ; gfree ; ; ; ; Frees a global object. ; ; ; ; Arguments: ; ; DX = global memory object handle ; ; CX = owner field value to match or zero if dont care ; ; DS:DI = address of global heap info ; ; ; ; Returns: ; ; AX = 0 ; ; CX = 0 ; ; ; ; Error Returns: ; ; AX = -1 ; ; CX = -1 ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ? ; ; Calls: ; ; gdref ; ; free_object ; ; hfree ; ; ; ; History: ; ; ; ; Sat Sep 20, 1986 11:48:38a -by- David N. Weise [davidw] ; ; Added this nifty comment block and restructured. ; ;-----------------------------------------------------------------------; cProc gfree, cBegin nogen push cx call pdref pop dx jz object_discarded call free_object jmps gfree_exit object_discarded: cCall AssociateSelector, cCall FreeSelArray, xor ax,ax ;!!! just for now force success gfree_exit: mov cx,ax ret cEnd nogen ;-----------------------------------------------------------------------; ; free_object ; ; ; ; Arguments: ; ; DX = owner field value to match or zero if dont care ; ; DS:DI = address of global heap info ; ; ES:DI = address of arena header ; ; ; ; Returns: ; ; AX = 0 ; ; ; ; Error Returns: ; ; AX = -1 ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ; ; Calls: ; ; glrudel ; ; gmarkfree ; ; hfree ; ; History: ; ; ; ; Sat Sep 20, 1986 02:59:06p -by- David N. Weise [davidw] ; ; Moved it from gfree. ; ;-----------------------------------------------------------------------; cProc free_object, cBegin nogen or dx,dx jz free_it cmp es:[di].ga_owner,dx je free_it mov ax,-1 jmps free_object_exit free_it: call glrudel ; delete object from LRU chain xor si,si call gmarkfree ; free the object cCall AssociateSelector, cCall FreeSelArray, xor ax,ax ;!!! just for now force success free_object_exit: ret cEnd nogen ;-----------------------------------------------------------------------; ; free_handle ; ; ; ; Frees the given handle. ; ; ; ; Arguments: ; ; DS:SI = handle table entry address ; ; ; ; Returns: ; ; AX = 0 ; ; CX = AX ; ; ; ; Error Returns: ; ; AX = -1 ; ; ; ; Registers Preserved: ; ; BX ; ; ; ; Registers Destroyed: ; ; ? ; ; Calls: ; ; hfree ; ; History: ; ; ; ; Sat Sep 20, 1986 02:30:32p -by- David N. Weise [davidw] ; ; Moved it from gfree. ; ;-----------------------------------------------------------------------; ;cProc free_handle, ;cBegin nogen ; xor ax,ax ; or si,si ; jz free_handle_exit ; push bx ; mov bx,si ; call hfree ; pop bx ;free_handle_exit: ; ret ;cEnd nogen ;-----------------------------------------------------------------------; ; gfreeall ; ; ; ; Frees all global objects that belong to the given owner. It first ; ; loops through the global heap freeing objects and then loops through ; ; the handle table freeing handles of discarded objects. ; ; ; ; Arguments: ; ; DX = owner field value to match ; ; DS:DI = address of global heap info ; ; ; ; Returns: ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; CX,ES,SI ; ; ; ; Calls: ; ; free_object ; ; henum ; ; hfree ; ; ; ; History: ; ; ; ; Fri Sep 19, 1986 05:46:52p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------; cProc gfreeall, cBegin nogen mov es,[di].hi_first ; ES:DI points to first arena entry mov cx,[di].hi_count ; CX = #entries in the arena free_all_objects: push cx call free_object ; Free object if matches owner pop cx mov es,es:[di].ga_next ; Move to next block loop free_all_objects ; may go extra times, as CX does not track coalescing done by gfree, ; but no big whoop push ax push bx push di SetKernelDS es mov si, SelTableStart mov cx, SelTableLen shr cx, 1 mov di, si smov es, ds UnSetKernelDS es free_all_handles_loop: mov ax, dx repne scas word ptr es:[di] ; Isn't this easy? jne short we_be_done lea bx, [di-2] sub bx, si shl bx, 2 or bl, SEG_RING if KDEBUG lsl ax, bx cmp ax, dx je @F INT3_ANCIENT @@: endif cCall GetAccessWord, test al,DSC_PRESENT ; segment present? jnz short free_all_handles_loop ; yes, not a handle test ah,DSC_DISCARDABLE ; discardable? jz short free_all_handles_loop ; no, nothing to free cCall free_sel, mov word ptr [di-2], 0 ; Remove owner from table jcxz we_be_done jmps free_all_handles_loop we_be_done: pop di pop bx pop ax gfreeall_done: ret cEnd nogen ;-----------------------------------------------------------------------; ; glock ; ; ; ; Increment the lock count of an object in handle table entry ; ; ; ; Arguments: ; ; BX = handle to global object ; ; CH = handle table flags ; ; CL = lock count for moveable objects ; ; DX = segment address of object ; ; DS:DI = address of master object ; ; ES:DI = arena header ; ; ; ; Returns: ; ; CX = updated lock count ; ; DX = pointer to client area ; ; ; ; Error Returns: ; ; ZF = 1 if count overflowed. ; ; ; ; Registers Preserved: ; ; AX ; ; ; ; Registers Destroyed: ; ; ; ; Calls: ; ; nothing ; ; History: ; ; ; ; Fri Sep 19, 1986 05:38:57p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------; cProc glock, cBegin nogen push ax inc ch ; Increment lock count jz overflow ; All done if overflow mov es:[di].ga_count,ch ; Update lock count glockerror: overflow: pop ax ret cEnd nogen ;-----------------------------------------------------------------------; ; gunlock ; ; ; ; Decrement the lock count of an object. ; ; ; ; Arguments: ; ; BX = handle to global object ; ; CH = handle table flags ; ; CL = lock count for moveable objects ; ; CX = handle table flags and lock count for moveable objects ; ; DS:DI = address of master object ; ; ES:DI = arena header ; ; ; ; Returns: ; ; CX = updated lock count, no underflow ; ; ; ; Registers Preserved: ; ; ; ; Registers Destroyed: ; ; ; ; Calls: ; ; glrutop ; ; History: ; ; ; ; Fri Sep 19, 1986 04:39:01p -by- David N. Weise [davidw] ; ; Added this nifty comment block. ; ;-----------------------------------------------------------------------; cProc gunlock, cBegin nogen push ax mov ax,bx dec ch ; Decrement usage count cmp ch,0FFh-1 ; ff -> fe, 0 -> ff jae count_zero ; Return if pinned, or was already 0 dec es:[di].ga_count ; Non-zero update lock count jnz count_positive ; All done if still non-zero test cl,GA_DISCARDABLE ; Is this a discardable handle? jz count_zero ; No, all done call glrutop ; Yes, bring to top of LRU chain count_zero: xor cx,cx count_positive: pop ax ret cEnd nogen sEnd CODE end