Beispiel #1
0
	bool_t gfxQueueFSyncInsert(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, gfxQueueASyncItem *pafter, delaytime_t ms) {
		if (!pitem) return;				// Safety
		gfxSemInit(&pitem->sem, 0, 1);

		gfxSystemLock();
		if (pafter && gfxQueueGSyncIsInI(pqueue, pafter)) {
			pitem->next = pafter->next;
			pafter->next = pitem;
			if (pqueue->tail == pafter)
				pqueue->tail = pitem;
		} else {
			pitem->next = 0;
			if (!pqueue->head) {
				pqueue->head = pqueue->tail = pitem;
			} else {
				pqueue->tail->next = pitem;
				pqueue->tail = pitem;
			}
		}
		gfxSystemUnlock();

		gfxSemSignal(&pqueue->sem);

		return gfxSemWait(&pitem->sem, ms);

	}
Beispiel #2
0
GEvent *geventEventWait(GListener *pl, delaytime_t timeout) {
	gfxMutexEnter(&geventMutex);
	// Don't allow waiting if we are on callbacks or if there is already a thread waiting
	if (pl->callback || (pl->flags & GLISTENER_WAITING)) {
		gfxMutexExit(&geventMutex);
		return 0;
	}

	// Check to see if there is a pending event ready for us
	if ((pl->flags & GLISTENER_PENDING)) {
		pl->flags &= ~GLISTENER_PENDING;				// We have now got this
		pl->flags |= GLISTENER_EVENTBUSY;				// Event buffer is definitely busy
		gfxMutexExit(&geventMutex);
		return &pl->event;
	}

	// No - wait for one.
	pl->flags &= ~GLISTENER_EVENTBUSY;				// Event buffer is definitely not busy
	pl->flags |= GLISTENER_WAITING;					// We will now be waiting on the thread
	gfxMutexExit(&geventMutex);
	if (gfxSemWait(&pl->waitqueue, timeout))
		return &pl->event;

	// Timeout - clear the waiting flag.
	// We know this is safe as any other thread will still think there is someone waiting.
	gfxMutexEnter(&geventMutex);
	pl->flags &= ~GLISTENER_WAITING;
	gfxMutexExit(&geventMutex);
	return 0;
}
Beispiel #3
0
	gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, delaytime_t ms) {
		gfxQueueGSyncItem	*pi;

		if (!gfxSemWait(&pqueue->sem, ms)) return 0;
		gfxSystemLock();
		pi = pqueue->head;
		pqueue->head = pi->next;
		gfxSytemUnlock();
		return pi;
	}
Beispiel #4
0
void geventDetachSource(GListener *pl, GSourceHandle gsh) {
	if (pl) {
		gfxMutexEnter(&geventMutex);
		deleteAssignments(pl, gsh);
		if (!gsh && gfxSemCounter(&pl->waitqueue) < 0) {
			gfxSemWait(&pl->eventlock, TIME_INFINITE);		// Obtain the buffer lock
			pl->event.type = GEVENT_EXIT;					// Set up the EXIT event
			gfxSemSignal(&pl->waitqueue);					// Wake up the listener
			gfxSemSignal(&pl->eventlock);					// Release the buffer lock
		}
		gfxMutexExit(&geventMutex);
	}
}
Beispiel #5
0
	bool_t gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms) {
		gfxSemInit(&pitem->sem, 0, 1);

		gfxSystemLock();
		pitem->next = pqueue->head;
		pqueue->head = pitem;
		if (!pitem->next)
			pqueue->tail = pitem;
		gfxSystemUnlock();

		gfxSemSignal(&pqueue->sem);
		return gfxSemWait(&pitem->sem, ms);
	}
