int timerLoop (void) { IxOsalTimeval now; IxOsalVoidFnVoidPtr callback = NULL; void *callbackParam = NULL; IxOsalTimerRec *nextTimer; IX_STATUS status; while (1) { /* * This loop catches all cases in a simple way. If multiple * timers expire together, then lowest will be <=0 until all * have been processed and the queue get won't get invoked. */ status = ixOsalSemaphoreWait (&ixOsalCriticalSectSem, IX_OSAL_WAIT_FOREVER); if (status != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "timerLoop fail to get semaphore \n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } ixOsalTimeGet (&now); nextTimer = findNextTimeout (now); if ((nextTimer == NULL) || IX_OSAL_TIME_GT ((nextTimer->expires), (now))) { callback = NULL; } else { rescheduleTimer (nextTimer); callback = nextTimer->callback; callbackParam = nextTimer->callbackParam; } status = ixOsalSemaphorePost (&ixOsalCriticalSectSem); if (status != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "timerLoop fail to release semaphore \n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } if (callback != NULL) { callTimerCallback (callback, callbackParam); } else { timerSleep (nextTimer, now); } } }
PRIVATE IX_STATUS ixHssAccCodeletChanThreadMain ( void* arg, void** ptrRetObj) { ClientInfo *pClientInfo = (ClientInfo *)arg; Message *pMessage; while (1) { (void) ixOsalSemaphoreWait ( &pClientInfo->messageSem, IX_OSAL_WAIT_FOREVER); pMessage = &pClientInfo->messageQ[pClientInfo->qTail++]; pClientInfo->qTail %= NUMELEMS(pClientInfo->messageQ); switch (pMessage->type) { case RxCallback: ixHssAccCodeletChanRxCallbackProcess ( pClientInfo->hssPortId, pMessage->params.rxOffset, pMessage->params.txOffset, pMessage->params.numHssErrs); break; } } /* while (1) */ return IX_SUCCESS; }
PRIVATE void timerSleep (IxOsalTimerRec * nextTimer, IxOsalTimeval now) { UINT32 ticks; IxOsalTimeval temp; if (nextTimer == NULL) { ticks = IX_OSAL_WAIT_FOREVER; } else { temp.secs = nextTimer->expires.secs; temp.nsecs = nextTimer->expires.nsecs; IX_OSAL_TIME_SUB (temp, now); ticks = IX_OSAL_TIMEVAL_TO_TICKS (temp); /* * We should sleep but the period is less than a tick * * away, rounding up. */ if (ticks == 0) { ticks = 1; } } /* * Note: Status is ignored here, wait intentionally */ ixOsalSemaphoreWait (&ixOsalTimerRecalcSem, ticks); }
PUBLIC IX_STATUS ixOsalTimerCancel (IxOsalTimer * timer) { UINT32 id; UINT32 i; IX_STATUS status = IX_FAIL; if (ixOsalTimerInited == FALSE) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "ixOsalTimerCancel: call schedule APIs first to start timer \n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } id = *timer; status = ixOsalSemaphoreWait (&ixOsalCriticalSectSem, IX_OSAL_WAIT_FOREVER); if (status != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "ixOsalTimerCancel: fail to get semaphore \n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } /* * NOTE : there is no need to get the timer callback thread to wake * up and recalculate. If this timer is the next to expire, then * the timer callback thread will wake up but not find any timers to * callback and will just go back to sleep again anyway. */ /* * NOTE2 : We cancel a timer by doing a linear search for the timer id. * This is not terribly efficient but is the safest way to ensure that * cancellations do not cancel the wrong timer by mistake. Also we * assume timer cancellation does not occur often. If the timer to * be cancelled is not found, an error is logged. */ for (i = 0; i < ixOsalHigestTimeSlotUsed; i++) { if (ixOsalTimers[i].inUse && ixOsalTimers[i].id == id) { ixOsalTimers[i].inUse = FALSE; break; } } status = ixOsalSemaphorePost (&ixOsalCriticalSectSem); if (status != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "ixOsalTimerCancel: fail to free semaphore \n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } return IX_SUCCESS; }
/** * @ingroup IxTimeSyncAccCodelet * * @fn ixTimeSyncAccCodeletPTPMsgTransmit () * * @brief Transmit Sync message from master port and Delay_Req message * from slave port every 2 seconds. * * @return void */ PRIVATE void ixTimeSyncAccCodeletPTPMsgTransmit () { IX_OSAL_MBUF *mBufPtr; IxEthAccPortId portId = 0; IxTimeSyncAcc1588PTPPort tsChannel; IxTimeSyncAcc1588PTPMsgType txMsgType; IxTimeSyncAcc1588PTPPortMode tsChannelMode; /* clear PTP message transmission halt flag */ ixTimeSyncAccCodeletTxHalt = FALSE; for (tsChannel = IX_TIMESYNCACC_NPE_A_1588PTP_PORT; tsChannel < IX_TIMESYNCACC_CODELET_MAX_TS_CHANNELS; tsChannel++) { portId = ixTimeSyncAccCodeletPortIdList[tsChannel]; tsChannelMode = ixTimeSyncAccCodeletConfigPtr->tsChannelMode[tsChannel]; txMsgType = ixTimeSyncAccCodeletPTPMsgTypeList[tsChannelMode]; /* build PTP message */ ixTimeSyncAccCodeletPTPMsgBuild (txMsgType); if (IX_SUCCESS != ixTimeSyncAccCodeletPortConfigure (portId)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgTransmit: failed to configure port %d\n", portId, 0, 0, 0, 0, 0); /* terminate time sync codelet execution */ ixTimeSyncAccCodeletUninit (); return; } if (IX_ETH_ACC_SUCCESS != ixEthAccPortEnable (portId)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgTransmit: failed to enable port %d\n", portId, 0, 0, 0, 0, 0); /* terminate time sync codelet execution */ ixTimeSyncAccCodeletUninit (); return; } mBufPtr = ixTimeSyncAccCodeletGlobalMBuf[portId]; if (NULL == mBufPtr) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgTransmit: NULL mBuf pointer, port Id %d\n", portId, 0, 0, 0, 0, 0); /* terminate time sync codelet execution */ ixTimeSyncAccCodeletUninit (); return; } /* copy PTP message data to mBuf's data buffer */ ixOsalMemCopy (IX_OSAL_MBUF_MDATA(mBufPtr), ixTimeSyncAccCodeletPtpMsgData, IX_TIMESYNCACC_CODELET_UDP_FRAME_LEN); } /* end of for loop */ if (IX_SUCCESS != ixOsalSemaphoreInit (&ixTimeSyncAccCodeletSemId, IX_TIMESYNCACC_CODELET_MAX_TS_CHANNELS)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgTransmit: failed to create semaphore\n", 0, 0, 0, 0, 0, 0); /* terminate time sync codelet execution */ ixTimeSyncAccCodeletUninit (); return; } do { /* halt PTP message transmission */ if (TRUE == ixTimeSyncAccCodeletTxHalt) { ixOsalLog (IX_OSAL_LOG_LVL_USER, IX_OSAL_LOG_DEV_STDOUT, "ixTimeSyncAccCodeletPTPMsgTransmit: PTP message transmission was halted\n", 0, 0, 0, 0, 0, 0); return; } /* sleep and wait for interval time to elapse before transmitting next PTP message */ ixOsalSleep (IX_TIMESYNCACC_CODELET_PTP_MSG_XMIT_INTERVAL); for (portId = IX_ETH_PORT_1; portId <= IX_ETH_PORT_3; portId++) { if (IX_SUCCESS != ixOsalSemaphoreWait (&ixTimeSyncAccCodeletSemId, IX_TIMESYNCACC_CODELET_PTP_MSG_XMIT_INTERVAL)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgTransmit: PTP message transmission error at port %d\n", portId, 0, 0, 0, 0, 0); /* terminate time sync codelet execution */ ixTimeSyncAccCodeletUninit (); return; } if (IX_ETH_ACC_SUCCESS != ixEthAccPortTxFrameSubmit (portId, ixTimeSyncAccCodeletGlobalMBuf[portId], IX_ETH_ACC_TX_DEFAULT_PRIORITY)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "ixTimeSyncAccCodeletPTPMsgTransmit: failed to transmit PTP message from port %d\n", portId, 0, 0, 0, 0, 0); /* terminate time sync codelet execution */ ixTimeSyncAccCodeletUninit (); return; } } /* end of for loop */ } while (TRUE); } /* end of ixTimeSyncAccCodeletPTPMsgTransmit function */
/** * @brief Ethernet event processor loop * * Extracts at most EVENT_PROCESSING_LIMIT batches of events and * sends them for processing to @ref ixEthDBProcessEvent(). * Triggers port updates which normally follow learning events. * * @warning do not call directly, executes in separate thread * * @internal */ IX_ETH_DB_PUBLIC void ixEthDBEventProcessorLoop(void *unused1) { IxEthDBPortMap triggerPorts; IxEthDBPortId portIndex; ixEthDBEventProcessorRunning = TRUE; IX_ETH_DB_EVENTS_TRACE("DB: (Events) Event processor loop was started\n"); while (!ixEthDBLearningShutdown) { BOOL keepProcessing = TRUE; UINT32 processedEvents = 0; if (ixEthDBEventProcessorPausing == TRUE) { /* 100 ms*/ ixOsalSleep(100); continue; } IX_ETH_DB_EVENTS_VERBOSE_TRACE("DB: (Events) Waiting for new learning event...\n"); ixOsalSemaphoreWait(&eventQueueSemaphore, IX_OSAL_WAIT_FOREVER); IX_ETH_DB_EVENTS_VERBOSE_TRACE("DB: (Events) Received new event\n"); if (!ixEthDBLearningShutdown) { /* port update handling */ SET_EMPTY_DEPENDENCY_MAP(triggerPorts); while (keepProcessing) { PortEvent local_event; UINT32 intLockKey; /* lock queue */ ixOsalMutexLock(&eventQueueLock, IX_OSAL_WAIT_FOREVER); /* lock NPE interrupts */ intLockKey = ixOsalIrqLock(); /* extract event */ local_event = *(QUEUE_TAIL(&eventQueue)); SHIFT_UPDATE_QUEUE(&eventQueue); ixOsalIrqUnlock(intLockKey); ixOsalMutexUnlock(&eventQueueLock); IX_ETH_DB_EVENTS_TRACE("DB: (Events) Processing event with ID 0x%X\n", local_event.eventType); ixEthDBProcessEvent(&local_event, triggerPorts); processedEvents++; if (processedEvents > EVENT_PROCESSING_LIMIT /* maximum burst reached? */ || ixOsalSemaphoreTryWait(&eventQueueSemaphore) != IX_SUCCESS) /* or empty queue? */ { keepProcessing = FALSE; } } /* Added a pause check here to prevent NPE message * from being sent from ixEthDBUpdatePortLearningTrees() */ while (ixEthDBEventProcessorPausing == TRUE) { /* 100 ms*/ ixOsalSleep(100); } ixEthDBUpdatePortLearningTrees(triggerPorts); } } /* turn off automatic updates */ for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++) { ixEthDBPortInfo[portIndex].updateMethod.updateEnabled = FALSE; } ixEthDBEventProcessorRunning = FALSE; }
PUBLIC IX_STATUS ixOsalMutexLock (IxOsalMutex * mutex, INT32 timeout) { return ixOsalSemaphoreWait((IxOsalSemaphore *) mutex, timeout); }
/* * Attempt to get semaphore, return immediately, * no error info because users expect some failures * when using this API. */ PUBLIC IX_STATUS ixOsalSemaphoreTryWait(IxOsalSemaphore *sid) { return ixOsalSemaphoreWait(sid, IX_OSAL_WAIT_NONE); }
PRIVATE IX_STATUS createNewTimer (IxOsalVoidFnVoidPtr func, void *param, UINT32 priority, UINT32 interval, BOOL isRepeating, UINT32 * timerId) { UINT32 i; IX_STATUS status = IX_SUCCESS; int osTicks; IxOsalTimeval timeVal; /* * Check if callback is NULL */ if (func == NULL) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "client registered a NULL callback function\n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } osTicks = ixOsalSysClockRateGet (); /* * Figure out how many milisecond per tick and compare against interval */ if (interval < (UINT32) (1000 / osTicks)) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "client requested time interval (%d) finer than clock ticks\n", interval, 0, 0, 0, 0, 0); return IX_FAIL; } /* * Increment timerId */ *timerId = ++lastTimerId; status = ixOsalSemaphoreWait (&ixOsalCriticalSectSem, IX_OSAL_WAIT_FOREVER); if (status != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "createNewTimer fail to get semaphore \n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } for (i = 0; i < IX_OSAL_MAX_TIMERS; i++) { if (!ixOsalTimers[i].inUse) { break; } } if ((i >= IX_OSAL_TIMER_WARNING_THRESHOLD) && (ixOsalThresholdErr == FALSE)) { /* * This error serves as an early indication that the number of * available timer slots will need to be increased. This is done * by increasing IX_OSAL_MAX_TIMERS */ ixOsalLog (IX_OSAL_LOG_LVL_WARNING, IX_OSAL_LOG_DEV_STDOUT, "Timer threshold reached. Only %d timer slots now available\n", IX_OSAL_MAX_TIMERS - i, 0, 0, 0, 0, 0); ixOsalThresholdErr = TRUE; } if (i == IX_OSAL_MAX_TIMERS) { /* * If you get this error, increase MAX_TIMERS above */ ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "Out of timer slots %d used - request ignored\n", i, 0, 0, 0, 0, 0); status = IX_FAIL; } else { ixOsalTimers[i].inUse = TRUE; IX_OSAL_MS_TO_TIMEVAL (interval, &timeVal); ixOsalTimers[i].period = timeVal; ixOsalTimers[i].isRepeating = isRepeating; ixOsalTimeGet (&(ixOsalTimers[i].expires)); IX_OSAL_TIME_ADD ((ixOsalTimers[i].expires), (ixOsalTimers[i].period)) ixOsalTimers[i].priority = priority; ixOsalTimers[i].callback = func; ixOsalTimers[i].callbackParam = param; ixOsalTimers[i].id = *timerId; if ((i) >= ixOsalHigestTimeSlotUsed) { ixOsalHigestTimeSlotUsed = i + 1; } status = ixOsalSemaphorePost (&ixOsalTimerRecalcSem); if (status != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "createNewTimer: fail to release semaphore \n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } } status = ixOsalSemaphorePost (&ixOsalCriticalSectSem); if (status != IX_SUCCESS) { ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDOUT, "createNewTimer: fail to release semaphore: ixOsalCriticalSectSem \n", 0, 0, 0, 0, 0, 0); return IX_FAIL; } return status; }