2 * \brief Spawnd state internals for the process manager.
4 * Copyright (c) 2017, ETH Zurich.
7 * This file is distributed under the terms in the attached LICENSE file.
8 * If you do not find this file, copies can be found by writing to:
9 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
12 #include <barrelfish/barrelfish.h>
14 #include "spawnd_state.h"
16 static struct spawnd_state *spawnds[MAX_COREID];
18 errval_t spawnd_state_alloc(coreid_t core_id, struct spawn_binding *b)
20 spawnds[core_id] = (struct spawnd_state*) malloc(
21 sizeof(struct spawnd_state));
22 if (spawnds[core_id] == NULL) {
23 return LIB_ERR_MALLOC_FAIL;
26 spawnds[core_id]->b = b;
27 spawnds[core_id]->core_id = core_id;
28 spawnds[core_id]->queue.head = NULL;
29 spawnds[core_id]->queue.tail = NULL;
34 void spawnd_state_free(coreid_t core_id)
36 if (spawnds[core_id] != NULL) {
37 free(spawnds[core_id]);
41 inline bool spawnd_state_exists(coreid_t core_id)
43 return spawnds[core_id] != NULL;
46 inline struct spawnd_state *spawnd_state_get(coreid_t core_id)
48 return spawnds[core_id];
52 * \brief Enqueue on a waitset queue.
54 * \param q Pointer to queue to enqueue on
55 * \param m Pointer to element to enqueue
57 * \return true if queue was empty, false if not.
59 static bool enqueue_send(struct msg_queue *q, struct msg_queue_elem *m)
61 assert(m->next == NULL);
63 // Enqueue on the queue
67 assert(q->head == NULL);
72 return q->head == q->tail ? true : false;
76 * \brief Dequeues from a waitset queue.
78 * \param q Pointer to queue to dequeue from
80 * \return the newly dequeued element.
82 static struct msg_queue_elem *dequeue_send(struct msg_queue *q)
84 // Queue should have at least one element
85 assert(q->head != NULL && q->tail != NULL);
87 struct msg_queue_elem *e = q->head;
97 * \brief Enqueue an element on a waitset queue IN FRONT.
99 * \param q Pointer to queue to enqueue on
100 * \param m Pointer to element to enqueue
102 * \return true if queue was empty, false if not.
104 static bool enqueue_send_at_front(struct msg_queue *q, struct msg_queue_elem *m)
106 assert(m->next == NULL);
107 if(q->tail == NULL) {
108 assert(q->head == NULL);
115 return q->head == q->tail ? true : false;
118 static void spawnd_send_handler(void *arg)
120 struct spawnd_state *spawnd = (struct spawnd_state*) arg;
121 struct msg_queue *q = &spawnd->queue;
123 // Dequeue next element from the queue
124 struct msg_queue_elem *m = (struct msg_queue_elem*) dequeue_send(q);
126 assert(m->cont != NULL);
128 // Flounder TX busy, need to re-enqueue message.
129 // TODO(razvan): Re-enqueuing at the front of the queue, to preserve
130 // original message order. Could a different strategy be preferrable?
131 enqueue_send_at_front(q, m);
134 if (q->head != NULL) {
135 // Queue is non-empty, therefore re-register.
136 errval_t err = spawnd->b->register_send(spawnd->b, spawnd->b->waitset,
137 MKCONT(spawnd_send_handler,
139 if (err_is_fail(err)) {
140 DEBUG_ERR(err, "regitering for spawnd send");
146 errval_t spawnd_state_enqueue_send(struct spawnd_state *spawnd,
147 struct msg_queue_elem *msg)
151 // If queue was empty, enqueue on waitset
152 if(enqueue_send(&spawnd->queue, msg)) {
153 return spawnd->b->register_send(spawnd->b, spawnd->b->waitset,
154 MKCONT(spawnd_send_handler, spawnd));