void geventSendEvent(GSourceListener *psl) { gfxMutexEnter(&geventMutex); if (psl->pListener->callback) { // Mark it back as free and as sent. This is early to be marking as free but it protects // if the callback alters the listener in any way psl->pListener->flags &= ~(GLISTENER_WITHSOURCE|GLISTENER_EVENTBUSY|GLISTENER_PENDING); gfxMutexExit(&geventMutex); // Do the callback psl->pListener->callback(psl->pListener->param, &psl->pListener->event); } else { // Wake up the listener psl->pListener->flags &= ~GLISTENER_WITHSOURCE; if ((psl->pListener->flags & GLISTENER_WAITING)) { psl->pListener->flags &= ~(GLISTENER_WAITING|GLISTENER_PENDING); gfxSemSignal(&psl->pListener->waitqueue); } else psl->pListener->flags |= GLISTENER_PENDING; // The listener thread will free the event buffer when ready gfxMutexExit(&geventMutex); } }
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; }
GEvent *geventGetEventBuffer(GSourceListener *psl) { gfxMutexEnter(&geventMutex); if ((psl->pListener->flags & GLISTENER_EVENTBUSY)) { // Oops - event buffer is still in use gfxMutexExit(&geventMutex); return 0; } // Allocate the event buffer psl->pListener->flags |= (GLISTENER_WITHSOURCE|GLISTENER_EVENTBUSY); gfxMutexExit(&geventMutex); return &psl->pListener->event; }
void geventSendEvent(GSourceListener *psl) { gfxMutexEnter(&geventMutex); if (psl->pListener->callback) { // This test needs to be taken inside the mutex gfxMutexExit(&geventMutex); // We already know we have the event lock psl->pListener->callback(psl->pListener->param, &psl->pListener->event); } else { // Wake up the listener if (gfxSemCounter(&psl->pListener->waitqueue) <= 0) gfxSemSignal(&psl->pListener->waitqueue); gfxMutexExit(&geventMutex); } }
void geventDetachSource(GListener *pl, GSourceHandle gsh) { if (pl) { gfxMutexEnter(&geventMutex); deleteAssignments(pl, gsh); if (!gsh) doExitEvent(pl); gfxMutexExit(&geventMutex); } }
void gtimerJab(GTimer *pt) { gfxMutexEnter(&mutex); // Jab it! pt->flags |= GTIMER_FLG_JABBED; // Bump the thread gfxSemSignal(&waitsem); gfxMutexExit(&mutex); }
void geventRegisterCallback(GListener *pl, GEventCallbackFn fn, void *param) { if (pl) { gfxMutexEnter(&geventMutex); doExitEvent(pl); pl->param = param; // Set the param pl->callback = fn; // Set the callback function if (fn) pl->flags &= ~GLISTENER_EVENTBUSY; // The event buffer is immediately available gfxMutexExit(&geventMutex); } }
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 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; }
void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, bool_t periodic, delaytime_t millisec) { gfxMutexEnter(&mutex); // Start our thread if not already going if (!hThread) { hThread = gfxThreadCreate(waTimerThread, GTIMER_THREAD_WORKAREA_SIZE, GTIMER_THREAD_PRIORITY, GTimerThreadHandler, 0); if (hThread) {gfxThreadClose(hThread);} // We never really need the handle again } // Is this already scheduled? if (pt->flags & GTIMER_FLG_SCHEDULED) { // Cancel it! if (pt->next == pt) pTimerHead = 0; else { pt->next->prev = pt->prev; pt->prev->next = pt->next; if (pTimerHead == pt) pTimerHead = pt->next; } } // Set up the timer structure pt->fn = fn; pt->param = param; pt->flags = GTIMER_FLG_SCHEDULED; if (periodic) pt->flags |= GTIMER_FLG_PERIODIC; if (millisec == TIME_INFINITE) { pt->flags |= GTIMER_FLG_INFINITE; pt->period = TIME_INFINITE; } else { pt->period = gfxMillisecondsToTicks(millisec); pt->when = gfxSystemTicks() + pt->period; } // Just pop it on the end of the queue if (pTimerHead) { pt->next = pTimerHead; pt->prev = pTimerHead->prev; pt->prev->next = pt; pt->next->prev = pt; } else pt->next = pt->prev = pTimerHead = pt; // Bump the thread if (!(pt->flags & GTIMER_FLG_INFINITE)) gfxSemSignal(&waitsem); gfxMutexExit(&mutex); }
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); } }
GSourceListener *geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr) { GSourceListener *psl; // Safety first if (!gsh) return 0; gfxMutexEnter(&geventMutex); // Unlock the last listener event buffer if it wasn't used. if (lastlr && lastlr->pListener && (lastlr->pListener->flags & GLISTENER_WITHSOURCE)) lastlr->pListener->flags &= ~(GLISTENER_WITHSOURCE|GLISTENER_EVENTBUSY); // 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) { gfxMutexExit(&geventMutex); return psl; } } gfxMutexExit(&geventMutex); return 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; }
void gtimerStop(GTimer *pt) { gfxMutexEnter(&mutex); if (pt->flags & GTIMER_FLG_SCHEDULED) { // Cancel it! if (pt->next == pt) pTimerHead = 0; else { pt->next->prev = pt->prev; pt->prev->next = pt->next; if (pTimerHead == pt) pTimerHead = pt->next; } // Make sure we know the structure is dead! pt->flags = 0; } gfxMutexExit(&mutex); }
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 gfxSystemUnlock(void) { gfxMutexExit(&SystemMutex); }
static void exitLock(GHandle gh) { gdispGUnsetClip(gh->display); gfxMutexExit(&gmutex); }
void geventDetachSourceListeners(GSourceHandle gsh) { gfxMutexEnter(&geventMutex); deleteAssignments(0, gsh); gfxMutexExit(&geventMutex); }