* }
* \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 <bernie@codewiz.org>
*/
#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 <drv/timer.h> /* timer_clock() */