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

BUFFER.ASM

Buffer Array


; =============================================================================
;
;                              Litos - Buffer array
;
; =============================================================================

		CODE_SECTION	32

; ------------- Macro - initialized buffer array head
; %1 = size of one buffer entry, %2 = size of buffer block (must be power of 2)

%macro		BUFFER	2
		LISTHEAD		; list of free buffer entries
		SPINLOCK		; lock of buffer array
		dd	%1		; size of one buffer entry (min. 8)
		dd	%2		; size of buffer block (power of 2)
		dd	~(%2-1)		; block mask (to get block head)
		dd	(%2-BUFBLOCK_size)/%1 ; number of entries per block
		dd	NULL		; reserved block (NULL=none)
%endmacro

; -----------------------------------------------------------------------------
;                          Allocate buffer entry
; -----------------------------------------------------------------------------
; INPUT:	EDX = buffer array head
; OUTPUT:	EAX = new buffer entry (or EAX = NULL if CY)
;		CY = memory error (EAX = NULL)
; LOCKS:	BUFH_Lock, SysMemLock
; -----------------------------------------------------------------------------

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

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

; ------------- Lock buffer array lock
%ifdef	SMP
		LOCK_Lock (edx+BUFH_Lock) ; lock buffer array lock
%endif
; ------------- Check if list of free entries is empty

		LISTTEST edx		; is list empty?
		jnz	BuffAlloc6	; list is not empty

; ------------- Allocate new buffer block

		mov	eax,[edx+BUFH_BlockSize] ; EAX <- block size
		call	SysMemAlloc	; allocate system memory block
		jc	BuffAlloc9	; memory error (EAX = NULL)

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

		push	ecx		; push ECX
		push	esi		; push ESI

; ------------- Initialize head of the block (no entry used)

		and	dword [eax+BUFB_Used],byte 0 ; no entry used

; ------------- Initialize list of free entries

		mov	ecx,[edx+BUFH_Entries] ; ECX <- number of entries
		lea	eax,[eax+BUFB_Data] ; EAX <- first entry
		mov	esi,[edx+BUFH_EntrySize] ; EDI <- entry size
BuffAlloc4:	LISTLAST edx,eax,ebx	; add new entry into end of list
		add	eax,esi		; EAX <- next entry
		loop	BuffAlloc4	; link next entry

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

		pop	esi		; pop ESI
		pop	ecx		; pop ECX

; ------------- Get next entry from the list of free buffer entries

BuffAlloc6:	mov	eax,[edx+LIST_Next] ; EAX <- first entry in the list
		LISTDELPREV eax,edx,ebx	; delete list entry

; ------------- Increase number of used entries

		mov	ebx,[edx+BUFH_BlockMask] ; EBX <- block mask
		and	ebx,eax		; EBX <- block head
		inc	dword [ebx+BUFB_Used] ; increase used counter

; ------------- Release block from reserved block

		cmp	ebx,[edx+BUFH_Reserve] ; is it reserve block?
		jne	BuffAlloc8	; it is not reserve block
		and	dword [edx+BUFH_Reserve],byte 0 ; invalid block

; ------------- OK: Unlock buffer array lock

BuffAlloc8:
%ifdef	SMP
		LOCK_Unlock (edx+BUFH_Lock) ; unlock buffer array lock
%endif
; ------------- Pop registers and clear error flag

		popf			; pop flags
		clc			; clear error flag
		pop	ebx		; pop EBX
		ret

; ------------- ERROR: Unlock buffer array lock

BuffAlloc9:
%ifdef	SMP
		LOCK_Unlock (edx+BUFH_Lock) ; unlock buffer array lock
%endif
; ------------- Pop registers and set error flag

		popf			; pop flags
		stc			; set error flag
		pop	ebx		; pop EBX
		ret

; -----------------------------------------------------------------------------
;                              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
%ifdef	SMP
		LOCK_Lock (edx+BUFH_Lock) ; lock buffer array lock
%endif
; ------------- Link entry into list of free buffer entries

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

; ------------- 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

; ------------- 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
		lea	eax,[eax+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

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

BuffFree8:
%ifdef	SMP
		LOCK_Unlock (edx+BUFH_Lock) ; unlock buffer array lock
%endif
; ------------- Pop registers

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

Back to source browser