/** Test whether the FIFO is full. @param[in] Self Pointer to the FIFO instance. @retval TRUE The FIFO is full. @retval FALSE There is free space in the FIFO. **/ static BOOLEAN EFIAPI FIFO_IsFull ( cFIFO *Self ) { assert(Self != NULL); return (BOOLEAN)(ModuloIncrement(Self->WriteIndex, Self->NumElements) == (INT32)Self->ReadIndex); }
/** Read or copy elements from the FIFO. This function allows one to read one or more elements, as specified by Count, from the FIFO. Each element is of the size specified when the FIFO object was instantiated (FIFO.ElementSize). pElement points to the destination of the first byte of the first element to be read. If multiple elements are to be read, the elements are expected to be organized as a packed array. @param[in] Self Pointer to the FIFO instance. @param[out] pElement Pointer to where to store the element(s) read from the FIFO. @param[in] Count Number of elements to dequeue. @param[in] Consume If TRUE, consume read elements. Otherwise, preserve. @retval 0 The FIFO is empty. @retval >=0 The number of elements read from the FIFO. **/ static size_t EFIAPI FIFO_Dequeue ( cFIFO *Self, void *pElement, size_t Count, BOOLEAN Consume ) { UINTN ElemPtr; UINTN QPtr; UINT32 RDex; UINT32 SizeOfElement; UINT32 i; assert(Self != NULL); assert(pElement != NULL); assert(Count != 0); if(FIFO_IsEmpty(Self)) { Count = 0; } else { RDex = Self->ReadIndex; SizeOfElement = Self->ElementSize; ElemPtr = (UINTN)pElement; Count = MIN(Count, Self->Count(Self, AsElements)); QPtr = (UINTN)Self->Queue + (RDex * Self->ElementSize); for(i = 0; i < Count; ++i) { (void)CopyMem((void *)ElemPtr, (const void *)QPtr, Self->ElementSize); RDex = (UINT32)ModuloIncrement(RDex, Self->NumElements); if(RDex == 0) { // If the index wrapped QPtr = (UINTN)Self->Queue; } else { QPtr += Self->ElementSize; } ElemPtr += Self->ElementSize; } if(Consume) { Self->ReadIndex = RDex; } } return Count; }
/** Add one or more elements to the FIFO. This function allows one to add one or more elements, as specified by Count, to the FIFO. Each element is of the size specified when the FIFO object was instantiated (FIFO.ElementSize). pElement points to the first byte of the first element to be added. If multiple elements are to be added, the elements are expected to be organized as a packed array. @param[in] Self Pointer to the FIFO instance. @param[in] pElement Pointer to the element(s) to enqueue (add). @param[in] Count Number of elements to add. @retval 0 The FIFO is full. @retval >=0 The number of elements added to the FIFO. **/ static size_t EFIAPI FIFO_Enqueue ( cFIFO *Self, const void *pElement, size_t Count ) { uintptr_t ElemPtr; uintptr_t QPtr; size_t i; UINT32 SizeOfElement; UINT32 Windex; assert(Self != NULL); assert(pElement != NULL); assert(Count >= 0); if(FIFO_IsFull(Self)) { Count = 0; } else { Count = MIN(Count, Self->FreeSpace(Self, AsElements)); SizeOfElement = Self->ElementSize; Windex = Self->WriteIndex; ElemPtr = (uintptr_t)pElement; QPtr = (uintptr_t)Self->Queue + (SizeOfElement * Windex); for(i = 0; i < Count; ++i) { (void)CopyMem((void *)QPtr, (const void *)ElemPtr, SizeOfElement); Windex = (UINT32)ModuloIncrement(Windex, Self->NumElements); if(Windex == 0) { // If the index wrapped QPtr = (uintptr_t)Self->Queue; } else { QPtr += SizeOfElement; } ElemPtr += SizeOfElement; } (void)ZeroMem((void*)QPtr, SizeOfElement); Self->WriteIndex = Windex; } return Count; }