comparison src/nucleus/mbs.c @ 0:92470e5d0b9e

src: partial import from FC Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 15 May 2020 01:28:16 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:92470e5d0b9e
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