From a3f0f5671733a6c3e29c49fdd9ea472a8e1637bf Mon Sep 17 00:00:00 2001 From: arighi Date: Mon, 7 Mar 2011 18:34:01 +0000 Subject: [PATCH] event: introduce event_select() Add the following primitive to wait the completion of multiple generic events: int event_select(Event **evs, int n, ticks_t timeout); git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4757 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/mware/event.h | 97 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/bertos/mware/event.h b/bertos/mware/event.h index 0111ef8c..94121413 100644 --- a/bertos/mware/event.h +++ b/bertos/mware/event.h @@ -87,6 +87,50 @@ * } * \endcode * + * Example usage: wait multiple generic events via event_select() + * \code + * Event ev1; + * Event ev2; + * + * void event_notifier(void) + * { + * Event *evs[] = { &ev1, &ev2 }; + * + * event_initGeneric(&ev1); + * event_initGeneric(&ev2); + * + * while (1) + * { + * int id = event_select(evs, countof(evs), + * ms_to_ticks(100)); + * if (id < 0) + * { + * kprintf("no IRQ\n"); + * continue; + * } + * kprintf("IRQ %d happened\n", id); + * } + * } + * + * void irq1_handler(void) + * { + * // do something + * ... + * + * // notify the completion of event 1 + * event_do(&ev1); + * } + * + * void irq2_handler(void) + * { + * // do something + * ... + * + * // notify the completion of event 2 + * event_do(&ev2); + * } + * \endcode + * * \author Bernie Innocenti */ @@ -242,6 +286,59 @@ INLINE void event_wait(Event *e) #endif } +/** + * Wait for multiple events + * + * On success return the offset in the \a evs vector of the Event that + * happened, -1 if the timeout expires. + * + * NOTE: timeout == 0 means no timeout. + */ +#if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS +INLINE int event_select(Event **evs, int n, ticks_t timeout) +{ + sigmask_t mask = (1 << n) - 1; + int i; + + ASSERT(n <= SIG_USER_MAX); + for (i = 0; i < n; i++) + { + Event *e = evs[i]; + /* Map each event to a distinct signal bit */ + event_initSignal(e, proc_current(), 1 << i); + } + mask = timeout ? sig_waitTimeout(mask, timeout) : sig_wait(mask); + i = UINT8_LOG2(mask); + + return i < n ? i : -1; +} +#else +INLINE int event_select(Event **evs, int n, ticks_t timeout) +{ + ticks_t end = timer_clock() + timeout; + int i; + + while (1) + { + for (i = 0; i < n; i++) + { + Event *e = evs[i]; + if (ACCESS_SAFE(e->Ev.Gen.completed) == true) + { + e->Ev.Gen.completed = false; + MEMORY_BARRIER; + return i; + } + } + if (timeout && TIMER_AFTER(timer_clock(), end)) + break; + cpu_relax(); + } + return -1; +} +#endif + + #if CONFIG_TIMER_EVENTS #include /* timer_clock() */ -- 2.25.1