//------------------------------------------------------------------------------ tOplkError timeru_exit(void) { tTimeruData* pTimer; /* cancel thread */ pthread_cancel(timeruInstance_g.processThread); DEBUG_LVL_TIMERU_TRACE("%s() Waiting for thread to exit...\n", __func__); /* wait for thread to terminate */ pthread_join(timeruInstance_g.processThread, NULL); DEBUG_LVL_TIMERU_TRACE("%s()Thread exited\n", __func__); /* free up timer list */ resetTimerList(); while ((pTimer = getNextTimer()) != NULL) { removeTimer(pTimer); OPLK_FREE(pTimer); } pthread_mutex_destroy(&timeruInstance_g.mutex); timeruInstance_g.pFirstTimer = NULL; timeruInstance_g.pLastTimer = NULL; return kErrorOk; }
//------------------------------------------------------------------------------ static void* processThread(void* pArgument_p) { tTimeruData* pTimer; sigset_t awaitedSignal; siginfo_t signalInfo; UNUSED_PARAMETER(pArgument_p); // Uncomment to show the thread ID on Linux (include must also be uncommented)! // DEBUG_LVL_TIMERU_TRACE("%s() ThreadId:%d\n", __func__, syscall(SYS_gettid)); sigemptyset(&awaitedSignal); sigaddset(&awaitedSignal, SIGRTMIN); pthread_sigmask(SIG_BLOCK, &awaitedSignal, NULL); /* loop forever until thread will be canceled */ while (1) { if (sigwaitinfo(&awaitedSignal, &signalInfo) > 0) { pTimer = (tTimeruData*)signalInfo.si_value.sival_ptr; if (pTimer != NULL) /* call callback function of timer */ cbTimer((ULONG)pTimer); else { DEBUG_LVL_ERROR_TRACE("%s() sival_ptr==NULL code=%d\n", __func__, signalInfo.si_code); } } } DEBUG_LVL_TIMERU_TRACE("%s() Exiting!\n", __func__); return NULL; }
//------------------------------------------------------------------------------ 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; }