1 /*
2 * mbox.c
3 *
4 * Simple thread mailbox interface
5 */
6
7 #include "thread.h"
8 #include "mbox.h"
9 #include <errno.h>
10
mbox_init(struct mailbox * mbox,size_t size)11 void mbox_init(struct mailbox *mbox, size_t size)
12 {
13 if (!!mbox) {
14 sem_init(&mbox->prod_sem, size); /* All slots empty */
15 sem_init(&mbox->cons_sem, 0); /* No slots full */
16 sem_init(&mbox->head_sem, 1); /* Head mutex */
17 sem_init(&mbox->tail_sem, 1); /* Tail mutex */
18
19 mbox->wrap = &mbox->data[size];
20 mbox->head = &mbox->data[0];
21 mbox->tail = &mbox->data[0];
22 }
23 };
24
mbox_post(struct mailbox * mbox,void * msg,mstime_t timeout)25 int mbox_post(struct mailbox *mbox, void *msg, mstime_t timeout)
26 {
27 if (!mbox_is_valid(mbox))
28 return ENOMEM;
29 if (sem_down(&mbox->prod_sem, timeout) == (mstime_t)-1)
30 return ENOMEM;
31 sem_down(&mbox->head_sem, 0);
32
33 *mbox->head = msg;
34 mbox->head++;
35 if (mbox->head == mbox->wrap)
36 mbox->head = &mbox->data[0];
37
38 sem_up(&mbox->head_sem);
39 sem_up(&mbox->cons_sem);
40 return 0;
41 }
42
mbox_fetch(struct mailbox * mbox,void ** msg,mstime_t timeout)43 mstime_t mbox_fetch(struct mailbox *mbox, void **msg, mstime_t timeout)
44 {
45 mstime_t t;
46
47 if (!mbox)
48 return -1;
49 t = sem_down(&mbox->cons_sem, timeout);
50 if (t == (mstime_t)-1)
51 return -1;
52 t += sem_down(&mbox->tail_sem, 0);
53
54 if (msg)
55 *msg = *mbox->tail;
56 mbox->tail++;
57 if (mbox->tail == mbox->wrap)
58 mbox->tail = &mbox->data[0];
59
60 sem_up(&mbox->tail_sem);
61 sem_up(&mbox->prod_sem);
62 return t;
63 }
64