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