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