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]->sendq.head = NULL;
29 spawnds[core_id]->sendq.tail = NULL;
30 spawnds[core_id]->recvq.head = NULL;
31 spawnds[core_id]->recvq.tail = NULL;
33 b->st = spawnds[core_id];
38 void spawnd_state_free(coreid_t core_id)
40 if (spawnds[core_id] != NULL) {
41 free(spawnds[core_id]);
45 inline bool spawnd_state_exists(coreid_t core_id)
47 return spawnds[core_id] != NULL;
50 inline struct spawnd_state *spawnd_state_get(coreid_t core_id)
52 return spawnds[core_id];
56 * \brief Enqueue on a waitset queue.
58 * \param q Pointer to queue to enqueue on
59 * \param m Pointer to element to enqueue
61 * \return true if queue was empty, false if not.
63 static bool enqueue(struct msg_queue *q, struct msg_queue_elem *m)
65 assert(m->next == NULL);
67 // Enqueue on the queue
71 assert(q->head == NULL);
76 return q->head == q->tail ? true : false;
80 * \brief Dequeues from a waitset queue.
82 * \param q Pointer to queue to dequeue from
84 * \return the newly dequeued element.
86 static struct msg_queue_elem *dequeue(struct msg_queue *q)
88 // Queue should have at least one element
89 assert(q->head != NULL && q->tail != NULL);
91 struct msg_queue_elem *e = q->head;
101 * \brief Enqueue an element on a waitset queue IN FRONT.
103 * \param q Pointer to queue to enqueue on
104 * \param m Pointer to element to enqueue
106 * \return true if queue was empty, false if not.
108 static bool enqueue_at_front(struct msg_queue *q, struct msg_queue_elem *m)
110 assert(m->next == NULL);
111 if(q->tail == NULL) {
112 assert(q->head == NULL);
119 return q->head == q->tail ? true : false;
122 static void spawnd_send_handler(void *arg)
124 struct spawnd_state *spawnd = (struct spawnd_state*) arg;
125 struct msg_queue *q = &spawnd->sendq;
127 // Dequeue next element from the queue
128 struct msg_queue_elem *m = (struct msg_queue_elem*) dequeue(q);
130 assert(m->cont != NULL);
132 // Send continuation succeeded, need to enqueue a receive.
133 struct msg_queue_elem *recvm = (struct msg_queue_elem*) malloc(
134 sizeof(struct msg_queue_elem));
137 enqueue(&spawnd->recvq, recvm);
139 // Send continuation failed, need to re-enqueue message.
140 // TODO(razvan): Re-enqueuing at the front of the queue, to preserve
141 // original message order. Could a different strategy be preferrable?
142 enqueue_at_front(q, m);
145 if (q->head != NULL) {
146 // Queue is non-empty, therefore re-register.
147 errval_t err = spawnd->b->register_send(spawnd->b, spawnd->b->waitset,
148 MKCONT(spawnd_send_handler,
150 if (err_is_fail(err)) {
151 DEBUG_ERR(err, "regitering for spawnd send");
157 errval_t spawnd_state_enqueue_send(struct spawnd_state *spawnd,
158 struct msg_queue_elem *msg)
162 // If queue was empty, enqueue on waitset
163 if(enqueue(&spawnd->sendq, msg)) {
164 return spawnd->b->register_send(spawnd->b, spawnd->b->waitset,
165 MKCONT(spawnd_send_handler, spawnd));
171 void *spawnd_state_dequeue_recv(struct spawnd_state *spawnd)
173 struct msg_queue_elem *m = dequeue(&spawnd->recvq);