Beispiel #6
0
void geventRegisterCallback(GListener *pl, GEventCallbackFn fn, void *param) {
	if (pl) {
		gfxMutexEnter(&geventMutex);
		gfxSemWait(&pl->eventlock, TIME_INFINITE);			// Obtain the buffer lock
		pl->param = param;									// Set the param
		pl->callback = fn;									// Set the callback function
		if (gfxSemCounter(&pl->waitqueue) < 0) {
			pl->event.type = GEVENT_EXIT;			// Set up the EXIT event
			gfxSemSignal(&pl->waitqueue);			// Wake up the listener
		}
		gfxSemSignal(&pl->eventlock);				// Release the buffer lock
		gfxMutexExit(&geventMutex);
	}
}
Beispiel #7
0
/*	Null is treated as a wildcard. */
static void deleteAssignments(GListener *pl, GSourceHandle gsh) {
	GSourceListener *psl;

	for(psl = Assignments; psl < Assignments+GEVENT_MAX_SOURCE_LISTENERS; psl++) {
		if ((!pl || psl->pListener == pl) && (!gsh || psl->pSource == gsh)) {
			if (gfxSemCounter(&psl->pListener->waitqueue) < 0) {
				gfxSemWait(&psl->pListener->eventlock, TIME_INFINITE);	// Obtain the buffer lock
				psl->pListener->event.type = GEVENT_EXIT;				// Set up the EXIT event
				gfxSemSignal(&psl->pListener->waitqueue);				// Wake up the listener
				gfxSemSignal(&psl->pListener->eventlock);				// Release the buffer lock
			}
			psl->pListener = 0;
		}
	}
}
Beispiel #8
0
	gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms) {
		gfxQueueFSyncItem	*pi;

		if (!gfxSemWait(&pqueue->sem, ms))
			return 0;

		gfxSystemLock();
		pi = pqueue->head;
		pqueue->head = pi->next;
		pi->next = 0;
		gfxSystemUnlock();

		gfxSemSignal(&pi->sem);
		gfxSemDestroy(&pi->sem);

		return pi;
	}
Beispiel #9
0
	bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms) {
		if (!pitem) return;				// Safety
		gfxSemInit(&pitem->sem, 0, 1);
		pitem->next = 0;

		gfxSystemLock();
		if (!pqueue->head) {
			pqueue->head = pqueue->tail = pitem;
		} else {
			pqueue->tail->next = pitem;
			pqueue->tail = pitem;
		}
		gfxSystemUnlock();

		gfxSemSignal(&pqueue->sem);

		return gfxSemWait(&pitem->sem, ms);
	}
Beispiel #10
0
bool_t _gwinDrawStart(GHandle gh) {
	// This test should occur inside the lock. We do this
	//	here as well as an early out (more efficient).
	if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
		return FALSE;

	// Obtain the drawing lock
	gfxSemWait(&gwinsem, TIME_INFINITE);

	// Re-test visibility as we may have waited a while
	if (!(gh->flags & GWIN_FLG_SYSVISIBLE)) {
		_gwinDrawEnd(gh);
		return FALSE;
	}

	// OK - we are ready to draw.
	#if GDISP_NEED_CLIP
		gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
	#endif
	return TRUE;
}
Beispiel #11
0
bool_t geventAttachSource(GListener *pl, GSourceHandle gsh, unsigned flags) {
	GSourceListener *psl, *pslfree;

	// Safety first
	if (!pl || !gsh) {
		GEVENT_ASSERT(FALSE);
		return FALSE;
	}

	gfxMutexEnter(&geventMutex);

	// Check if this pair is already in the table (scan for a free slot at the same time)
	pslfree = 0;
	for(psl = Assignments; psl < Assignments+GEVENT_MAX_SOURCE_LISTENERS; psl++) {
		
		if (pl == psl->pListener && gsh == psl->pSource) {
			// Just update the flags
			gfxSemWait(&pl->eventlock, TIME_INFINITE);		// Safety first - just in case a source is using it
			psl->listenflags = flags;
			gfxSemSignal(&pl->eventlock);			// Release this lock
			gfxMutexExit(&geventMutex);
			return TRUE;
		}
		if (!pslfree && !psl->pListener)
			pslfree = psl;
	}
	
	// A free slot was found - allocate it
	if (pslfree) {
		pslfree->pListener = pl;
		pslfree->pSource = gsh;
		pslfree->listenflags = flags;
		pslfree->srcflags = 0;
	}
	gfxMutexExit(&geventMutex);
	GEVENT_ASSERT(pslfree != 0);
	return pslfree != 0;
}
Beispiel #12
0
GSourceListener *geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr) {
	GSourceListener *psl;

	// Safety first
	if (!gsh)
		return 0;

	gfxMutexEnter(&geventMutex);

	// Unlock the last listener event buffer
	if (lastlr)
		gfxSemSignal(&lastlr->pListener->eventlock);
		
	// Loop through the table looking for attachments to this source
	for(psl = lastlr ? (lastlr+1) : Assignments; psl < Assignments+GEVENT_MAX_SOURCE_LISTENERS; psl++) {
		if (gsh == psl->pSource) {
			gfxSemWait(&psl->pListener->eventlock, TIME_INFINITE);		// Obtain a lock on the listener event buffer
			gfxMutexExit(&geventMutex);
			return psl;
		}
	}
	gfxMutexExit(&geventMutex);
	return 0;
}
Beispiel #13
0
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);
}
Beispiel #14
0
void _gwinFlushRedraws(GRedrawMethod how) {
	GHandle		gh;

	// Do we really need to do anything?
	if (!RedrawPending)
		return;

	// Obtain the drawing lock
	if (how == REDRAW_WAIT)
		gfxSemWait(&gwinsem, TIME_INFINITE);
	else if (how == REDRAW_NOWAIT && !gfxSemWait(&gwinsem, TIME_IMMEDIATE))
		// Someone is drawing - They will do the redraw when they are finished
		return;

	// Do loss of visibility first
	while ((RedrawPending & DOREDRAW_INVISIBLES)) {
		RedrawPending &= ~DOREDRAW_INVISIBLES;				// Catch new requests

		for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
			if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) != GWIN_FLG_NEEDREDRAW)
				continue;

			// Do the redraw
			#if GDISP_NEED_CLIP
				gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
				_GWINwm->vmt->Redraw(gh);
				gdispGUnsetClip(gh->display);
			#else
				_GWINwm->vmt->Redraw(gh);
			#endif

			// Postpone further redraws
			#if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP
				if (how == REDRAW_NOWAIT) {
					RedrawPending |= DOREDRAW_INVISIBLES;
					TriggerRedraw();
					goto releaselock;
				}
			#endif
		}
	}

	// Do the visible windows next
	while ((RedrawPending & DOREDRAW_VISIBLES)) {
		RedrawPending &= ~DOREDRAW_VISIBLES;				// Catch new requests

		for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
			if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE))
				continue;

			// Do the redraw
			#if GDISP_NEED_CLIP
				gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
				_GWINwm->vmt->Redraw(gh);
				gdispGUnsetClip(gh->display);
			#else
				_GWINwm->vmt->Redraw(gh);
			#endif

			// Postpone further redraws (if there are any and the options are set right)
			#if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP
				if (how == REDRAW_NOWAIT) {
					while((gh = gwinGetNextWindow(gh))) {
						if ((gh->flags & (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_NEEDREDRAW|GWIN_FLG_SYSVISIBLE)) {
							RedrawPending |= DOREDRAW_VISIBLES;
							TriggerRedraw();
							break;
						}
					}
					goto releaselock;
				}
			#endif
		}
	}

	#if !GWIN_REDRAW_IMMEDIATE && !GWIN_REDRAW_SINGLEOP
		releaselock:
	#endif

	// Release the lock
	if (how == REDRAW_WAIT || how == REDRAW_NOWAIT)
		gfxSemSignal(&gwinsem);
}
Beispiel #15
0
GEvent *geventEventWait(GListener *pl, delaytime_t timeout) {
	if (pl->callback || gfxSemCounter(&pl->waitqueue) < 0)
		return 0;
	return gfxSemWait(&pl->waitqueue, timeout) ? &pl->event : 0;
}