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;
}
Esempio n. 10
0
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;
}