xref: /minix3/minix/lib/libddekit/src/msg_queue.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc #include "common.h"
2*433d6423SLionel Sambuc 
3*433d6423SLionel Sambuc #include <ddekit/memory.h>
4*433d6423SLionel Sambuc #include <ddekit/minix/msg_queue.h>
5*433d6423SLionel Sambuc #include <ddekit/panic.h>
6*433d6423SLionel Sambuc #include <ddekit/semaphore.h>
7*433d6423SLionel Sambuc 
8*433d6423SLionel Sambuc #define MESSAGE_QUEUE_SIZE 16
9*433d6423SLionel Sambuc 
10*433d6423SLionel Sambuc #ifdef DDEBUG_LEVEL_MSG_Q
11*433d6423SLionel Sambuc #undef DDEBUG
12*433d6423SLionel Sambuc #define DDEBUG DDEBUG_LEVEL_MSG_Q
13*433d6423SLionel Sambuc #endif
14*433d6423SLionel Sambuc 
15*433d6423SLionel Sambuc #include "debug.h"
16*433d6423SLionel Sambuc 
17*433d6423SLionel Sambuc struct ddekit_minix_msg_q {
18*433d6423SLionel Sambuc 
19*433d6423SLionel Sambuc 	unsigned from, to;
20*433d6423SLionel Sambuc 
21*433d6423SLionel Sambuc 	message messages[MESSAGE_QUEUE_SIZE];
22*433d6423SLionel Sambuc 	int ipc_status[MESSAGE_QUEUE_SIZE];
23*433d6423SLionel Sambuc 	ddekit_sem_t *msg_w_sem, *msg_r_sem;
24*433d6423SLionel Sambuc 	int msg_r_pos, msg_w_pos;
25*433d6423SLionel Sambuc 
26*433d6423SLionel Sambuc 	struct ddekit_minix_msg_q *next;
27*433d6423SLionel Sambuc };
28*433d6423SLionel Sambuc 
29*433d6423SLionel Sambuc static struct ddekit_minix_msg_q * _list = NULL;
30*433d6423SLionel Sambuc static void _ddekit_minix_queue_msg
31*433d6423SLionel Sambuc                    (struct ddekit_minix_msg_q *mq, message *m, int ipc_status);
32*433d6423SLionel Sambuc 
33*433d6423SLionel Sambuc /*****************************************************************************
34*433d6423SLionel Sambuc  *      ddekit_minix_create_msg_q                                            *
35*433d6423SLionel Sambuc  ****************************************************************************/
36*433d6423SLionel Sambuc struct ddekit_minix_msg_q *
ddekit_minix_create_msg_q(unsigned from,unsigned to)37*433d6423SLionel Sambuc ddekit_minix_create_msg_q(unsigned from, unsigned to)
38*433d6423SLionel Sambuc {
39*433d6423SLionel Sambuc 	struct ddekit_minix_msg_q *mq =  (struct ddekit_minix_msg_q *)
40*433d6423SLionel Sambuc 	    ddekit_simple_malloc(sizeof(struct ddekit_minix_msg_q));
41*433d6423SLionel Sambuc 
42*433d6423SLionel Sambuc 	mq->from = from;
43*433d6423SLionel Sambuc 	mq->to   = to;
44*433d6423SLionel Sambuc 	mq->msg_w_pos = 0;
45*433d6423SLionel Sambuc 	mq->msg_r_pos = 0;
46*433d6423SLionel Sambuc 
47*433d6423SLionel Sambuc 	mq->msg_r_sem = ddekit_sem_init(0);
48*433d6423SLionel Sambuc 	mq->msg_w_sem = ddekit_sem_init(MESSAGE_QUEUE_SIZE);
49*433d6423SLionel Sambuc 
50*433d6423SLionel Sambuc 	/* TODO: check for overlapping message ranges */
51*433d6423SLionel Sambuc 	mq->next = _list;
52*433d6423SLionel Sambuc 	_list     = mq;
53*433d6423SLionel Sambuc 
54*433d6423SLionel Sambuc 	DDEBUG_MSG_VERBOSE("created msg_q from %x to %x\n", from , to);
55*433d6423SLionel Sambuc 
56*433d6423SLionel Sambuc 	return mq;
57*433d6423SLionel Sambuc }
58*433d6423SLionel Sambuc 
59*433d6423SLionel Sambuc /*****************************************************************************
60*433d6423SLionel Sambuc  *      ddekit_minix_deregister_msg_q                                        *
61*433d6423SLionel Sambuc  ****************************************************************************/
ddekit_minix_deregister_msg_q(struct ddekit_minix_msg_q * mq)62*433d6423SLionel Sambuc void ddekit_minix_deregister_msg_q(struct ddekit_minix_msg_q *mq)
63*433d6423SLionel Sambuc {
64*433d6423SLionel Sambuc 	struct ddekit_minix_msg_q *prev =_list, *it;
65*433d6423SLionel Sambuc 
66*433d6423SLionel Sambuc 	for (it = _list->next; it != NULL ; it = it->next) {
67*433d6423SLionel Sambuc 		if (it == mq) {
68*433d6423SLionel Sambuc 			prev->next = it->next;
69*433d6423SLionel Sambuc 			break;
70*433d6423SLionel Sambuc 		}
71*433d6423SLionel Sambuc 		prev=it;
72*433d6423SLionel Sambuc 	}
73*433d6423SLionel Sambuc 
74*433d6423SLionel Sambuc 	ddekit_sem_deinit(mq->msg_r_sem);
75*433d6423SLionel Sambuc 	ddekit_sem_deinit(mq->msg_w_sem);
76*433d6423SLionel Sambuc 
77*433d6423SLionel Sambuc 	ddekit_simple_free(mq);
78*433d6423SLionel Sambuc 
79*433d6423SLionel Sambuc 	DDEBUG_MSG_VERBOSE("destroyed msg_q from \n");
80*433d6423SLionel Sambuc }
81*433d6423SLionel Sambuc 
82*433d6423SLionel Sambuc /*****************************************************************************
83*433d6423SLionel Sambuc  *     _ddekit_minix_queue_msg                                               *
84*433d6423SLionel Sambuc  ****************************************************************************/
85*433d6423SLionel Sambuc static void
_ddekit_minix_queue_msg(struct ddekit_minix_msg_q * mq,message * m,int ipc_status)86*433d6423SLionel Sambuc _ddekit_minix_queue_msg (
87*433d6423SLionel Sambuc 	struct ddekit_minix_msg_q *mq,
88*433d6423SLionel Sambuc 	message *m,
89*433d6423SLionel Sambuc 	int ipc_status
90*433d6423SLionel Sambuc )
91*433d6423SLionel Sambuc {
92*433d6423SLionel Sambuc 	int full;
93*433d6423SLionel Sambuc 	full = ddekit_sem_down_try(mq->msg_w_sem);
94*433d6423SLionel Sambuc 
95*433d6423SLionel Sambuc 	if (full) {
96*433d6423SLionel Sambuc 		/* Our message queue is full... */
97*433d6423SLionel Sambuc 		int result;
98*433d6423SLionel Sambuc 		DDEBUG_MSG_WARN("Receive queue is full. Dropping request.\n");
99*433d6423SLionel Sambuc 
100*433d6423SLionel Sambuc 		/* XXX should reply to the sender with EIO or so, but for that
101*433d6423SLionel Sambuc 		 * we would need to look at the request and find a suitable
102*433d6423SLionel Sambuc 		 * reply code..
103*433d6423SLionel Sambuc 		 */
104*433d6423SLionel Sambuc 	} else {
105*433d6423SLionel Sambuc 		/* queue the message */
106*433d6423SLionel Sambuc 		memcpy(&mq->messages[mq->msg_w_pos], m, sizeof(message));
107*433d6423SLionel Sambuc 		mq->ipc_status[mq->msg_w_pos] = ipc_status;
108*433d6423SLionel Sambuc 		if (++mq->msg_w_pos == MESSAGE_QUEUE_SIZE) {
109*433d6423SLionel Sambuc 			mq->msg_w_pos = 0;
110*433d6423SLionel Sambuc 		}
111*433d6423SLionel Sambuc 		DDEBUG_MSG_VERBOSE("ddekit_minix_queue_msg: queueing msg %x\n",
112*433d6423SLionel Sambuc 		                    m->m_type);
113*433d6423SLionel Sambuc 		ddekit_sem_up(mq->msg_r_sem);
114*433d6423SLionel Sambuc 	}
115*433d6423SLionel Sambuc }
116*433d6423SLionel Sambuc 
117*433d6423SLionel Sambuc /*****************************************************************************
118*433d6423SLionel Sambuc  *       ddekit_minix_queue_msg                                              *
119*433d6423SLionel Sambuc  ****************************************************************************/
ddekit_minix_queue_msg(message * m,int ipc_status)120*433d6423SLionel Sambuc void ddekit_minix_queue_msg(message *m, int ipc_status)
121*433d6423SLionel Sambuc {
122*433d6423SLionel Sambuc 	struct ddekit_minix_msg_q *it, *mq = NULL;
123*433d6423SLionel Sambuc 
124*433d6423SLionel Sambuc 	for (it = _list; it !=NULL ; it = it->next) {
125*433d6423SLionel Sambuc 		if (m->m_type >= it->from && m->m_type <= it->to) {
126*433d6423SLionel Sambuc 			mq = it;
127*433d6423SLionel Sambuc 			break;
128*433d6423SLionel Sambuc 		}
129*433d6423SLionel Sambuc 	}
130*433d6423SLionel Sambuc 	if (mq == NULL) {
131*433d6423SLionel Sambuc 		DDEBUG_MSG_VERBOSE("no q for msgtype %x\n", m->m_type);
132*433d6423SLionel Sambuc 		return;
133*433d6423SLionel Sambuc 	}
134*433d6423SLionel Sambuc 	_ddekit_minix_queue_msg(mq, m, ipc_status);
135*433d6423SLionel Sambuc }
136*433d6423SLionel Sambuc 
137*433d6423SLionel Sambuc /*****************************************************************************
138*433d6423SLionel Sambuc  *        ddekit_minix_rcv                                                   *
139*433d6423SLionel Sambuc  ****************************************************************************/
ddekit_minix_rcv(struct ddekit_minix_msg_q * mq,message * m,int * ipc_status)140*433d6423SLionel Sambuc void ddekit_minix_rcv (
141*433d6423SLionel Sambuc 	struct ddekit_minix_msg_q *mq,
142*433d6423SLionel Sambuc 	message *m,
143*433d6423SLionel Sambuc 	int *ipc_status
144*433d6423SLionel Sambuc )
145*433d6423SLionel Sambuc {
146*433d6423SLionel Sambuc 	DDEBUG_MSG_VERBOSE("waiting for message");
147*433d6423SLionel Sambuc 
148*433d6423SLionel Sambuc 	ddekit_sem_down(mq->msg_r_sem);
149*433d6423SLionel Sambuc 
150*433d6423SLionel Sambuc 	memcpy(m, &mq->messages[mq->msg_r_pos], sizeof(message));
151*433d6423SLionel Sambuc 	*ipc_status = mq->ipc_status[mq->msg_r_pos];
152*433d6423SLionel Sambuc 	if (++mq->msg_r_pos == MESSAGE_QUEUE_SIZE) {
153*433d6423SLionel Sambuc 		mq->msg_r_pos = 0;
154*433d6423SLionel Sambuc 	}
155*433d6423SLionel Sambuc 
156*433d6423SLionel Sambuc 	DDEBUG_MSG_VERBOSE("unqueing message");
157*433d6423SLionel Sambuc 
158*433d6423SLionel Sambuc 	ddekit_sem_up(mq->msg_w_sem);
159*433d6423SLionel Sambuc }
160