コード例 #1
0
ファイル: gtimer.c プロジェクト: niamster/ChibiOS-GFX
static msg_t GTimerThreadHandler(void *arg) {
	(void)arg;
	GTimer			*pt;
	systime_t		tm;
	systime_t		nxtTimeout;
	systime_t		lastTime;
	GTimerFunction	fn;
	void			*param;

	#if CH_USE_REGISTRY
		chRegSetThreadName("GTimer");
	#endif

	nxtTimeout = TIME_INFINITE;
	lastTime = 0;
	while(1) {
		/* Wait for work to do. */
		chThdYield();					// Give someone else a go no matter how busy we are
		chBSemWaitTimeout(&waitsem, nxtTimeout);
		
	restartTimerChecks:
	
		// Our reference time
		tm = chTimeNow();
		nxtTimeout = TIME_INFINITE;
		
		/* We need to obtain the mutex */
		chMtxLock(&mutex);

		if (pTimerHead) {
			pt = pTimerHead;
			do {
				// Do we have something to do for this timer?
				if ((pt->flags & GTIMER_FLG_JABBED) || (!(pt->flags & GTIMER_FLG_INFINITE) && TimeIsWithin(pt->when, lastTime, tm))) {
				
					// Is this timer periodic?
					if ((pt->flags & GTIMER_FLG_PERIODIC) && pt->period != TIME_IMMEDIATE) {
						// Yes - Update ready for the next period
						if (!(pt->flags & GTIMER_FLG_INFINITE)) {
							// We may have skipped a period.
							// We use this complicated formulae rather than a loop
							//	because the gcc compiler stuffs up the loop so that it
							//	either loops forever or doesn't get executed at all.
							pt->when += ((tm + pt->period - pt->when) / pt->period) * pt->period;
						}

						// We are definitely no longer jabbed
						pt->flags &= ~GTIMER_FLG_JABBED;
						
					} else {
						// No - get us off the timers list
						if (pt->next == pt->prev)
							pTimerHead = 0;
						else {
							pt->next->prev = pt->prev;
							pt->prev->next = pt->next;
							if (pTimerHead == pt)
								pTimerHead = pt->next;
						}
						pt->flags = 0;
					}
					
					// Call the callback function
					fn = pt->fn;
					param = pt->param;
					chMtxUnlock();
					fn(param);
					
					// We no longer hold the mutex, the callback function may have taken a while
					// and our list may have been altered so start again!
					goto restartTimerChecks;
				}
				
				// Find when we next need to wake up
				if (!(pt->flags & GTIMER_FLG_INFINITE) && pt->when - tm < nxtTimeout)
					nxtTimeout = pt->when - tm;
				pt = pt->next;
			} while(pt != pTimerHead);
		}

		// Ready for the next loop
		lastTime = tm;
		chMtxUnlock();
	}
	return 0;
}
コード例 #2
0
ファイル: gtimer.c プロジェクト: bunnie/chibi-ugfx
static DECLARE_THREAD_FUNCTION(GTimerThreadHandler, arg) {
	GTimer			*pt;
	systemticks_t	tm;
	systemticks_t	nxtTimeout;
	systemticks_t	lastTime;
	GTimerFunction	fn;
	void			*param;
	(void)			arg;

	nxtTimeout = TIME_INFINITE;
	lastTime = 0;
	while(1) {
		/* Wait for work to do. */
		gfxYield();					// Give someone else a go no matter how busy we are
		gfxSemWait(&waitsem, nxtTimeout);
		
	restartTimerChecks:
	
		// Our reference time
		tm = gfxSystemTicks();
		nxtTimeout = TIME_INFINITE;
		
		/* We need to obtain the mutex */
		gfxMutexEnter(&mutex);

		if (pTimerHead) {
			pt = pTimerHead;
			do {
				// Do we have something to do for this timer?
				if ((pt->flags & GTIMER_FLG_JABBED) || (!(pt->flags & GTIMER_FLG_INFINITE) && TimeIsWithin(pt->when, lastTime, tm))) {
				
					// Is this timer periodic?
					if ((pt->flags & GTIMER_FLG_PERIODIC) && pt->period != TIME_IMMEDIATE) {
						// Yes - Update ready for the next period
						if (!(pt->flags & GTIMER_FLG_INFINITE)) {
							// We may have skipped a period.
							// We use this complicated formulae rather than a loop
							//	because the gcc compiler stuffs up the loop so that it
							//	either loops forever or doesn't get executed at all.
							pt->when += ((tm + pt->period - pt->when) / pt->period) * pt->period;
						}

						// We are definitely no longer jabbed
						pt->flags &= ~GTIMER_FLG_JABBED;
						
					} else {
						// No - get us off the timers list
						if (pt->next == pt)
							pTimerHead = 0;
						else {
							pt->next->prev = pt->prev;
							pt->prev->next = pt->next;
							if (pTimerHead == pt)
								pTimerHead = pt->next;
						}
						pt->flags = 0;
					}
					
					// Call the callback function
					fn = pt->fn;
					param = pt->param;
					gfxMutexExit(&mutex);
					fn(param);
					
					// We no longer hold the mutex, the callback function may have taken a while
					// and our list may have been altered so start again!
					goto restartTimerChecks;
				}
				
				// Find when we next need to wake up
				if (!(pt->flags & GTIMER_FLG_INFINITE) && pt->when - tm < nxtTimeout)
					nxtTimeout = (pt->when - tm)/ticks2ms;
				pt = pt->next;
			} while(pt != pTimerHead);
		}

		// Ready for the next loop
		lastTime = tm;
		gfxMutexExit(&mutex);
	}
	THREAD_RETURN(0);
}