Tvůrce webu je i pro tebe! Postav třeba web. Bez grafika. Bez kodéra. Hned.
wz

Obsah / Utility / BUFFER / Uvolnění položky pole bufferů

Zdrojový kód: INCLUDE\UTIL\BUFFER.INC, UTIL\BUFFER.ASM


Uvolnění položky pole bufferů

Alokační položka může být uvolněna funkcí BuffFree. Jako vstupní parametr je funkci předán ukazatel na záhlaví pole bufferů v registru EDX a ukazatel na uvolňovanou položku v registru EAX. Ukazatel v EAX nesmí být nulový a musí se jednat o položku, která byla alokována pomocí funkce BuffAlloc. Po ukončení funkce je registr EAX vynulován pro zvýšení bezpečnosti, aby uvolněná položka nebyla znovu použita.


; -----------------------------------------------------------------------------
;                              Free buffer entry
; -----------------------------------------------------------------------------
; INPUT:	EAX = buffer entry to free
;		EDX = buffer array head
; OUTPUT:	EAX = NULL
; LOCKS:	BUFH_Lock, SysMemLock
; -----------------------------------------------------------------------------

; ------------- Push registers

BuffFree:	push	ebx		; push EBX
		pushf			; push flags
		cli			; disable interrupts

; ------------- Lock buffer array lock

		LOCK_Lock (edx+BUFH_Lock) ; lock buffer array lock

Na začátku funkce je uchován obsah registru EBX a obsah registru příznaků, zakázáno přerušení a uzamknut zámek bufferu BUFH_Lock. Tím je zabráněno souběhu operací mezi více procesory nebo souběhu s obsluhou přerušení.


; ------------- Link entry into list of free buffer entries

		LISTADD	edx,eax,ebx	; add entry into list of free entries

Uvolňovaná položka je začleněna na začátek seznamu volných položek pomocí makra LISTADD. V registru EDX je ukazatel na záhlaví seznamu volných položek (je shodný s ukazatelem na pole bufferů), registr EAX obsahuje ukazatel na uvolňovanou položku a registr EBX je pracovní.


; ------------- Decrease number of used entries in block head

		and	eax,[edx+BUFH_BlockMask] ; EAX <- block head
		dec	dword [eax+BUFB_Used] ; decrease used counter
		jnz	BuffFree8	; block have not been freed

; ------------- Check if there is any reserved block

		xchg	eax,[edx+BUFH_Reserve] ; EAX <- reserved block
		or	eax,eax		; is reserved block valid?
		jz	BuffFree8	; reserve block is not valid

Z adresy položky (v registru EAX) je pomocí masky BUFH_BlockMask odvozena adresa začátku alokačního bloku a v jeho záhlaví je snížen počet použitých položek BUFB_Used. Pokud zůstávají v bloku i nadále použité alokační položky, funkce se ukončí.

Jsou-li již všechny alokační položky bloku uvolněny, může být uvolněn celý alokační blok. Z důvodu optimalizace nedojde k uvolnění bloku ihned, ale je ponechán jako rezervní blok (protože vyřazení alokačních položek z řetězce volných položek je časově náročná operace). Blok je zrušen jen když už nějaký rezervní blok existuje, jinak se funkce ukončí.


; ------------- Push registers 2

		push	eax		; push EAX
		push	ecx		; push ECX
		push	esi		; push ESI
		push	esi		; push EDI

; ------------- Release list of free entries

		mov	ecx,[edx+BUFH_Entries] ; ECX <- number of entries
		add	eax,byte BUFB_Data ; EAX <- first entry
		mov	edi,[edx+BUFH_EntrySize] ; EDI <- entry size
BuffFree4:	LISTDEL eax,ebx,esi	; delete entry
		add	eax,edi		; EAX <- next entry
		loop	BuffFree4	; link next entry

; ------------- Pop registers 2
	
		pop	edi		; pop EDI
		pop	esi		; pop ESI
		pop	ecx		; pop ECX
		pop	eax		; pop EAX

; ------------- Deallocate old block

		call	SysMemFree	; deallocate old block

Před uvolněním alokačního bloku je potřeba uvolnit všechny alokační položky v bloku z řetězce volných alokačních položek. Nejdříve jsou uloženy obsahy registrů EAX, ECX, ESI a EDI. Do registru ECX se připraví počet položek, které bude potřeba uvolnit (z proměnné BUFH_Entries), registr EAX se posune na začátek první dealokované položky a do registru EDI se připravé velikost jedné položky (z proměnné BUFH_EntrySize). V cyklu se potom každá z položek odpojí ze seznamu volných položek pomocí makra LISTDEL. Registr EAX obsahuje ukazatel na dealokovanou položku a registry EBX a ESI jsou pracovní registry. Po uvolnění všech položek ze seznamu jsou obnoveny obsahy registrů EAX, ECX, ESI a EDI.

Nakonec je alokační blok dealokován pomocí funkce SysMemFree (registr EAX obsahuje adresu alokačního bloku).


; ------------- Unlock buffer array lock

BuffFree8:	LOCK_Unlock (edx+BUFH_Lock) ; unlock buffer array lock

; ------------- Pop registers

		popf			; pop flags
		pop	ebx		; pop EBX
		xor	eax,eax		; EAX <- 0, invalid pointer
		ret

V závěru funkce je zámek BUFH_Lock opět odemknut, navrácením registru příznaků je případně opět povoleno přerušení, je navrácen obsah registru EBX a registr EAX je vynulován.


Obsah / Utility / BUFFER / Uvolnění položky pole bufferů