void IPC_QRemove(IPC_SmQEntry Entry) { IPC_QEntry EntryPtr = IPC_QEntryPtr(Entry); IPC_QEntry NextPtr = IPC_QEntryPtr(EntryPtr->Next); IPC_QEntry PreviousPtr = IPC_QEntryPtr(EntryPtr->Previous); NextPtr->Previous = EntryPtr->Previous; PreviousPtr->Next = EntryPtr->Next; EntryPtr->Next = Entry; EntryPtr->Previous = Entry; }
void IPC_QAddBack(IPC_SmQEntry Entry, IPC_SmQ Queue) { IPC_QEntry EntryPtr = IPC_QEntryPtr(Entry); IPC_QHead HeadPtr = IPC_QHeadPtr(Queue); IPC_QEntry PreviousPtr = IPC_QEntryPtr(HeadPtr->Link.Previous); EntryPtr->Next = Queue; EntryPtr->Previous = HeadPtr->Link.Previous; PreviousPtr->Next = Entry; HeadPtr->Link.Previous = Entry; }
IPC_SmQEntry IPC_QAddFront(IPC_SmQEntry Entry, IPC_SmQ Queue) { IPC_QEntry EntryPtr = IPC_QEntryPtr(Entry); IPC_QHead HeadPtr = IPC_QHeadPtr(Queue); IPC_QEntry FrontPtr = IPC_QEntryPtr(HeadPtr->Link.Next); EntryPtr->Next = HeadPtr->Link.Next; EntryPtr->Previous = Queue; FrontPtr->Previous = Entry; HeadPtr->Link.Next = Entry; return Entry; }
IPC_SmQEntry IPC_QAddAfter(IPC_SmQEntry Entry, IPC_SmQEntry After) { IPC_QEntry EntryPtr = IPC_QEntryPtr(Entry); IPC_QEntry AfterPtr = IPC_QEntryPtr(After); IPC_QEntry BeforePtr = IPC_QEntryPtr(AfterPtr->Next); EntryPtr->Next = AfterPtr->Next; EntryPtr->Previous = After; BeforePtr->Previous = Entry; AfterPtr->Next = Entry; return Entry; }
IPC_SmQEntry IPC_QAddBefore(IPC_SmQEntry Entry, IPC_SmQEntry Before) { IPC_QEntry EntryPtr = IPC_QEntryPtr(Entry); IPC_QEntry BeforePtr = IPC_QEntryPtr(Before); IPC_QEntry AfterPtr = IPC_QEntryPtr(BeforePtr->Previous); EntryPtr->Next = Before; EntryPtr->Previous = BeforePtr->Previous; AfterPtr->Next = Entry; BeforePtr->Previous = Entry; return Entry; }
IPC_SmQEntry IPC_QGetLast(IPC_SmQ Queue) { IPC_QHead HeadPtr = IPC_QHeadPtr(Queue); IPC_SmQEntry Entry = HeadPtr->Link.Previous; IPC_QEntry EntryPtr = IPC_QEntryPtr(Entry); IPC_QEntry PreviousPtr = IPC_QEntryPtr(EntryPtr->Previous); if (Entry == Queue) return 0; HeadPtr->Link.Previous = EntryPtr->Previous; PreviousPtr->Next = Queue; EntryPtr->Next = Entry; EntryPtr->Previous = Entry; return Entry; }
IPC_SmQEntry IPC_QGetFirst(IPC_SmQ Queue) { IPC_QHead HeadPtr = IPC_QHeadPtr(Queue); IPC_SmQEntry Entry = HeadPtr->Link.Next; IPC_QEntry EntryPtr = IPC_QEntryPtr(Entry); IPC_QEntry NextPtr = IPC_QEntryPtr(EntryPtr->Next); if (Entry == Queue) return 0; HeadPtr->Link.Next = EntryPtr->Next; NextPtr->Previous = Queue; EntryPtr->Next = Entry; EntryPtr->Previous = Entry; return Entry; }
IPC_SmQEntry IPC_QPrevious(IPC_SmQEntry Entry) { IPC_QEntry EntryPtr = IPC_QEntryPtr(Entry); return EntryPtr->Previous; }
IPC_SmQEntry IPC_QNext(IPC_SmQEntry Entry) { IPC_QEntry EntryPtr = IPC_QEntryPtr(Entry); return EntryPtr->Next; }
IPC_Buffer IPC_AllocateBuffer(IPC_BufferPool Pool) { CRITICAL_REIGON_SETUP IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool); IPC_SmQEntry QElement; IPC_U32 BufferCount; IPC_Buffer Buffer; IPC_Boolean FlowControlCallNeeded = IPC_FALSE; if (!Pool) { IPC_TRACE(IPC_Channel_Error, "IPC_AllocateBuffer", "Invalid Pool %08X", Pool, 0, 0, 0); return 0; } CRITICAL_REIGON_ENTER(PoolPtr->Lock); QElement = IPC_QGetFirst(IPC_POOLFreeQ(Pool)); if (!QElement) { PoolPtr->FlowControlState = IPC_FLOW_STOP; PoolPtr->AllocationFailures++; CRITICAL_REIGON_LEAVE(PoolPtr->Lock); if (PoolPtr->DestinationEndpointId != IPC_EP_LogApps) IPC_TRACE(IPC_Channel_FlowControl, "IPC_ReportFlowControlEvent", "Pool %08X Empty, Allocations %d AllocationFailures %d FlowStopCalls %d", Pool, PoolPtr->Allocations, PoolPtr->AllocationFailures, PoolPtr->FlowStopCalls); return 0; } #ifdef IPC_DEBUG IPC_QAddBack(QElement, IPC_SmOffset(&PoolPtr->AllocatedBufferQ)); #endif BufferCount = --PoolPtr->FreeBuffers; /* Flow Control Check */ if (BufferCount == PoolPtr->FlowStopLimit) CHECK_FLOW_STATE(PoolPtr, IPC_FLOW_STOP, FlowControlCallNeeded) CRITICAL_REIGON_LEAVE(PoolPtr->Lock); if (FlowControlCallNeeded) IPC_ReportFlowControlEvent(PoolPtr, IPC_FLOW_STOP); Buffer = IPC_QEntryPtr(QElement)->Item; if (Buffer) { IPC_Buffer_T *BufferPtr = IPC_SmOffsetToPointer(IPC_Buffer_T, Buffer); BufferPtr->HeaderSize = 0; BufferPtr->DataSize = 0; BufferPtr->UserParameter = 0; BufferPtr->TimeStampAlloc = TIMER_GetValue(); BufferPtr->StatusCode = IPC_BUFFER_STATUS_ALLOC; BufferPtr->DataOffset = BufferPtr->DataBufferStart + IPC_PoolPtr(BufferPtr->Pool)->MaxHeaderSize; } IPC_TRACE(IPC_Channel_Buffer, "IPC_AllocateBuffer", "Buf %d (%08X) Pool %08X, %d Left", IPC_BufferId(Buffer), Buffer, Pool, BufferCount); /* Update Statistics */ PoolPtr->Allocations++; if (BufferCount < PoolPtr->LowWaterMark) PoolPtr->LowWaterMark = BufferCount; return Buffer; }