int main(int argc, char **argv) { Timer *timer; CLOCK period = { 1, 0 }; counter = 10; if (1 < argc) counter = strtol(argv[1], NULL, 10); if ((timer = timerCreate(task, NULL, NULL, &period, 0)) == NULL) return 1; sleep(6); timerFree(timer); return 0; }
void clean() { cleanMemory(); freeFileName(); cmdFree(); conFree(); #ifndef NO_GUI colourSpectrumClear(); timerFree(); if (video.sdlStarted) { TTF_Quit(); SDL_Quit(); } #endif }
/*----------------------------------------------------------------------------* * NAME * SchedLoop * * DESCRIPTION * The main function of the background task scheduler. This * invokes tasks as messages become available for them and * delivers timed event calls. * * * RETURNS * void * *----------------------------------------------------------------------------*/ void SchedLoop(void *data) { ThreadInstanceType *thread; uint32 eventBits, timeout; uint32 eventBitsOther; Time now; TimerType *timer; uint16 i; Result result; thread = (ThreadInstanceType *) data; result = EventWait(&thread->eventHandle, _EVENT_WAIT_INFINITE, &eventBits); if (result != _RESULT_SUCCESS) { // Panic(_TECH_FW, _PANIC_FW_UNEXPECTED_VALUE, "Event wait failed"); } eventBitsOther = (eventBits & ~START_EVENT); if (eventBitsOther) { /* If thread is signalled from another thread, by a message put, * then pass this signal to our self. */ EventSet(&thread->eventHandle, eventBitsOther); } /* make sure the Sched loop continues until interrupted */ thread->schedRunning = TRUE; /* Tasks' initialisation functions. */ for (i = 0; i < thread->numberOfTasks; i ++) { thread->currentTask = (Task) (i | (thread->id << _SCHED_QUEUE_SEGMENT_SHIFT)); if (thread->tasks[i].initFunction) { thread->tasks[i].initFunction(&(thread->tasks[i].instanceDataPointer)); } thread->currentTask = _SCHED_TASK_ID; } i = 0; while (thread->schedRunning) { if (thread->pendingMessages > 0) { /* Consider each task in turn. */ while (1) { TaskDefinitionType *task; if (i >= thread->numberOfTasks) { i = 0; } task = &thread->tasks[i]; if (task->messageQueueFirst) { thread->currentTask = (int) (i | (thread->id << _SCHED_QUEUE_SEGMENT_SHIFT)); task->handlerFunction(&(task->instanceDataPointer)); thread->currentTask = _SCHED_TASK_ID; i++; break; } else { i++; } } } /* if no internal messages wait for external event or a timer to to expire */ if (thread->pendingMessages == 0) { /* Currently there is no messages on any of the Scheduler task queues. Wait for a timer or an external event to occur */ if (thread->timerList != NULL) { now = TimeGet(NULL); if (thread->timerList->wrapCount > thread->currentWrapCount) { timeout = (_SCHED_TIME_MAX - now + thread->timerList->when); /* Avoid rounding to zero in division below. */ timeout += 999; } else { if (now < thread->timerList->when) { timeout = TimeSub(thread->timerList->when, now); /* Avoid rounding to zero in division below. */ timeout += 999; } else { timeout = 0; } } timeout /= 1000; if (timeout >= _EVENT_WAIT_INFINITE) { timeout = _EVENT_WAIT_INFINITE - 1; } } else { timeout = _EVENT_WAIT_INFINITE; } } else { timeout = 0; } if (EventWait(&thread->eventHandle, (uint16) timeout, &eventBits) == _RESULT_SUCCESS) { /* background interrupt */ SchedBgint vector; vector = (SchedBgint) (eventBits & BG_INT_MASK); /* Are any background interrupts set? */ if (vector) { uint32 j; j = 0; do { BgIntType *bgint; bgint = &instance->bgint[j]; /* Check if this bgint is set */ if (vector & bgint->eventBit) { /* Clear the bit so the bgint is accounted for. */ vector &= ~bgint->eventBit; thread->currentTask = bgint->qid; bgint->handler(bgint->arg); thread->currentTask = _SCHED_TASK_ID; } j++; } while (vector); } /* a message arriving from outside */ if (EXT_MSG_EVENT & eventBits) { SchedTaskId qi; MessageQueueEntryType *message; MutexLock(&thread->qMutex); while (thread->extMsgQueueFirst != NULL) { /* remove from ext queue */ message = thread->extMsgQueueFirst; thread->extMsgQueueFirst = message->next; message->next = NULL; qi = message->receiver; /* ...store the on the end of the task's message chain. */ if (thread->tasks[qi].messageQueueLast == NULL) { thread->tasks[qi].messageQueueFirst = message; thread->tasks[qi].messageQueueLast = message; } else { thread->tasks[qi].messageQueueLast->next = message; thread->tasks[qi].messageQueueLast = message; } thread->pendingMessages++; } /* At this point the external queue is empty. */ thread->extMsgQueueLast = NULL; MutexUnlock(&thread->qMutex); } /* a sched stop req */ if (STOP_REQ_EVENT & eventBits) { /* return stop cfm and break out of scheduler loop */ thread->schedRunning = FALSE; EventSet(&instance->eventHandle, STOP_CFM_EVENT | (0x0001 << (uint32) thread->id)); break; } } while (thread->timerList) { /* Now, back to timed events. */ now = TimeGet(NULL); /* Handle timer wrap */ adjust_wrap_count(thread, now); if (thread->timerList->wrapCount > thread->currentWrapCount) { /* The earliest deadline is more than 1 wrapCount in the future. */ break; } else { if ((thread->timerList->when > now) && (thread->timerList->wrapCount == thread->currentWrapCount)) { break; } else { /* Run the timed event function. */ timer = thread->timerList; timer->active = FALSE; thread->timerList = timer->next; if (thread->timerList != NULL) { thread->timerList->prev = NULL; } thread->currentTask = timer->queue; timer->eventFunction(timer->id, timer->fniarg, timer->fnvarg); thread->currentTask = _SCHED_TASK_ID; timerFree(thread, timer); } } } } /* while (thread->schedRunning) */ /* wait for deinit req event */ while (1) { eventBits = 0; result = EventWait(&thread->eventHandle, _EVENT_WAIT_INFINITE, &eventBits); if ((result == _RESULT_SUCCESS) && (DEINIT_REQ_EVENT & eventBits)) { SchedTaskId qi; MessageQueueEntryType *message; /* * Pull any messages off the external queue and * put them on the relevant task queue. These may * be put here after we stopped because the sender * had not received its stop event yet. */ while (thread->extMsgQueueFirst != NULL) { /* remove from ext queue */ message = thread->extMsgQueueFirst; thread->extMsgQueueFirst = message->next; message->next = NULL; qi = message->receiver; /* ...store the on the end of the task's message chain. */ if (thread->tasks[qi].messageQueueLast == NULL) { thread->tasks[qi].messageQueueFirst = message; thread->tasks[qi].messageQueueLast = message; } else { thread->tasks[qi].messageQueueLast->next = message; thread->tasks[qi].messageQueueLast = message; } thread->pendingMessages++; } /* deinit all tasks in this scheduler thread and * return deinit cfm */ SchedInstanceTaskDeinit(thread); EventSet(&instance->eventHandle, DEINIT_CFM_EVENT | (0x0001 << (uint32) thread->id)); return; } else if (result != _RESULT_SUCCESS) { GENERROR(("Failure in wait for thread deinit req")); return; } } }
/*----------------------------------------------------------------------------* * NAME * SchedTimerCancel * * DESCRIPTION * Attempts to prevent the timer with identifier "eventid" from * occurring. * * RETURNS * BOOL - true if cancelled, false if the event has already occurred. * *----------------------------------------------------------------------------*/ bool SchedTimerCancel(SchedTid tid, uint16 *pmi, void **pmv) { bool rv; if (tid != _SCHED_TID_INVALID) { uint8 index; index = GetThreadIndex(); if (index < _SCHED_MAX_SEGMENTS) { ThreadInstanceType *thread; TimerType *timer; thread = &instance->thread[index]; /* Unlink the timer from the list. */ timer = thread->timer[tid]; if (timer && timer->active) { TimerType *prev, *next; timer->active = FALSE; rv = TRUE; prev = timer->prev; next = timer->next; if ((prev != NULL) && (next != NULL)) { /* In the middle of the list. */ next->prev = prev; prev->next = next; } else if ((prev == NULL) && (next != NULL)) { /* Removing the list head. */ thread->timerList = next; next->prev = NULL; } else if ((prev != NULL) && (next == NULL)) { /* Removing the list tail. */ prev->next = NULL; } else { /* Removing the only active timer. */ thread->timerList = NULL; } if (pmi != NULL) { *pmi = timer->fniarg; } if (pmv != NULL) { *pmv = timer->fnvarg; } timerFree(thread, timer); } else { rv = FALSE; } } else { rv = FALSE; // Panic(_TECH_FW, _PANIC_FW_UNEXPECTED_VALUE, // "SchedTimerCancel not called from scheduler thread"); } } else { rv = FALSE; } return rv; }