FreeCalypso > hg > freecalypso-sw
comparison nuc-fw/nucleus/mbs.c @ 79:947b1f473960
beginning of nuc-fw
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 11 Aug 2013 07:17:25 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
78:2c266d4339ff | 79:947b1f473960 |
---|---|
1 /*************************************************************************/ | |
2 /* */ | |
3 /* Copyright Mentor Graphics Corporation 2002 */ | |
4 /* All Rights Reserved. */ | |
5 /* */ | |
6 /* THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS */ | |
7 /* THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS */ | |
8 /* SUBJECT TO LICENSE TERMS. */ | |
9 /* */ | |
10 /*************************************************************************/ | |
11 | |
12 /*************************************************************************/ | |
13 /* */ | |
14 /* FILE NAME VERSION */ | |
15 /* */ | |
16 /* mbs.c Nucleus PLUS 1.14 */ | |
17 /* */ | |
18 /* COMPONENT */ | |
19 /* */ | |
20 /* MB - Mailbox Management */ | |
21 /* */ | |
22 /* DESCRIPTION */ | |
23 /* */ | |
24 /* This file contains the core routines for the Mailbox management */ | |
25 /* component. */ | |
26 /* */ | |
27 /* DATA STRUCTURES */ | |
28 /* */ | |
29 /* None */ | |
30 /* */ | |
31 /* FUNCTIONS */ | |
32 /* */ | |
33 /* MBS_Reset_Mailbox Reset a mailbox */ | |
34 /* MBS_Broadcast_To_Mailbox Broadcast a mailbox message */ | |
35 /* */ | |
36 /* DEPENDENCIES */ | |
37 /* */ | |
38 /* cs_extr.h Common Service functions */ | |
39 /* tc_extr.h Thread Control functions */ | |
40 /* mb_extr.h Mailbox functions */ | |
41 /* hi_extr.h History functions */ | |
42 /* */ | |
43 /* HISTORY */ | |
44 /* */ | |
45 /* DATE REMARKS */ | |
46 /* */ | |
47 /* 03-01-1994 Initial version of supplemental */ | |
48 /* mailbox service file, */ | |
49 /* version 1.1 */ | |
50 /* */ | |
51 /* 03-18-1994 Verified version 1.1 */ | |
52 /* 04-17-1996 updated to version 1.2 */ | |
53 /* 03-24-1998 Released version 1.3 */ | |
54 /* 03-26-1999 Released 1.11m (new release */ | |
55 /* numbering scheme) */ | |
56 /* 04-23-2001 Fixed problem with resuming task in */ | |
57 /* MBS_Broadcast_To_Mailbox */ | |
58 /* 04-17-2002 Released version 1.13m */ | |
59 /* 11-07-2002 Released version 1.14 */ | |
60 /*************************************************************************/ | |
61 #define NU_SOURCE_FILE | |
62 | |
63 | |
64 #include "cs_extr.h" /* Common service functions */ | |
65 #include "tc_extr.h" /* Thread control functions */ | |
66 #include "mb_extr.h" /* Mailbox functions */ | |
67 #include "hi_extr.h" /* History functions */ | |
68 #include "profiler.h" /* ProView interface */ | |
69 | |
70 | |
71 /* Define internal component function prototypes. */ | |
72 | |
73 VOID MBC_Cleanup(VOID *information); | |
74 | |
75 | |
76 /*************************************************************************/ | |
77 /* */ | |
78 /* FUNCTION */ | |
79 /* */ | |
80 /* MBS_Reset_Mailbox */ | |
81 /* */ | |
82 /* DESCRIPTION */ | |
83 /* */ | |
84 /* This function resets a mailbox back to the initial state. Any */ | |
85 /* message in the mailbox is discarded. Also, all tasks suspended */ | |
86 /* on the mailbox are resumed with the reset completion status. */ | |
87 /* */ | |
88 /* CALLED BY */ | |
89 /* */ | |
90 /* Application */ | |
91 /* MBSE_Reset_Mailbox Error checking shell */ | |
92 /* */ | |
93 /* CALLS */ | |
94 /* */ | |
95 /* [HIC_Make_History_Entry] Make entry in history log */ | |
96 /* TCC_Resume_Task Resume a suspended task */ | |
97 /* [TCT_Check_Stack] Stack checking function */ | |
98 /* TCT_Control_To_System Transfer control to system */ | |
99 /* TCT_System_Protect Protect mailbox */ | |
100 /* TCT_Unprotect Release protection */ | |
101 /* */ | |
102 /* INPUTS */ | |
103 /* */ | |
104 /* mailbox_ptr Mailbox control block pointer*/ | |
105 /* */ | |
106 /* OUTPUTS */ | |
107 /* */ | |
108 /* NU_SUCCESS */ | |
109 /* */ | |
110 /* HISTORY */ | |
111 /* */ | |
112 /* NAME DATE REMARKS */ | |
113 /* */ | |
114 /* 03-01-1993 Created initial version 1.0 */ | |
115 /* 04-19-1993 Verified version 1.0 */ | |
116 /* 03-01-1994 Changed function interface to */ | |
117 /* match the prototype, added */ | |
118 /* register variable logic, */ | |
119 /* optimized protection logic, */ | |
120 /* resulting in version 1.1 */ | |
121 /* */ | |
122 /* 03-18-1994 Verified version 1.1 */ | |
123 /* */ | |
124 /*************************************************************************/ | |
125 STATUS MBS_Reset_Mailbox(NU_MAILBOX *mailbox_ptr) | |
126 { | |
127 | |
128 R1 MB_MCB *mailbox; /* Mailbox control block ptr */ | |
129 R2 MB_SUSPEND *suspend_ptr; /* Suspend block pointer */ | |
130 MB_SUSPEND *next_ptr; /* Next suspend block pointer*/ | |
131 STATUS preempt; /* Status for resume call */ | |
132 NU_SUPERV_USER_VARIABLES | |
133 | |
134 /* Switch to supervisor mode */ | |
135 NU_SUPERVISOR_MODE(); | |
136 | |
137 /* Move input mailbox pointer into internal pointer. */ | |
138 mailbox = (MB_MCB *) mailbox_ptr; | |
139 | |
140 | |
141 #ifdef NU_ENABLE_STACK_CHECK | |
142 | |
143 /* Call stack checking function to check for an overflow condition. */ | |
144 TCT_Check_Stack(); | |
145 | |
146 #endif | |
147 | |
148 #ifdef NU_ENABLE_HISTORY | |
149 | |
150 /* Make an entry that corresponds to this function in the system history | |
151 log. */ | |
152 HIC_Make_History_Entry(NU_RESET_MAILBOX_ID, (UNSIGNED) mailbox, | |
153 (UNSIGNED) 0, (UNSIGNED) 0); | |
154 | |
155 #endif | |
156 | |
157 /* Protect against access to the mailbox. */ | |
158 TCT_System_Protect(); | |
159 | |
160 /* Pickup the suspended task pointer list. */ | |
161 suspend_ptr = mailbox -> mb_suspension_list; | |
162 | |
163 /* Walk the chain task(s) currently suspended on the mailbox. */ | |
164 preempt = 0; | |
165 while (suspend_ptr) | |
166 { | |
167 | |
168 /* Resume the suspended task. Insure that the status returned is | |
169 NU_MAILBOX_RESET. */ | |
170 suspend_ptr -> mb_return_status = NU_MAILBOX_RESET; | |
171 | |
172 /* Point to the next suspend structure in the link. */ | |
173 next_ptr = (MB_SUSPEND *) (suspend_ptr -> mb_suspend_link.cs_next); | |
174 | |
175 /* Resume the specified task. */ | |
176 preempt = preempt | | |
177 TCC_Resume_Task((NU_TASK *) suspend_ptr -> mb_suspended_task, | |
178 NU_MAILBOX_SUSPEND); | |
179 | |
180 /* Determine if the next is the same as the head pointer. */ | |
181 if (next_ptr == mailbox -> mb_suspension_list) | |
182 | |
183 /* Clear the suspension pointer to signal the end of the list | |
184 traversal. */ | |
185 suspend_ptr = NU_NULL; | |
186 else | |
187 | |
188 /* Position the suspend pointer to the next suspend block. */ | |
189 suspend_ptr = next_ptr; | |
190 } | |
191 | |
192 /* Initialize the mailbox. */ | |
193 mailbox -> mb_message_present = NU_FALSE; | |
194 mailbox -> mb_tasks_waiting = 0; | |
195 mailbox -> mb_suspension_list = NU_NULL; | |
196 | |
197 #ifdef INCLUDE_PROVIEW | |
198 _RTProf_DumpMailBox(RT_PROF_RESET_MAILBOX,mailbox,RT_PROF_OK); | |
199 #endif /* INCLUDE_PROVIEW */ | |
200 | |
201 /* Determine if preemption needs to occur. */ | |
202 if (preempt) | |
203 | |
204 /* Transfer control to system to facilitate preemption. */ | |
205 TCT_Control_To_System(); | |
206 | |
207 /* Release protection. */ | |
208 TCT_Unprotect(); | |
209 | |
210 /* Return to user mode */ | |
211 NU_USER_MODE(); | |
212 | |
213 /* Return a successful completion. */ | |
214 return(NU_SUCCESS); | |
215 } | |
216 | |
217 | |
218 /*************************************************************************/ | |
219 /* */ | |
220 /* FUNCTION */ | |
221 /* */ | |
222 /* MBS_Broadcast_To_Mailbox */ | |
223 /* */ | |
224 /* DESCRIPTION */ | |
225 /* */ | |
226 /* This function sends a message to all tasks currently waiting for */ | |
227 /* a message from the mailbox. If no tasks are waiting, this */ | |
228 /* service behaves like a normal send message. */ | |
229 /* */ | |
230 /* CALLED BY */ | |
231 /* */ | |
232 /* Application */ | |
233 /* MBSE_Broadcast_To_Mailbox Broadcast to a mailbox */ | |
234 /* */ | |
235 /* CALLS */ | |
236 /* */ | |
237 /* CSC_Place_On_List Place on suspend list */ | |
238 /* CSC_Priority_Place_On_List Place on priority list */ | |
239 /* CSC_Remove_From_List Remove from suspend list */ | |
240 /* [HIC_Make_History_Entry] Make entry in history log */ | |
241 /* TCC_Resume_Task Resume a suspended task */ | |
242 /* TCC_Suspend_Task Suspend calling task */ | |
243 /* TCC_Task_Priority Priority of specified task */ | |
244 /* [TCT_Check_Stack] Stack checking function */ | |
245 /* TCT_Control_To_System Transfer control to system */ | |
246 /* TCT_Current_Thread Pickup current thread pointer*/ | |
247 /* TCT_System_Protect Protect mailbox */ | |
248 /* TCT_Unprotect Release protection */ | |
249 /* */ | |
250 /* INPUTS */ | |
251 /* */ | |
252 /* mailbox_ptr Mailbox control block pointer*/ | |
253 /* message Pointer to message to send */ | |
254 /* suspend Suspension option if full */ | |
255 /* */ | |
256 /* OUTPUTS */ | |
257 /* */ | |
258 /* NU_SUCCESS If service is successful */ | |
259 /* NU_MAILBOX_FULL If mailbox is currently full */ | |
260 /* NU_TIMEOUT If timeout on service expires*/ | |
261 /* NU_MAILBOX_DELETED If mailbox is deleted during */ | |
262 /* suspension */ | |
263 /* NU_MAILBOX_RESET If mailbox is deleted during */ | |
264 /* suspension */ | |
265 /* */ | |
266 /* HISTORY */ | |
267 /* */ | |
268 /* DATE REMARKS */ | |
269 /* */ | |
270 /* 03-01-1993 Created initial version 1.0 */ | |
271 /* 04-19-1993 Verified version 1.0 */ | |
272 /* 03-01-1994 Changed function interface to */ | |
273 /* match the prototype, added */ | |
274 /* register variable logic, */ | |
275 /* optimized protection logic, */ | |
276 /* resulting in version 1.1 */ | |
277 /* */ | |
278 /* 03-18-1994 Verified version 1.1 */ | |
279 /* */ | |
280 /*************************************************************************/ | |
281 STATUS MBS_Broadcast_To_Mailbox(NU_MAILBOX *mailbox_ptr, VOID *message, | |
282 UNSIGNED suspend) | |
283 { | |
284 | |
285 R1 MB_MCB *mailbox; /* Mailbox control block ptr */ | |
286 MB_SUSPEND suspend_block; /* Allocate suspension block */ | |
287 R2 MB_SUSPEND *suspend_ptr; /* Pointer to suspend block */ | |
288 MB_SUSPEND *suspend_head; /* Pointer to suspend head */ | |
289 MB_SUSPEND *next_suspend_ptr; /* Get before restarting task*/ | |
290 STATUS preempt; /* Preemption flag */ | |
291 R3 UNSIGNED *source_ptr; /* Pointer to source */ | |
292 R4 UNSIGNED *destination_ptr; /* Pointer to destination */ | |
293 TC_TCB *task; /* Task pointer */ | |
294 STATUS status; /* Completion status */ | |
295 NU_SUPERV_USER_VARIABLES | |
296 | |
297 /* Switch to supervisor mode */ | |
298 NU_SUPERVISOR_MODE(); | |
299 | |
300 /* Move input mailbox pointer into internal pointer. */ | |
301 mailbox = (MB_MCB *) mailbox_ptr; | |
302 | |
303 | |
304 #ifdef NU_ENABLE_STACK_CHECK | |
305 | |
306 /* Call stack checking function to check for an overflow condition. */ | |
307 TCT_Check_Stack(); | |
308 | |
309 #endif | |
310 | |
311 #ifdef NU_ENABLE_HISTORY | |
312 | |
313 /* Make an entry that corresponds to this function in the system history | |
314 log. */ | |
315 HIC_Make_History_Entry(NU_BROADCAST_TO_MAILBOX_ID, (UNSIGNED) mailbox, | |
316 (UNSIGNED) message, (UNSIGNED) suspend); | |
317 | |
318 #endif | |
319 | |
320 /* Initialize the status as successful. */ | |
321 status = NU_SUCCESS; | |
322 | |
323 /* Protect against simultaneous access to the mailbox. */ | |
324 TCT_System_Protect(); | |
325 | |
326 /* Determine if the mailbox is empty or full. */ | |
327 if (mailbox -> mb_message_present) | |
328 { | |
329 | |
330 /* Mailbox already has a message. Determine if suspension is | |
331 required. */ | |
332 if (suspend) | |
333 { | |
334 | |
335 /* Suspension is requested. */ | |
336 | |
337 /* Increment the number of tasks suspended on the mailbox. */ | |
338 mailbox -> mb_tasks_waiting++; | |
339 | |
340 #ifdef INCLUDE_PROVIEW | |
341 _RTProf_DumpMailBox(RT_PROF_BROADCAST_TO_MAILBOX,mailbox,RT_PROF_WAIT); | |
342 #endif /* INCLUDE_PROVIEW */ | |
343 | |
344 /* Setup the suspend block and suspend the calling task. */ | |
345 suspend_ptr = &suspend_block; | |
346 suspend_ptr -> mb_mailbox = mailbox; | |
347 suspend_ptr -> mb_suspend_link.cs_next = NU_NULL; | |
348 suspend_ptr -> mb_suspend_link.cs_previous = NU_NULL; | |
349 suspend_ptr -> mb_message_area = (UNSIGNED *) message; | |
350 task = (TC_TCB *) TCT_Current_Thread(); | |
351 suspend_ptr -> mb_suspended_task = task; | |
352 | |
353 /* Determine if priority or FIFO suspension is associated with the | |
354 mailbox. */ | |
355 if (mailbox -> mb_fifo_suspend) | |
356 { | |
357 | |
358 /* FIFO suspension is required. Link the suspend block into | |
359 the list of suspended tasks on this mailbox. */ | |
360 CSC_Place_On_List((CS_NODE **) &(mailbox ->mb_suspension_list), | |
361 &(suspend_ptr -> mb_suspend_link)); | |
362 } | |
363 else | |
364 { | |
365 | |
366 /* Get the priority of the current thread so the suspend block | |
367 can be placed in the appropriate place. */ | |
368 suspend_ptr -> mb_suspend_link.cs_priority = | |
369 TCC_Task_Priority(task); | |
370 | |
371 CSC_Priority_Place_On_List((CS_NODE **) | |
372 &(mailbox -> mb_suspension_list), | |
373 &(suspend_ptr -> mb_suspend_link)); | |
374 } | |
375 | |
376 /* Finally, suspend the calling task. Note that the suspension call | |
377 automatically clears the protection on the mailbox. */ | |
378 TCC_Suspend_Task((NU_TASK *) task, NU_MAILBOX_SUSPEND, | |
379 MBC_Cleanup, suspend_ptr, suspend); | |
380 | |
381 /* Pickup the return status. */ | |
382 status = suspend_ptr -> mb_return_status; | |
383 } | |
384 else | |
385 { | |
386 | |
387 /* Return a status of NU_MAILBOX_FULL because there is no | |
388 room in the mailbox for the message. */ | |
389 status = NU_MAILBOX_FULL; | |
390 | |
391 #ifdef INCLUDE_PROVIEW | |
392 _RTProf_DumpMailBox(RT_PROF_BROADCAST_TO_MAILBOX,mailbox,RT_PROF_FAIL); | |
393 #endif /* INCLUDE_PROVIEW */ | |
394 | |
395 } | |
396 } | |
397 else | |
398 { | |
399 | |
400 /* Determine if a task is waiting on the mailbox. */ | |
401 if (mailbox -> mb_suspension_list) | |
402 { | |
403 | |
404 #ifdef INCLUDE_PROVIEW | |
405 _RTProf_DumpMailBox(RT_PROF_BROADCAST_TO_MAILBOX,mailbox,RT_PROF_OK); | |
406 #endif /* INCLUDE_PROVIEW */ | |
407 | |
408 /* At least one task is waiting on mailbox for a message. */ | |
409 | |
410 /* Save off the suspension list and and then clear out the | |
411 mailbox suspension. */ | |
412 suspend_head = mailbox -> mb_suspension_list; | |
413 mailbox -> mb_suspension_list = NU_NULL; | |
414 | |
415 /* Loop to wakeup all of the tasks waiting on the mailbox for | |
416 a message. */ | |
417 suspend_ptr = suspend_head; | |
418 preempt = 0; | |
419 do | |
420 { | |
421 | |
422 /* Setup the source and destination pointers. */ | |
423 source_ptr = (UNSIGNED *) message; | |
424 destination_ptr = suspend_ptr -> mb_message_area; | |
425 | |
426 /* Copy the message directly into the waiting task's | |
427 destination. */ | |
428 *destination_ptr = *source_ptr; | |
429 *(destination_ptr + 1) = *(source_ptr + 1); | |
430 *(destination_ptr + 2) = *(source_ptr + 2); | |
431 *(destination_ptr + 3) = *(source_ptr + 3); | |
432 | |
433 /* Setup the appropriate return value. */ | |
434 suspend_ptr -> mb_return_status = NU_SUCCESS; | |
435 | |
436 /* Move the suspend pointer along to the next block. */ | |
437 next_suspend_ptr = (MB_SUSPEND *) | |
438 suspend_ptr -> mb_suspend_link.cs_next; | |
439 | |
440 /* Wakeup each task waiting. */ | |
441 preempt = preempt | | |
442 TCC_Resume_Task((NU_TASK *) suspend_ptr -> mb_suspended_task, | |
443 NU_MAILBOX_SUSPEND); | |
444 suspend_ptr = next_suspend_ptr; | |
445 | |
446 } while (suspend_ptr != suspend_head); | |
447 | |
448 /* Clear the number of tasks waiting counter of the mailbox. */ | |
449 mailbox -> mb_tasks_waiting = 0; | |
450 | |
451 /* Determine if a preempt condition is present. */ | |
452 if (preempt) | |
453 | |
454 /* Transfer control to the system if the resumed task function | |
455 detects a preemption condition. */ | |
456 TCT_Control_To_System(); | |
457 } | |
458 else | |
459 { | |
460 | |
461 /* Mailbox is empty and no task is waiting. */ | |
462 | |
463 /* Setup the source and destination pointers. */ | |
464 source_ptr = (UNSIGNED *) message; | |
465 destination_ptr = &(mailbox -> mb_message_area[0]); | |
466 | |
467 /* Place the message in the mailbox. */ | |
468 *destination_ptr = *source_ptr; | |
469 *(destination_ptr + 1) = *(source_ptr + 1); | |
470 *(destination_ptr + 2) = *(source_ptr + 2); | |
471 *(destination_ptr + 3) = *(source_ptr + 3); | |
472 | |
473 /* Indicate that the mailbox has a message. */ | |
474 mailbox -> mb_message_present = NU_TRUE; | |
475 | |
476 #ifdef INCLUDE_PROVIEW | |
477 _RTProf_DumpMailBox(RT_PROF_BROADCAST_TO_MAILBOX,mailbox,RT_PROF_OK); | |
478 #endif /* INCLUDE_PROVIEW */ | |
479 } | |
480 } | |
481 | |
482 /* Release protection. */ | |
483 TCT_Unprotect(); | |
484 | |
485 /* Return to user mode */ | |
486 NU_USER_MODE(); | |
487 | |
488 /* Return the completion status. */ | |
489 return(status); | |
490 } | |
491 | |
492 | |
493 | |
494 | |
495 | |
496 |