void IPC_PoolDumpStats(IPC_BufferPool Pool) { IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool); if (!PoolPtr) { IPC_TRACE(IPC_Channel_General, "IPC_Stats", "Pool %08X Invalid", Pool, 0, 0, 0); return; }; IPC_TRACE(IPC_Channel_General, "IPC_Stats", "Pool %08X: UserP %08X, BufSize %d, BufCount %d", Pool, PoolPtr->UserParameter, PoolPtr->MaxDataSize, PoolPtr->MaxBuffers); IPC_TRACE(IPC_Channel_General, " ", "Alloc %d, Fail %d, FcStart %d, FcStop %d", PoolPtr->Allocations, PoolPtr->AllocationFailures, PoolPtr->FlowStartCalls, PoolPtr->FlowStopCalls); IPC_TRACE(IPC_Channel_General, " ", "Sent %d, FreeBufs %d, LowWaterMark %d, FcState %d", PoolPtr->BytesSent, PoolPtr->FreeBuffers, PoolPtr->LowWaterMark, PoolPtr->FlowControlState); }
IPC_U32 IPC_PoolFreeBuffers(IPC_BufferPool Pool) { IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool); if (!PoolPtr) { IPC_TRACE(IPC_Channel_Error, "IPC_PoolFreeBuffers", "Invalid Pool %d", Pool, 0, 0, 0); return 0; } return PoolPtr->FreeBuffers; }
//************************************************** IPC_U32 IPC_PoolUserParameterGet (IPC_BufferPool Pool) { IPC_BufferPool_T * PoolPtr = IPC_PoolToPtr (Pool); if (!Pool) { IPC_TRACE (IPC_Channel_Error, "IPC_PoolUserParameterGet", "Invalid Pool %d", Pool, 0, 0, 0); return 0; } return PoolPtr->UserParameter; }
//************************************************** void IPC_PoolSetFreeCallback (IPC_BufferPool Pool, IPC_BufferFreeFPtr_T BufferFreeFunction) { IPC_BufferPool_T * PoolPtr = IPC_PoolToPtr (Pool); if (!PoolPtr) { IPC_TRACE (IPC_Channel_Error, "IPC_PoolSetFreeCallback", "Invalid Pool %d", Pool, 0, 0, 0); return; } PoolPtr->BufferFreeFunction = BufferFreeFunction; }
//************************************************** void IPC_PoolAddBytesSent (IPC_BufferPool Pool, IPC_U32 Bytes) { IPC_BufferPool_T * PoolPtr = IPC_PoolToPtr (Pool); if (!PoolPtr) { IPC_TRACE (IPC_Channel_Error, "IPC_PoolAddBytesSent", "Invalid Pool %d", Pool, 0, 0, 0); return; } PoolPtr->BytesSent += Bytes; }
//************************************************** IPC_CPU_ID_T IPC_PoolOwningCpu (IPC_BufferPool Pool) { IPC_BufferPool_T * PoolPtr = IPC_PoolToPtr (Pool); if (!PoolPtr) { IPC_TRACE (IPC_Channel_Error, "IPC_PoolMaxDataSize", "Invalid Pool %d", Pool, 0, 0, 0); return IPC_NO_CPU; } return PoolPtr->Cpu; }
//************************************************** IPC_U32 IPC_PoolMaxHeaderSize (IPC_BufferPool Pool) { IPC_BufferPool_T * PoolPtr = IPC_PoolToPtr (Pool); if (!PoolPtr) { IPC_TRACE (IPC_Channel_Error, "IPC_PoolMaxHeaderSize", "Invalid Pool %d", Pool, 0, 0, 0); return 0; } return PoolPtr->MaxHeaderSize; }
//************************************************** IPC_EndpointId_T IPC_PoolDestinationEndpointId (IPC_BufferPool Pool) { IPC_BufferPool_T * PoolPtr = IPC_PoolToPtr (Pool); if (!PoolPtr) { IPC_TRACE (IPC_Channel_Error, "IPC_PoolDestinationEndpointId", "Invalid Pool %d", Pool, 0, 0, 0); return IPC_EP_None; } return PoolPtr->DestinationEndpointId; }
void IPC_PoolDump(IPC_BufferPool Pool) { IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool); IPC_U32 Id; IPC_SmPtr Buffer; IPC_U32 BufferSize; IPC_Buffer_T *BufferPtr; IPC_TRACE(IPC_Channel_General, "----- IPC_PoolDump -----", "", 0, 0, 0, 0); if (!PoolPtr) { IPC_TRACE(IPC_Channel_General, "IPC_PoolDump", "Pool %08X Invalid", Pool, 0, 0, 0); return; }; IPC_TRACE(IPC_Channel_General, "IPC_PoolDump", "Pool %08X, CPU %s, SrcEp %02X, DestEp %02X", Pool, (IPC_U32)IPC_GetCpuName(PoolPtr->Cpu), PoolPtr->SourceEndpointId, PoolPtr->DestinationEndpointId); IPC_TRACE(IPC_Channel_General, " ", "SrcEp Id=%02X Name=%s, DestEp Id=%02X Name=%s", PoolPtr->SourceEndpointId, (IPC_U32)IPC_GetEndPointName(PoolPtr->SourceEndpointId), PoolPtr->DestinationEndpointId, (IPC_U32)IPC_GetEndPointName(PoolPtr->DestinationEndpointId)); IPC_TRACE(IPC_Channel_General, " ", "BufCount %d, Free %d, FlowState %01d, Param %08X", PoolPtr->MaxBuffers, PoolPtr->FreeBuffers, PoolPtr->FlowControlState, PoolPtr->UserParameter); IPC_PoolDumpStats(Pool); /* Dump IPC buffer not consumed by receiver to debug IPC memory depletion issue */ if (PoolPtr->MaxBuffers == PoolPtr->FreeBuffers) return; Buffer = Pool + sizeof(IPC_BufferPool_T); BufferSize = IPC_BufferOverhead() + PoolPtr->MaxHeaderSize + PoolPtr->MaxDataSize; IPC_TRACE(IPC_Channel_General, "IPC_PoolDump", "Allocated Buffers:", 0, 0, 0, 0); for (Id = 0; Id < PoolPtr->MaxBuffers; Id++) { BufferPtr = IPC_BufferToPtr(Buffer); if (BufferPtr->StatusCode != IPC_BUFFER_STATUS_FREE) IPC_BufferDump(Buffer); Buffer += BufferSize; } }
//************************************************** IPC_Boolean IPC_PoolUserParameterSet (IPC_BufferPool Pool, IPC_U32 Parameter) { IPC_BufferPool_T * PoolPtr = IPC_PoolToPtr (Pool); if (!PoolPtr) { IPC_TRACE (IPC_Channel_Error, "IPC_PoolUserParameterSet", "Invalid Pool %d", Pool, 0, 0, 0); return IPC_FALSE; } PoolPtr->UserParameter = Parameter; return IPC_TRUE; }
void IPC_BufferReturn(IPC_Buffer Buffer, IPC_BufferPool Pool) { IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool); if (PoolPtr == 0) { IPC_TRACE(IPC_Channel_Error, "IPC_BufferReturn", "Invalid Pool for Buffer %08X", Buffer, 0, 0, 0); return; } if (PoolPtr->BufferFreeFunction) { IPC_TRACE(IPC_Channel_Buffer, "IPC_BufferReturn", "User Function %08X called for Buffer %08X", PoolPtr->BufferFreeFunction, Buffer, 0, 0); (PoolPtr->BufferFreeFunction) (Pool, Buffer); } else { IPC_BufferReturnToPool(Buffer, Pool); } }
void IPC_BufferReturnToPool(IPC_Buffer Buffer, IPC_BufferPool Pool) { IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool); IPC_U32 BufferCount; IPC_Boolean FlowControlCallNeeded = IPC_FALSE; CRITICAL_REIGON_SETUP IPC_TRACE(IPC_Channel_Buffer, "IPC_BufferReturnToPool", "Buffer %d (%08X), now %d in pool", IPC_BufferId(Buffer), Buffer, PoolPtr->FreeBuffers + 1, 0); CRITICAL_REIGON_ENTER(PoolPtr->Lock); BufferCount = ++PoolPtr->FreeBuffers; #ifdef IPC_DEBUG IPC_QRemove(IPC_BufferQueue(Buffer)); #endif IPC_QAddBack(IPC_BufferQueue(Buffer), IPC_POOLFreeQ(IPC_SmOffset(PoolPtr))); /* Flow Control Check */ if (BufferCount == PoolPtr->FlowStartLimit) CHECK_FLOW_STATE(PoolPtr, IPC_FLOW_START, FlowControlCallNeeded) CRITICAL_REIGON_LEAVE(PoolPtr->Lock); if (FlowControlCallNeeded) IPC_ReportFlowControlEvent(PoolPtr, IPC_FLOW_START); /* Last ditch check - should never happen */ if (PoolPtr->FlowControlState == IPC_FLOW_STOP && !PoolPtr->FlowControlCallPending && PoolPtr->FlowStartLimit < BufferCount) { IPC_TRACE(IPC_Channel_FlowControl, "IPC_BufferReturnToPool", "Retry Flow Start", 0, 0, 0, 0); IPC_ReportFlowControlEvent(PoolPtr, IPC_FLOW_START); } /* For IPC_AllocateBufferWait () */ if ((BufferCount == 1) && (PoolPtr->EmptyEvent)) IPC_EVENT_SET(PoolPtr->EmptyEvent); }
void IPC_BufferDump(IPC_Buffer Buffer) { IPC_Buffer_T *BufferPtr = IPC_BufferToPtr(Buffer); /** * DataPtr is used to dump the contents of the first 4 U32s * of the memory location * * coverity[returned_pointer] */ IPC_U32 *DataPtr = IPC_BufferDataPointer(Buffer); IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(BufferPtr->Pool); if (BufferPtr == 0) { IPC_TRACE(IPC_Channel_General, "IPC_BufferDump", "Invalid Buffer %08X", Buffer, 0, 0, 0); return; } IPC_TRACE(IPC_Channel_General, "IPC_BufferDump", "Id %d, Pool %08X, Next %08X, Prev %08X", BufferPtr->BufferId, BufferPtr->Pool, BufferPtr->Q.Next, BufferPtr->Q.Previous); IPC_TRACE(IPC_Channel_General, " ", "Buffer %08X, DataOffset %08X, DataSize %d, HeaderSize %d", BufferPtr->DataBufferStart, BufferPtr->DataOffset, BufferPtr->DataSize, BufferPtr->HeaderSize); if (BufferPtr->StatusCode == IPC_BUFFER_STATUS_FREE) { IPC_TRACE(IPC_Channel_General, " ", "Free FreeTime %d, prevAllocTime %d, prevSendTime %d", BufferPtr->TimeStampFree, BufferPtr->TimeStampAlloc, BufferPtr->TimeStampSend, 0); } else if (BufferPtr->StatusCode == IPC_BUFFER_STATUS_ALLOC) { IPC_TRACE(IPC_Channel_General, " ", "Alloc AllocTime %d, prevSendTime %d, prevFreeTime %d", BufferPtr->TimeStampAlloc, BufferPtr->TimeStampSend, BufferPtr->TimeStampFree, 0); } else if (BufferPtr->StatusCode == IPC_BUFFER_STATUS_SENT) { IPC_TRACE(IPC_Channel_General, " ", "Sent SendTime %d, AllocTime %d, prevFreeTime %d", BufferPtr->TimeStampSend, BufferPtr->TimeStampAlloc, BufferPtr->TimeStampFree, 0); } else { IPC_TRACE(IPC_Channel_General, " ", "Invalid Status", 0, 0, 0, 0); } IPC_TRACE(IPC_Channel_General, " ", "Data 0..3 %08X %08X %08X %08X", DataPtr[0], DataPtr[1], DataPtr[2], DataPtr[3]); IPC_TRACE(IPC_Channel_General, " ", "Data 4..7 %08X %08X %08X %08X", DataPtr[4], DataPtr[5], DataPtr[6], DataPtr[7]); /* Print RPC message ID located at byte 18-19 of IPC buffer */ if (PoolPtr->SourceEndpointId == IPC_EP_Capi2Cp || PoolPtr->DestinationEndpointId == IPC_EP_Capi2Cp) { UInt8 *rpcDataPtr = (UInt8 *)DataPtr; UInt32 rpcMsgId; rpcMsgId = ((UInt32)(rpcDataPtr[19])) | ((UInt32)(rpcDataPtr[18]) << 8); IPC_TRACE(IPC_Channel_General, " ", "RPC message ID %08X", rpcMsgId, 0, 0, 0); } }
IPC_Buffer IPC_AllocateBufferWait(IPC_BufferPool Pool, IPC_U32 MilliSeconds) { IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool); IPC_Buffer Buffer; IPC_ReturnCode_T errCode; UInt32 curTick, endTick; UInt32 beforeTick, afterTick; curTick = 0; endTick = MilliSeconds; while (curTick < endTick) { /* Try straight allocate first (saves event operations most of the time) */ Buffer = IPC_AllocateBuffer(Pool); if (Buffer) return Buffer; /* Check Event exists */ if (!PoolPtr->EmptyEvent) { /* Can't suspend without an event flag */ IPC_TRACE(IPC_Channel_Error, "IPC_AllocateBufferWait", "No Event Flag for Pool %08X", Pool, 0, 0, 0); return 0; } /* Clear event before waiting on it */ if (IPC_OK != IPC_EVENT_CLEAR(PoolPtr->EmptyEvent)) { IPC_TRACE(IPC_Channel_Error, "IPC_AllocateBufferWait", "Cannot clear Event Flag %08P for Pool %08X", PoolPtr->EmptyEvent, Pool, 0, 0); return 0; } /* Check in case the event was set before the clear */ Buffer = IPC_AllocateBuffer(Pool); if (Buffer) return Buffer; /* Now can safely wait for the event to be set * by the buffer free */ IPC_TRACE(IPC_Channel_FlowControl, "IPC_AllocateBufferWait", "Pool %08X Empty, waiting for %d Milliseconds, total=%d", Pool, (endTick - curTick), MilliSeconds, 0); beforeTick = TIMER_GetValue(); errCode = IPC_EVENT_WAIT(PoolPtr->EmptyEvent, (endTick - curTick)); afterTick = TIMER_GetValue(); /* Handle wrap around for 0xFFFFFFFF */ curTick += (UInt32)(afterTick - beforeTick); if (IPC_ERROR == errCode) { IPC_TRACE(IPC_Channel_Error, "IPC_AllocateBufferWait", "Error from IPC_EVENT_WAIT; Event Flag %08P for Pool %08X", PoolPtr->EmptyEvent, Pool, 0, 0); return 0; } else if (IPC_OK == errCode) { continue; /* retry */ } else { /* IPC_TIMEOUT */ break; } } return IPC_AllocateBuffer(Pool); }
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; }
void IPC_PoolDelete(IPC_BufferPool Pool) { IPC_BufferPool_T *PoolPtr = IPC_PoolToPtr(Pool); IPC_EVENT_DELETE(PoolPtr->EmptyEvent); CRITICAL_REIGON_DELETE(PoolPtr->Lock); }