📄 ixqmgrdispatcher.c
字号:
{ ixQMgrDispatcherReBuildPriorityTable (); }}voidixQMgrDispatcherLoopRunB0LLP (IxQMgrDispatchGroup group){ UINT32 intRegVal =0; /* Interrupt reg val */ UINT32 intRegCheckMask; /* Mask for checking interrupt bits */ IxQMgrQInfo *currDispatchQInfo; int priorityTableIndex; /* Priority table index */ int qIndex; /* Current queue being processed */ UINT32 intRegValCopy = 0; UINT32 intEnableRegVal = 0; UINT8 i = 0;#ifndef NDEBUG IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) || (group == IX_QMGR_QUELOW_GROUP));#endif /* Read the interrupt register */ ixQMgrAqmIfQInterruptRegRead (group, &intRegVal); /* * mask any interrupts that are not enabled */ ixQMgrAqmIfQInterruptEnableRegRead (group, &intEnableRegVal); intRegVal &= intEnableRegVal; /* No queue has interrupt register set */ if (intRegVal != 0) { if (IX_QMGR_QUELOW_GROUP == group) { /* * As the sticky bit is set, the interrupt register will * not clear if write back at this point because the condition * has not been cleared. Take a copy and write back later after * the condition has been cleared */ intRegValCopy = intRegVal; } else { /* no sticky for upper Q's, so write back now */ ixQMgrAqmIfQInterruptRegWrite (group, intRegVal); } /* get the first queue Id from the interrupt register value */ qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal); if (IX_QMGR_QUEUPP_GROUP == group) { /* Set the queue range based on the queue group to proccess */ qIndex += IX_QMGR_MIN_QUEUPP_QID; } /* check if the interrupt register contains * only 1 bit set * For example: * intRegVal = 0x0010 * currDispatchQInfo->intRegCheckMask = 0x0010 * intRegVal == currDispatchQInfo->intRegCheckMask is TRUE. */ currDispatchQInfo = &dispatchQInfo[qIndex]; if (intRegVal == currDispatchQInfo->intRegCheckMask) { /* * check if Q type periodic - only lower queues can * have there type set to periodic */ if (IX_QMGR_TYPE_REALTIME_PERIODIC == ixQMgrQTypes[qIndex]) { /* * Disable the notifications on any sporadics */ for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++) { if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrQTypes[i]) { ixQMgrNotificationDisable(i);#ifndef NDEBUG /* Update statistics */ dispatcherStats.queueStats[i].disableCount++;#endif } } } currDispatchQInfo->callback (qIndex, currDispatchQInfo->callbackId);#ifndef NDEBUG /* Update statistics */ dispatcherStats.queueStats[qIndex].callbackCnt++;#endif } else { /* the event is triggered by more than 1 queue, * the queue search will be starting from the beginning * or the middle of the priority table * * the serach will end when all the bits of the interrupt * register are cleared. There is no need to maintain * a seperate value and test it at each iteration. */ if (IX_QMGR_QUELOW_GROUP == group) { /* check if any bit related to queues in the first * half of the priority table is set */ if (intRegVal & lowPriorityTableFirstHalfMask) { priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX; } else { priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX; } } else { /* check if any bit related to queues in the first * half of the priority table is set */ if (intRegVal & uppPriorityTableFirstHalfMask) { priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; } else { priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX; } } /* iterate following the priority table until all the bits * of the interrupt register are cleared. */ do { qIndex = priorityTable[priorityTableIndex++]; currDispatchQInfo = &dispatchQInfo[qIndex]; intRegCheckMask = currDispatchQInfo->intRegCheckMask; /* If this queue caused this interrupt to be raised */ if (intRegVal & intRegCheckMask) { /* * check if Q type periodic - only lower queues can * have there type set to periodic. There can only be one * periodic queue, so the sporadics are only disabled once. */ if (IX_QMGR_TYPE_REALTIME_PERIODIC == ixQMgrQTypes[qIndex]) { /* * Disable the notifications on any sporadics */ for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++) { if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrQTypes[i]) { ixQMgrNotificationDisable(i); /* * remove from intRegVal as we don't want * to service any sporadics now */ intRegVal &= ~dispatchQInfo[i].intRegCheckMask;#ifndef NDEBUG /* Update statistics */ dispatcherStats.queueStats[i].disableCount++;#endif } } } currDispatchQInfo->callback (qIndex, currDispatchQInfo->callbackId);#ifndef NDEBUG /* Update statistics */ dispatcherStats.queueStats[qIndex].callbackCnt++;#endif /* Clear the interrupt register bit */ intRegVal &= ~intRegCheckMask; } } while(intRegVal); } /*End of intRegVal == currDispatchQInfo->intRegCheckMask */ } /* End of intRegVal != 0 */#ifndef NDEBUG /* Update statistics */ dispatcherStats.loopRunCnt++;#endif if ((intRegValCopy != 0) && (IX_QMGR_QUELOW_GROUP == group)) { /* * lower groups (therefore sticky) AND at least one enabled interrupt * Write back to clear the interrupt */ ixQMgrAqmIfQInterruptRegWrite (IX_QMGR_QUELOW_GROUP, intRegValCopy); } /* Rebuild the priority table if needed */ if (rebuildTable) { ixQMgrDispatcherReBuildPriorityTable (); }}PRIVATE voidixQMgrDispatcherReBuildPriorityTable (void){ UINT32 qIndex; UINT32 priority; int lowQuePriorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX; int uppQuePriorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX; /* Reset the rebuild flag */ rebuildTable = FALSE; /* initialize the mak used to identify the queues in the first half * of the priority table */ lowPriorityTableFirstHalfMask = 0; uppPriorityTableFirstHalfMask = 0; /* For each priority level */ for(priority=0; priority<IX_QMGR_NUM_PRIORITY_LEVELS; priority++) { /* Foreach low queue in this priority */ for(qIndex=0; qIndex<IX_QMGR_MIN_QUEUPP_QID; qIndex++) { if (dispatchQInfo[qIndex].priority == priority) { /* build the priority table bitmask which match the * queues of the first half of the priority table */ if (lowQuePriorityTableIndex < IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX) { lowPriorityTableFirstHalfMask |= dispatchQInfo[qIndex].intRegCheckMask; } /* build the priority table */ priorityTable[lowQuePriorityTableIndex++] = qIndex; } } /* Foreach upp queue */ for(qIndex=IX_QMGR_MIN_QUEUPP_QID; qIndex<=IX_QMGR_MAX_QID; qIndex++) { if (dispatchQInfo[qIndex].priority == priority) { /* build the priority table bitmask which match the * queues of the first half of the priority table */ if (uppQuePriorityTableIndex < IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX) { uppPriorityTableFirstHalfMask |= dispatchQInfo[qIndex].intRegCheckMask; } /* build the priority table */ priorityTable[uppQuePriorityTableIndex++] = qIndex; } } }}IxQMgrDispatcherStats*ixQMgrDispatcherStatsGet (void){ return &dispatcherStats;}PRIVATE voiddummyCallback (IxQMgrQId qId, IxQMgrCallbackId cbId){ /* Throttle the trace message */ if ((dispatchQInfo[qId].dummyCallbackCount % LOG_THROTTLE_COUNT) == 0) { IX_QMGR_LOG_WARNING2("--> dummyCallback: qId (%d), callbackId (%d)\n",qId,cbId); } dispatchQInfo[qId].dummyCallbackCount++;#ifndef NDEBUG /* Update statistcs */ dispatcherStats.queueStats[qId].intNoCallbackCnt++;#endif}voidixQMgrLLPShow (int resetStats){#ifndef NDEBUG UINT8 i = 0; IxQMgrQInfo *q; UINT32 intEnableRegVal = 0; printf ("Livelock statistics are printed on the fly.\n"); printf ("qId Type EnableCnt DisableCnt IntEnableState Callbacks\n"); printf ("=== ======== ========= ========== ============== =========\n"); for (i=0; i<= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++) { q = &dispatchQInfo[i]; if (ixQMgrQTypes[i] != IX_QMGR_TYPE_REALTIME_OTHER) { printf (" %2d ", i); if (ixQMgrQTypes[i] == IX_QMGR_TYPE_REALTIME_SPORADIC) { printf ("Sporadic"); } else { printf ("Periodic"); } ixQMgrAqmIfQInterruptEnableRegRead (IX_QMGR_QUELOW_GROUP, &intEnableRegVal); intEnableRegVal &= dispatchQInfo[i].intRegCheckMask; intEnableRegVal = intEnableRegVal >> i; printf (" %10d %10d %10d %10d\n", dispatcherStats.queueStats[i].enableCount, dispatcherStats.queueStats[i].disableCount, intEnableRegVal, dispatcherStats.queueStats[i].callbackCnt); if (resetStats) { dispatcherStats.queueStats[i].enableCount = dispatcherStats.queueStats[i].disableCount = dispatcherStats.queueStats[i].callbackCnt = 0; } } }#else IX_QMGR_LOG0("Livelock Prevention statistics are only collected in debug mode\n");#endif}voidixQMgrPeriodicDone (void){ UINT32 i = 0; UINT32 ixQMgrLockKey = 0; /* * for the lower queues */ for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++) { /* * check for sporadics */ if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrQTypes[i]) { /* * enable any sporadics */ ixQMgrLockKey = ixOsalIrqLock(); ixQMgrAqmIfQInterruptEnable(i); ixOsalIrqUnlock(ixQMgrLockKey);#ifndef NDEBUG /* * Update statistics */ dispatcherStats.queueStats[i].enableCount++; dispatcherStats.queueStats[i].notificationEnabled = TRUE;#endif } }}IX_STATUSixQMgrCallbackTypeSet (IxQMgrQId qId, IxQMgrType type){ UINT32 ixQMgrLockKey = 0; IxQMgrType ixQMgrOldType =0;#ifndef NDEBUG if (!ixQMgrQIsConfigured(qId)) { return IX_QMGR_Q_NOT_CONFIGURED; } if (qId >= IX_QMGR_MIN_QUEUPP_QID) { return IX_QMGR_PARAMETER_ERROR; } if(!IX_QMGR_DISPATCHER_CALLBACK_TYPE_CHECK(type)) { return IX_QMGR_PARAMETER_ERROR; }#endif ixQMgrOldType = ixQMgrQTypes[qId]; ixQMgrQTypes[qId] = type; /* * check if Q has been changed from type SPORADIC */ if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrOldType) { /* * previously Q was a SPORADIC, this means that LLP * might have had it disabled. enable it now. */ ixQMgrLockKey = ixOsalIrqLock(); ixQMgrAqmIfQInterruptEnable(qId); ixOsalIrqUnlock(ixQMgrLockKey);#ifndef NDEBUG /* * Update statistics */ dispatcherStats.queueStats[qId].enableCount++;#endif } return IX_SUCCESS;}IX_STATUSixQMgrCallbackTypeGet (IxQMgrQId qId, IxQMgrType *type){#ifndef NDEBUG if (!ixQMgrQIsConfigured(qId)) { return IX_QMGR_Q_NOT_CONFIGURED; } if (qId >= IX_QMGR_MIN_QUEUPP_QID) { return IX_QMGR_PARAMETER_ERROR; } if(type == NULL) { return IX_QMGR_PARAMETER_ERROR; }#endif *type = ixQMgrQTypes[qId]; return IX_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -