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); }
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; }
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; }
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); } }
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); }
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); } }
/* 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; } } }
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; }
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); }
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; }
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; }
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; }
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); }
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); }
GEvent *geventEventWait(GListener *pl, delaytime_t timeout) { if (pl->callback || gfxSemCounter(&pl->waitqueue) < 0) return 0; return gfxSemWait(&pl->waitqueue, timeout) ? &pl->event : 0; }