//------------------------------------------------------------------------------ tOplkError timeru_setTimer(tTimerHdl* pTimerHdl_p, ULONG timeInMs_p, tTimerArg argument_p) { tTimeruData* pData; struct itimerspec relTime; tHrtimerSig sig; if (pTimerHdl_p == NULL) return kErrorTimerInvalidHandle; pData = (tTimeruData*)OPLK_MALLOC(sizeof(tTimeruData)); if (pData == NULL) { DEBUG_LVL_ERROR_TRACE("error allocating user timer memory!\n"); return kErrorNoResource; } OPLK_MEMCPY(&pData->timerArg, &argument_p, sizeof(tTimerArg)); addTimer(pData); sig.sigType = kHrtimerSigMsgQueue; sig.sigParam.m_signalMq.msgQueue = timeruInstance_l.msgQueue; sig.sigParam.m_signalMq.m_sigData = (ULONG)pData; if (hrtimer_create(CLOCK_MONOTONIC, &sig, &pData->timer) != 0) { DEBUG_LVL_ERROR_TRACE("%s() Error hrtimer_create!\n", __func__); return kErrorNoResource; } if (timeInMs_p >= 1000) { relTime.it_value.tv_sec = (timeInMs_p / 1000); relTime.it_value.tv_nsec = (timeInMs_p % 1000) * 1000000; } else { relTime.it_value.tv_sec = 0; relTime.it_value.tv_nsec = timeInMs_p * 1000000; } relTime.it_interval.tv_sec = 0; relTime.it_interval.tv_nsec = 0; DEBUG_LVL_TIMERU_TRACE("%s() Set timer:%08x timeInMs_p=%ld\n", __func__, *pData, timeInMs_p); if (hrtimer_settime(pData->timer, 0, &relTime, NULL) < 0) { DEBUG_LVL_ERROR_TRACE("%s() Error hrtimer_settime!\n", __func__); return kErrorTimerNoTimerCreated; } *pTimerHdl_p = (tTimerHdl)pData; return kErrorOk; }
//------------------------------------------------------------------------------ tOplkError timeru_modifyTimer(tTimerHdl* pTimerHdl_p, ULONG timeInMs_p, const tTimerArg* pArgument_p) { tTimeruData* pData; struct itimerspec relTime; if (pTimerHdl_p == NULL) return kErrorTimerInvalidHandle; // check handle itself, i.e. was the handle initialized before if (*pTimerHdl_p == 0) return timeru_setTimer(pTimerHdl_p, timeInMs_p, pArgument_p); pData = (tTimeruData*)*pTimerHdl_p; if (timeInMs_p >= 1000) { relTime.it_value.tv_sec = (timeInMs_p / 1000); relTime.it_value.tv_nsec = (timeInMs_p % 1000) * 1000000; } else { relTime.it_value.tv_sec = 0; relTime.it_value.tv_nsec = timeInMs_p * 1000000; } DEBUG_LVL_TIMERU_TRACE("%s() Modify timer:%08x timeInMs_p=%ld\n", __func__, *pTimerHdl_p, timeInMs_p); relTime.it_interval.tv_sec = 0; relTime.it_interval.tv_nsec = 0; if (hrtimer_settime(pData->timer, 0, &relTime, NULL) != 0) { DEBUG_LVL_ERROR_TRACE("%s() Error timer_settime!\n", __func__); return kErrorTimerNoTimerCreated; } // copy the TimerArg after the timer is restarted, // so that a timer occurred immediately before hrtimer_settime // won't use the new timerArg and // therefore the old timer cannot be distinguished from the new one. // But if the new timer is too fast, it may get lost. OPLK_MEMCPY(&pData->timerArg, pArgument_p, sizeof(tTimerArg)); return kErrorOk; }
//------------------------------------------------------------------------------ tOplkError hrestimer_deleteTimer(tTimerHdl* pTimerHdl_p) { tOplkError ret = kErrorOk; UINT index; tHresTimerInfo* pTimerInfo; struct itimerspec relTime; DEBUG_LVL_TIMERH_TRACE("%s() Deleting timer:%lx\n", __func__, *pTimerHdl_p); if (pTimerHdl_p == NULL) return kErrorTimerInvalidHandle; if (*pTimerHdl_p == 0) { // no timer created yet return ret; } else { index = HDL_TO_IDX(*pTimerHdl_p); if (index >= TIMER_COUNT) { // invalid handle return kErrorTimerInvalidHandle; } pTimerInfo = &hresTimerInstance_l.aTimerInfo[index]; if (pTimerInfo->eventArg.timerHdl != *pTimerHdl_p) return ret; } // values of 0 disarms the timer relTime.it_value.tv_sec = 0; relTime.it_value.tv_nsec = 0; hrtimer_settime(pTimerInfo->timer, 0, &relTime, NULL); *pTimerHdl_p = 0; pTimerInfo->eventArg.timerHdl = 0; pTimerInfo->pfnCallback = NULL; hrtimer_setCallback(pTimerInfo->timer, (void*)pTimerInfo->pfnCallback, 0); return ret; }
//------------------------------------------------------------------------------ tOplkError hrestimer_modifyTimer(tTimerHdl* pTimerHdl_p, ULONGLONG time_p, tTimerkCallback pfnCallback_p, ULONG argument_p, BOOL fContinue_p) { tOplkError ret = kErrorOk; UINT index; tHresTimerInfo* pTimerInfo; struct itimerspec relTime; if (pTimerHdl_p == NULL) { DEBUG_LVL_ERROR_TRACE("%s() Invalid timer handle\n", __func__); return kErrorTimerInvalidHandle; } if (*pTimerHdl_p == 0) { // no timer created yet, search free timer info structure pTimerInfo = &hresTimerInstance_l.aTimerInfo[0]; for (index = 0; index < TIMER_COUNT; index++, pTimerInfo++) { if (pTimerInfo->eventArg.timerHdl == 0) break; // free structure found } if (index >= TIMER_COUNT) { // no free structure found DEBUG_LVL_ERROR_TRACE("%s() Invalid timer index:%d\n", __func__, index); return kErrorTimerNoTimerCreated; } pTimerInfo->eventArg.timerHdl = HDL_INIT(uiIndex); } else { index = HDL_TO_IDX(*pTimerHdl_p); if (index >= TIMER_COUNT) { // invalid handle DEBUG_LVL_ERROR_TRACE("%s() Invalid timer index:%d\n", __func__, index); return kErrorTimerInvalidHandle; } pTimerInfo = &hresTimerInstance_l.aTimerInfo[index]; } // increase too small time values if (fContinue_p != FALSE) { if (time_p < TIMER_MIN_VAL_CYCLE) time_p = TIMER_MIN_VAL_CYCLE; } else { if (time_p < TIMER_MIN_VAL_SINGLE) time_p = TIMER_MIN_VAL_SINGLE; } /* Increment timer handle (if timer expires right after this statement, the user * would detect an unknown timer handle and discard it) */ pTimerInfo->eventArg.timerHdl = HDL_INC(pTimerInfo->eventArg.timerHdl); *pTimerHdl_p = pTimerInfo->eventArg.timerHdl; /* initialize timer info */ pTimerInfo->eventArg.argument.value = argument_p; pTimerInfo->pfnCallback = pfnCallback_p; hrtimer_setCallback(pTimerInfo->timer, (void*)pTimerInfo->pfnCallback, (void*)&pTimerInfo->eventArg); /*logMsg("set TCB: %p(%p)\n", (int)pTimerInfo->pfnCallback, (int)pTimerInfo->eventArg.argument.value, 0, 0, 0, 0);*/ if (time_p >= 1000000000L) { relTime.it_value.tv_sec = (time_p / 1000000000L); relTime.it_value.tv_nsec = (time_p % 1000000000); } else { relTime.it_value.tv_sec = 0; relTime.it_value.tv_nsec = time_p; } if (fContinue_p) { relTime.it_interval.tv_nsec = relTime.it_value.tv_nsec; relTime.it_interval.tv_sec = relTime.it_value.tv_sec; } else { relTime.it_interval.tv_nsec = 0; relTime.it_interval.tv_sec = 0; } #if 0 DEBUG_LVL_TIMERH_TRACE("hrestimer_modifyTimer() timer=%lx ", pTimerInfo->eventArg.timerHdl); DEBUG_LVL_TIMERH_TRACE(" timeout=%ld:%ld/%ld:%ld\n", relTime.it_value.tv_sec, relTime.it_value.tv_nsec, relTime.it_interval.tv_sec, relTime.it_interval.tv_nsec); #endif hrtimer_settime(pTimerInfo->timer, 0, &relTime, NULL); return ret; }