/** * \brief Register a closure to be called when a channel is triggered * * In the Future, call the closure on a thread associated with the waitset * when the channel is triggered. Only one closure may be registered per * channel state at any one time. * This function must only be called when enabled. * * \param ws Waitset * \param chan Waitset's per-channel state * \param closure Event handler */ errval_t waitset_chan_register(struct waitset *ws, struct waitset_chanstate *chan, struct event_closure closure) { dispatcher_handle_t handle = disp_disable(); errval_t err = waitset_chan_register_disabled(ws, chan, closure); disp_enable(handle); return err; }
/** * \brief Register a deferred event * * \param ws Waitset * \param delay Delay in microseconds * \param closure Event closure to execute * \param event Storage for event metadata */ errval_t deferred_event_register(struct deferred_event *event, struct waitset *ws, delayus_t delay, struct event_closure closure) { errval_t err; dispatcher_handle_t dh = disp_disable(); err = waitset_chan_register_disabled(ws, &event->waitset_state, closure); if (err_is_ok(err)) { struct dispatcher_generic *dg = get_dispatcher_generic(dh); // XXX: determine absolute time for event (ignoring time since dispatch!) event->time = get_system_time() + delay; // enqueue in sorted list of pending timers for (struct deferred_event *e = dg->deferred_events, *p = NULL; ; p = e, e = e->next) { if (e == NULL || e->time > event->time) { if (p == NULL) { // insert at head assert(e == dg->deferred_events); event->prev = NULL; event->next = e; if (e != NULL) { e->prev = event; } dg->deferred_events = event; } else { event->next = e; event->prev = p; p->next = event; if (e != NULL) { e->prev = event; } } break; } } } update_wakeup_disabled(dh); disp_enable(dh); return err; }