static void event_queue_runner(void *arg) { struct event_queue *q = arg; errval_t err; assert(q->mode == EVENT_QUEUE_CONTINUOUS); thread_mutex_lock(&q->mutex); // dequeue the next node from the head struct event_queue_node *qn = next_event(q); if (qn == NULL) { // an event was cancelled while we were pending thread_mutex_unlock(&q->mutex); return; } if (q->head == NULL) { // queue is non-empty: trigger ourselves again struct event_closure self = { .handler = event_queue_runner, .arg = arg }; err = waitset_chan_trigger_closure(q->waitset, &q->waitset_state, self); assert(err_is_ok(err)); // shouldn't fail } qn->run = true; thread_mutex_unlock(&q->mutex); // run closure qn->event.handler(qn->event.arg); }
/** * \brief Add a new event to an event queue * * \param q Event queue * \param qn Storage for queue node (uninitialised) * \param event Event closure */ void event_queue_add(struct event_queue *q, struct event_queue_node *qn, struct event_closure event) { errval_t err; qn->event = event; qn->run = false; thread_mutex_lock(&q->mutex); // enqueue at tail if (q->tail == NULL) { assert(q->head == NULL); qn->next = qn->prev = NULL; q->head = q->tail = qn; // was empty: need to trigger queue runner if in continuous mode if (q->mode == EVENT_QUEUE_CONTINUOUS) { struct event_closure runner = { .handler = event_queue_runner, .arg = q }; err = waitset_chan_trigger_closure(q->waitset, &q->waitset_state, runner); assert(err_is_ok(err)); // shouldn't fail } } else {
errval_t flounder_support_register(struct waitset *ws, struct waitset_chanstate *wc, struct event_closure ec, bool trigger_now) { if (trigger_now) { return waitset_chan_trigger_closure(ws, wc, ec); } else { return waitset_chan_register(ws, wc, ec); } }
static void span_slave_done_request(struct interdisp_binding *b) { USER_PANIC("shouldn't be called"); struct waitset_chanstate *cs = malloc(sizeof(struct waitset_chanstate)); // Signal the default waitset of this event struct event_closure closure = { .handler = span_slave_done_handler, .arg = cs, }; waitset_chanstate_init(cs, CHANTYPE_EVENT_QUEUE); errval_t err = waitset_chan_trigger_closure(get_default_waitset(), cs, closure); if(err_is_fail(err)) { USER_PANIC_ERR(err, "Triggering default waitset"); } }
/** * \brief Handled for dispatcher_initialized msg type * * Called when a recently spanned dispatcher has initialized. * Store it's connection object, and upcall into the registered callback */ static void dispatcher_initialized(struct interdisp_binding *st, genvaddr_t id) { struct span_domain_state *span_domain_state = (struct span_domain_state*)(uintptr_t)id; // Signal the default waitset of this event struct event_closure closure = { .handler = dispatcher_initialized_handler, .arg = span_domain_state, }; waitset_chanstate_init(&span_domain_state->initev, CHANTYPE_EVENT_QUEUE); errval_t err = waitset_chan_trigger_closure(get_default_waitset(), &span_domain_state->initev, closure); if(err_is_fail(err)) { USER_PANIC_ERR(err, "Triggering default waitset"); } }