1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - OS
3 File: os_message.c
4
5 Copyright 2003-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16
17 *---------------------------------------------------------------------------*/
18
19 #include <nitro/os.h>
20 #include <nitro/os/common/message.h>
21
22 /*---------------------------------------------------------------------------*
23 Name: OS_InitMessageQueue
24
25 Description: initialize message queue
26
27 Arguments: mq message queue
28 msgArray buffer for message queue
29 msgCount max massage size for buffer
30
31 Returns: None
32 *---------------------------------------------------------------------------*/
OS_InitMessageQueue(OSMessageQueue * mq,OSMessage * msgArray,s32 msgCount)33 void OS_InitMessageQueue(OSMessageQueue *mq, OSMessage *msgArray, s32 msgCount)
34 {
35 OS_InitThreadQueue(&mq->queueSend);
36 OS_InitThreadQueue(&mq->queueReceive);
37 mq->msgArray = msgArray;
38 mq->msgCount = msgCount;
39 mq->firstIndex = 0;
40 mq->usedCount = 0;
41 }
42
43 /*---------------------------------------------------------------------------*
44 Name: OS_SendMessage
45
46 Description: send message to message queue
47
48 Arguments: mq message queue
49 msg massage which is sent
50 flags whether wait or not when queue is full
51
52 Returns: TRUE if send
53
54 *---------------------------------------------------------------------------*/
OS_SendMessage(OSMessageQueue * mq,OSMessage msg,s32 flags)55 BOOL OS_SendMessage(OSMessageQueue *mq, OSMessage msg, s32 flags)
56 {
57 OSIntrMode enabled;
58 s32 lastIndex;
59
60 enabled = OS_DisableInterrupts();
61
62 while (mq->msgCount <= mq->usedCount) // check for full queue
63 {
64 if (!(flags & OS_MESSAGE_BLOCK))
65 {
66 (void)OS_RestoreInterrupts(enabled);
67 return FALSE;
68 }
69 else
70 {
71 // Yield
72 OS_SleepThread(&mq->queueSend);
73 }
74 }
75
76 // Store message
77 lastIndex = (mq->firstIndex + mq->usedCount) % mq->msgCount;
78 mq->msgArray[lastIndex] = msg;
79 mq->usedCount++;
80
81 // Wakeup receiving threads if any
82 OS_WakeupThread(&mq->queueReceive);
83
84 (void)OS_RestoreInterrupts(enabled);
85 return TRUE;
86 }
87
88 /*---------------------------------------------------------------------------*
89 Name: OS_ReceiveMessage
90
91 Description: receive message from message queue
92
93 Arguments: mq message queue
94 msg massage which is received
95 flags whether wait or not when queue is empty
96
97 Returns: TRUE if reveice
98
99 *---------------------------------------------------------------------------*/
OS_ReceiveMessage(OSMessageQueue * mq,OSMessage * msg,s32 flags)100 BOOL OS_ReceiveMessage(OSMessageQueue *mq, OSMessage *msg, s32 flags)
101 {
102 OSIntrMode enabled;
103
104 enabled = OS_DisableInterrupts();
105
106 while (mq->usedCount == 0) // check for empty queue
107 {
108 if (!(flags & OS_MESSAGE_BLOCK))
109 {
110 (void)OS_RestoreInterrupts(enabled);
111 return FALSE;
112 }
113 else
114 {
115 // Yield
116 OS_SleepThread(&mq->queueReceive);
117 }
118 }
119
120 // Copy-out message
121 if (msg != NULL)
122 {
123 *msg = mq->msgArray[mq->firstIndex];
124 }
125 mq->firstIndex = (mq->firstIndex + 1) % mq->msgCount;
126 mq->usedCount--;
127
128 // Wakeup sending threads if any
129 OS_WakeupThread(&mq->queueSend);
130
131 (void)OS_RestoreInterrupts(enabled);
132 return TRUE;
133 }
134
135
136 /*---------------------------------------------------------------------------*
137 Name: OS_JamMessage
138
139 Description: send message to message queue, cutting in the top of the queue
140
141 Arguments: mq message queue
142 msg massage which is sent
143 flags whether wait or not when queue is full
144
145 Returns: TRUE if send
146
147 *---------------------------------------------------------------------------*/
OS_JamMessage(OSMessageQueue * mq,OSMessage msg,s32 flags)148 BOOL OS_JamMessage(OSMessageQueue *mq, OSMessage msg, s32 flags)
149 {
150 OSIntrMode enabled;
151
152 enabled = OS_DisableInterrupts();
153
154 while (mq->msgCount <= mq->usedCount) // check for full queue
155 {
156 if (!(flags & OS_MESSAGE_BLOCK))
157 {
158 (void)OS_RestoreInterrupts(enabled);
159 return FALSE;
160 }
161 else
162 {
163 // Yield
164 OS_SleepThread(&mq->queueSend);
165 }
166 }
167
168 // Store message at the front
169 mq->firstIndex = (mq->firstIndex + mq->msgCount - 1) % mq->msgCount;
170 mq->msgArray[mq->firstIndex] = msg;
171 mq->usedCount++;
172
173 // Wakeup receiving threads if any
174 OS_WakeupThread(&mq->queueReceive);
175
176 (void)OS_RestoreInterrupts(enabled);
177 return TRUE;
178 }
179
180
181 /*---------------------------------------------------------------------------*
182 Name: OS_ReadMessage
183
184 Description: read message at message queue. no change in queue
185 not occur to switch threads.
186
187 Arguments: mq message queue
188 msg massage which is received
189 flags whether wait or not when queue is empty
190
191 Returns: TRUE if read
192
193 *---------------------------------------------------------------------------*/
OS_ReadMessage(OSMessageQueue * mq,OSMessage * msg,s32 flags)194 BOOL OS_ReadMessage(OSMessageQueue *mq, OSMessage *msg, s32 flags)
195 {
196 OSIntrMode enabled;
197
198 enabled = OS_DisableInterrupts();
199
200 while (mq->usedCount == 0) // check for empty queue
201 {
202 if (!(flags & OS_MESSAGE_BLOCK))
203 {
204 (void)OS_RestoreInterrupts(enabled);
205 return FALSE;
206 }
207 else
208 {
209 // Yield
210 OS_SleepThread(&mq->queueReceive);
211 }
212 }
213
214 // Copy-out message
215 if (msg != NULL)
216 {
217 *msg = mq->msgArray[mq->firstIndex];
218 }
219
220 (void)OS_RestoreInterrupts(enabled);
221 return TRUE;
222 }
223