comparison src/nucleus/tcs.c @ 0:4e78acac3d88

src/{condat,cs,gpf,nucleus}: import from Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:23:26 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4e78acac3d88
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 /* tcs.c Nucleus PLUS 1.14 */
17 /* */
18 /* COMPONENT */
19 /* */
20 /* TC - Thread Control */
21 /* */
22 /* DESCRIPTION */
23 /* */
24 /* This file contains supplemental routines for the Thread Control */
25 /* component. */
26 /* */
27 /* DATA STRUCTURES */
28 /* */
29 /* None */
30 /* */
31 /* FUNCTIONS */
32 /* */
33 /* TCS_Change_Priority Change task's priority */
34 /* TCS_Change_Preemption Change task's preemption */
35 /* TCS_Change_Time_Slice Change task's time-slice */
36 /* TCS_Control_Signals Control signals */
37 /* TCS_Receive_Signals Receive signals */
38 /* TCS_Register_Signal_Handler Register signal handler */
39 /* TCS_Send_Signals Send signals to a task */
40 /* */
41 /* */
42 /* DEPENDENCIES */
43 /* */
44 /* cs_extr.h Common Service functions */
45 /* tc_extr.h Thread Control functions */
46 /* in_extr.h Initialization/Interrupt */
47 /* functions */
48 /* tm_extr.h Timer Control function */
49 /* er_extr.h Error handling function */
50 /* hi_extr.h History functions */
51 /* */
52 /* HISTORY */
53 /* */
54 /* DATE REMARKS */
55 /* */
56 /* 03-01-1994 Created initial version 1.1 from */
57 /* previous version of TCC.C */
58 /* */
59 /* 03-18-1994 Verified version 1.1 */
60 /* 04-04-1996 Modified TCS_Send_Signals, */
61 /* resulting in version 1.1+ */
62 /* (spr 107) */
63 /* 04-17-1996 updated to version 1.2 */
64 /* 03-24-1998 Released version 1.3. */
65 /* 03-26-1999 Released 1.11m (new release */
66 /* numbering scheme) */
67 /* 04-17-2002 Released version 1.13m */
68 /* 11-07-2002 Released version 1.14 */
69 /*************************************************************************/
70 #define NU_SOURCE_FILE
71
72
73 #include "cs_extr.h" /* Common service functions */
74 #include "tc_extr.h" /* Thread control functions */
75 #include "in_extr.h" /* Initialization/Interrupt */
76 /* functions */
77 #include "tm_extr.h" /* Timer control functions */
78 #include "er_extr.h" /* Error handling function */
79 #include "hi_extr.h" /* History functions */
80 #include "profiler.h" /* ProView interface */
81
82
83 /* Define external inner-component global data references. */
84
85 extern CS_NODE *TCD_Created_Tasks_List;
86 extern TC_TCB *TCD_Priority_List[TC_PRIORITIES];
87 extern UNSIGNED TCD_Priority_Groups;
88 extern DATA_ELEMENT TCD_Sub_Priority_Groups[TC_MAX_GROUPS];
89 extern UNSIGNED_CHAR TCD_Lowest_Set_Bit[];
90 extern INT TCD_Highest_Priority;
91 extern TC_TCB *TCD_Execute_Task;
92 extern VOID *TCD_Current_Thread;
93 extern TC_PROTECT TCD_System_Protect;
94 extern INT TMD_Time_Slice_State;
95
96
97
98 /* Define external inner-component function calls that are not available to
99 other components. */
100
101 VOID TCT_Build_Signal_Frame(TC_TCB *task_ptr);
102 VOID TCT_Protect_Switch(TC_TCB *task);
103 VOID TCT_Signal_Exit(VOID);
104
105
106 /* Define internal function calls. */
107
108 VOID TCC_Signal_Shell(VOID);
109
110
111 /*************************************************************************/
112 /* */
113 /* FUNCTION */
114 /* */
115 /* TCS_Change_Priority */
116 /* */
117 /* DESCRIPTION */
118 /* */
119 /* This function changes the priority of the specified task. The */
120 /* priority of a suspended or a ready task can be changed. If the */
121 /* new priority necessitates a context switch, control is */
122 /* transferred back to the system. */
123 /* */
124 /* CALLED BY */
125 /* */
126 /* Application */
127 /* TCSE_Change_Priority Error checking shell */
128 /* */
129 /* CALLS */
130 /* */
131 /* [HIC_Make_History_Entry] Make entry in history log */
132 /* [TCT_Check_Stack] Stack checking function */
133 /* TCT_Control_To_System Transfer control to system */
134 /* TCT_Protect Protect scheduling data */
135 /* TCT_Set_Execute_Task Set TCD_Execute_Task pointer */
136 /* TCT_Unprotect Release protection of data */
137 /* */
138 /* INPUTS */
139 /* */
140 /* task_ptr Task control block pointer */
141 /* new_priority New priority for task */
142 /* */
143 /* OUTPUTS */
144 /* */
145 /* old_priority Original task priority */
146 /* */
147 /* HISTORY */
148 /* */
149 /* DATE REMARKS */
150 /* */
151 /* 03-01-1993 Created initial version 1.0 */
152 /* 04-19-1993 Verified version 1.0 */
153 /* 03-01-1994 Modified function interface, */
154 /* added register optimizations, */
155 /* modified protection logic, */
156 /* resulting in version 1.1 */
157 /* */
158 /* 03-18-1994 Verified version 1.1 */
159 /* */
160 /* 10-4-1999 Bug fixes - return if new */
161 /* priority equals old priority */
162 /* and don't move the head pointer */
163 /* unless the head node is changing */
164 /*************************************************************************/
165 OPTION TCS_Change_Priority(NU_TASK *task_ptr, OPTION new_priority)
166 {
167
168 R1 TC_TCB *task; /* Task control block ptr */
169 R2 TC_TCB *head; /* Head list pointer */
170 R3 INT index; /* Working index variable */
171 OPTION old_priority; /* Previous priority of task */
172 DATA_ELEMENT temp; /* Temporary variable */
173 NU_SUPERV_USER_VARIABLES
174
175 /* Switch to supervisor mode */
176 NU_SUPERVISOR_MODE();
177
178 /* Move task control block pointer into internal pointer. */
179 task = (TC_TCB *) task_ptr;
180
181
182 #ifdef NU_ENABLE_STACK_CHECK
183
184 /* Call stack checking function to check for an overflow condition. */
185 TCT_Check_Stack();
186
187 #endif
188
189 #ifdef NU_ENABLE_HISTORY
190
191 /* Make an entry that corresponds to this function in the system history
192 log. */
193 HIC_Make_History_Entry(NU_CHANGE_PRIORITY_ID, (UNSIGNED) task,
194 (UNSIGNED) new_priority, (UNSIGNED) 0);
195
196 #endif
197
198 /* Protect against multiple access to the scheduling list. */
199 TCT_Protect(&TCD_System_Protect);
200
201 /* Save the old priority of the task. */
202 old_priority = task -> tc_priority;
203
204
205 /* BUG FIX this should probably go into an error checking routine instead of here */
206 if (!(task -> tc_priority == new_priority))
207 {
208
209
210 /* Check to see if the task is currently ready. */
211 if (task -> tc_status == NU_READY)
212 {
213
214 /* Remove the task from the ready list. */
215
216 /* Determine if the task is the only one on the list. */
217 if (task -> tc_ready_next == task)
218 {
219
220 /* Only task on the list. Clear the task's pointers and
221 clear the entry in the priority table. */
222 task -> tc_ready_next = NU_NULL;
223 task -> tc_ready_previous = NU_NULL;
224 *(task -> tc_priority_head) = NU_NULL;
225
226 /* Clear the sub-priority group. */
227 *(task -> tc_sub_priority_ptr) =
228 *(task -> tc_sub_priority_ptr) & ~(task -> tc_sub_priority);
229
230 /* Determine if the main priority group needs to be cleared.
231 This is only true if there are no other bits set in this
232 sub-priority. */
233 if (*(task -> tc_sub_priority_ptr) == 0)
234
235 /* Clear the main priority group bit. */
236 TCD_Priority_Groups =
237 TCD_Priority_Groups & ~(task -> tc_priority_group);
238 }
239 else
240 {
241
242 /* Not the only task ready at the same priority level. */
243
244 /* Remove from the linked-list. */
245 (task -> tc_ready_previous) -> tc_ready_next =
246 task -> tc_ready_next;
247 (task -> tc_ready_next) -> tc_ready_previous =
248 task -> tc_ready_previous;
249
250
251
252 /* Update the head pointer. */
253 /* BUG FIX - update head if head is changing priority - leave
254 it alone otherwise! */
255 if(*(task -> tc_priority_head) == task )
256 *(task -> tc_priority_head) = task -> tc_ready_next;
257
258 /* Clear the next and previous pointers. */
259 task -> tc_ready_next = NU_NULL;
260 task -> tc_ready_previous = NU_NULL;
261 }
262
263 /* Now add in the task at the new priority. */
264 task -> tc_priority = new_priority;
265
266 /* Build the other priority information. */
267 task -> tc_priority = new_priority;
268 task -> tc_priority_head = &(TCD_Priority_List[new_priority]);
269 task -> tc_sub_priority = (DATA_ELEMENT) (1 << (new_priority & 7));
270 task -> tc_priority_group = ((UNSIGNED) 1) << (new_priority >> 3);
271 task -> tc_sub_priority_ptr =
272 &(TCD_Sub_Priority_Groups[(new_priority >> 3)]);
273
274 #ifdef INCLUDE_PROVIEW
275 _RTProf_DumpTask(task,RT_PROF_CHANGE_PRIORITY);
276 #endif
277 /* Link the task into the new priority list. */
278 head = *(task -> tc_priority_head);
279
280 /* Determine if the list is non-empty. */
281 if (head)
282 {
283
284 /* Add the TCB to the end of the ready list. */
285 task -> tc_ready_previous = head -> tc_ready_previous;
286 (task -> tc_ready_previous) -> tc_ready_next = task;
287 task -> tc_ready_next = head;
288 (task -> tc_ready_next) -> tc_ready_previous = task;
289
290 /* Note that the priority bit map does not need to be
291 modified since there are other active tasks at the
292 same priority. */
293 }
294 else
295 {
296
297 /* Add the TCB to an empty list. */
298 task -> tc_ready_previous = task;
299 task -> tc_ready_next = task;
300 *(task -> tc_priority_head)= task;
301
302 /* Update the priority group bit map to indicate that this
303 priority now has a task ready. */
304 TCD_Priority_Groups =
305 TCD_Priority_Groups | (task -> tc_priority_group);
306
307 /* Update the sub-priority bit map to show that this priority
308 is ready. */
309 *(task -> tc_sub_priority_ptr) =
310 (*(task -> tc_sub_priority_ptr)) | task -> tc_sub_priority;
311 }
312
313 /* Determine the highest priority task in the system. */
314 if (TCD_Priority_Groups & TC_HIGHEST_MASK)
315
316 /* Base of sub-group is 0. */
317 index = 0;
318
319 else if (TCD_Priority_Groups & TC_NEXT_HIGHEST_MASK)
320
321 /* Base of sub-group is 8. */
322 index = 8;
323
324 else if (TCD_Priority_Groups & TC_NEXT_LOWEST_MASK)
325
326 /* Base of sub-group is 16. */
327 index = 16;
328 else
329
330 /* Base of sub-group is 24. */
331 index = 24;
332
333 /* Calculate the highest available priority. */
334 index = index + TCD_Lowest_Set_Bit[(INT)
335 ((TCD_Priority_Groups >> index) & TC_HIGHEST_MASK)];
336
337 /* Get the mask of the priority within the group of 8 priorities. */
338 temp = TCD_Sub_Priority_Groups[index];
339
340 /* Calculate the actual priority. */
341 TCD_Highest_Priority = (index << 3) + TCD_Lowest_Set_Bit[temp];
342
343 /* Check for preemption. */
344 if ((TCD_Highest_Priority <= ((INT) TCD_Execute_Task -> tc_priority))
345 && (TCD_Execute_Task -> tc_preemption))
346 {
347
348 /* Update the current task pointer. */
349 TCT_Set_Execute_Task(TCD_Priority_List[TCD_Highest_Priority]);
350
351 /* Now, check and see if the current thread is a task.
352 If so, return a status that indicates a context
353 switch is needed. */
354 if ((TCD_Current_Thread) &&
355 (((TC_TCB *) TCD_Current_Thread) -> tc_id == TC_TASK_ID))
356
357 /* Transfer control to the system. */
358 TCT_Control_To_System();
359 }
360 }
361 else
362 {
363
364 /* Just modify the priority. */
365 task -> tc_priority = new_priority;
366
367 /* Build the other priority information. */
368 task -> tc_priority = new_priority;
369 task -> tc_priority_head = &(TCD_Priority_List[new_priority]);
370 task -> tc_sub_priority = (DATA_ELEMENT) (1 << (new_priority & 7));
371 task -> tc_priority_group = ((UNSIGNED) 1) << (new_priority >> 3);
372 task -> tc_sub_priority_ptr =
373 &(TCD_Sub_Priority_Groups[(new_priority >> 3)]);
374 }
375 #ifdef INCLUDE_PROVIEW
376 _RTProf_DumpTask(task,RT_PROF_CHANGE_PRIORITY);
377 #endif
378 }
379
380 /* Release the protection of the scheduling list. */
381 TCT_Unprotect();
382
383 /* Return to user mode */
384 NU_USER_MODE();
385
386 /* Return the old priority. */
387 return(old_priority);
388 }
389
390
391 /*************************************************************************/
392 /* */
393 /* FUNCTION */
394 /* */
395 /* TCS_Change_Preemption */
396 /* */
397 /* DESCRIPTION */
398 /* */
399 /* This function changes the preemption posture of the calling */
400 /* task. Preemption for a task may be enabled or disabled. If */
401 /* it is disabled, the task runs until it suspends or relinquishes. */
402 /* If a preemption is pending, a call to this function to enable */
403 /* preemption causes a context switch. */
404 /* */
405 /* CALLED BY */
406 /* */
407 /* Application */
408 /* TCSE_Change_Preemption Error checking function */
409 /* */
410 /* CALLS */
411 /* */
412 /* [HIC_Make_History_Entry] Make entry in history log */
413 /* [TCT_Check_Stack] Stack checking function */
414 /* TCT_Control_To_System Transfer control to system */
415 /* TCT_Protect Protect scheduling info */
416 /* TCT_Set_Execute_Task Set TCD_Execute_Task pointer */
417 /* TCT_Unprotect Release protection of info */
418 /* */
419 /* INPUTS */
420 /* */
421 /* preempt Preempt selection parameter */
422 /* */
423 /* OUTPUTS */
424 /* */
425 /* old_preempt Original preempt value */
426 /* */
427 /* HISTORY */
428 /* */
429 /* DATE REMARKS */
430 /* */
431 /* 03-01-1993 Created initial version 1.0 */
432 /* 04-19-1993 Verified version 1.0 */
433 /* 03-01-1994 Modified protection logic, */
434 /* resulting in version 1.1 */
435 /* */
436 /* 03-18-1994 Verified version 1.1 */
437 /* */
438 /*************************************************************************/
439 OPTION TCS_Change_Preemption(OPTION preempt)
440 {
441
442 TC_TCB *task; /* Pointer to task */
443 OPTION old_preempt;
444 NU_SUPERV_USER_VARIABLES
445
446 /* Switch to supervisor mode */
447 NU_SUPERVISOR_MODE();
448
449 #ifdef NU_ENABLE_STACK_CHECK
450
451 /* Call stack checking function to check for an overflow condition. */
452 TCT_Check_Stack();
453
454 #endif
455
456 #ifdef NU_ENABLE_HISTORY
457
458 /* Make an entry that corresponds to this function in the system history
459 log. */
460 HIC_Make_History_Entry(NU_CHANGE_PREEMPTION_ID, (UNSIGNED) preempt,
461 (UNSIGNED) 0, (UNSIGNED) 0);
462
463 #endif
464
465 /* Protect the scheduling information. */
466 TCT_Protect(&TCD_System_Protect);
467
468 /* Pickup the current thread and place it in the task pointer. */
469 task = (TC_TCB *) TCD_Current_Thread;
470
471 /* Save the old preempt value. */
472 if (task -> tc_preemption)
473
474 /* Previously enabled. */
475 old_preempt = NU_PREEMPT;
476 else
477
478 /* Previously disabled. */
479 old_preempt = NU_NO_PREEMPT;
480
481 /* Process the new value. */
482 if (preempt == NU_NO_PREEMPT)
483
484 /* Disable preemption. */
485 TCD_Execute_Task -> tc_preemption = NU_FALSE;
486 else
487 {
488
489 /* Enable preemption. */
490 task -> tc_preemption = NU_TRUE;
491
492 /* Check for a preemption condition. */
493 if ((task == TCD_Execute_Task) &&
494 (TCD_Highest_Priority < ((INT) TCD_Execute_Task -> tc_priority)))
495 {
496
497 /* Preempt the current task. */
498 TCT_Set_Execute_Task(TCD_Priority_List[TCD_Highest_Priority]);
499
500 /* Transfer control to the system. */
501 TCT_Control_To_System();
502 }
503 }
504
505 #ifdef INCLUDE_PROVIEW
506 _RTProf_DumpTask(task,RT_PROF_CHANGE_PREEMPTION);
507 #endif
508
509 /* Release protection of information. */
510 TCT_Unprotect();
511
512 /* Return to user mode */
513 NU_USER_MODE();
514
515 /* Return the previous preemption posture. */
516 return(old_preempt);
517 }
518
519
520 /*************************************************************************/
521 /* */
522 /* FUNCTION */
523 /* */
524 /* TCS_Change_Time_Slice */
525 /* */
526 /* DESCRIPTION */
527 /* */
528 /* This function changes the time slice of the specified task. A */
529 /* time slice value of 0 disables time slicing. */
530 /* */
531 /* CALLED BY */
532 /* */
533 /* Application */
534 /* TCES_Change_Preemption Error checking function */
535 /* */
536 /* CALLS */
537 /* */
538 /* [HIC_Make_History_Entry] Make entry in history log */
539 /* [TCT_Check_Stack] Stack checking function */
540 /* TCT_Protect Protect scheduling info */
541 /* TCT_Unprotect Release protection of info */
542 /* */
543 /* INPUTS */
544 /* */
545 /* task_ptr Task control block pointer */
546 /* time_slice New time slice value */
547 /* */
548 /* OUTPUTS */
549 /* */
550 /* old_time_slice Original time slice value */
551 /* */
552 /* HISTORY */
553 /* */
554 /* DATE REMARKS */
555 /* */
556 /* 03-01-1993 Created initial version 1.0 */
557 /* 04-19-1993 Verified version 1.0 */
558 /* 03-01-1994 Modified function interface, */
559 /* added register optimizations, */
560 /* modified protection logic, */
561 /* resulting in version 1.1 */
562 /* */
563 /* 03-18-1994 Verified version 1.1 */
564 /* */
565 /*************************************************************************/
566 UNSIGNED TCS_Change_Time_Slice(NU_TASK *task_ptr, UNSIGNED time_slice)
567 {
568
569 TC_TCB *task; /* Task control block ptr */
570 UNSIGNED old_time_slice; /* Old time slice value */
571 NU_SUPERV_USER_VARIABLES
572
573 /* Switch to supervisor mode */
574 NU_SUPERVISOR_MODE();
575
576 /* Move input task control block pointer into internal pointer. */
577 task = (TC_TCB *) task_ptr;
578
579
580 #ifdef NU_ENABLE_STACK_CHECK
581
582 /* Call stack checking function to check for an overflow condition. */
583 TCT_Check_Stack();
584
585 #endif
586
587 #ifdef NU_ENABLE_HISTORY
588
589 /* Make an entry that corresponds to this function in the system history
590 log. */
591 HIC_Make_History_Entry(NU_CHANGE_TIME_SLICE_ID, (UNSIGNED) task,
592 (UNSIGNED) time_slice, (UNSIGNED) 0);
593
594 #endif
595
596 /* Protect the scheduling information. */
597 TCT_Protect(&TCD_System_Protect);
598
599 /* Save the old time slice value. */
600 old_time_slice = task -> tc_time_slice;
601
602 /* Store the new time slice value. */
603 task -> tc_time_slice = time_slice;
604 task -> tc_cur_time_slice = time_slice;
605
606 /* Bug fix. Let the system know we have started a new time slice */
607 TMD_Time_Slice_State = TM_ACTIVE;
608
609 #ifdef INCLUDE_PROVIEW
610 _RTProf_DumpTask(task,RT_PROF_CHANGE_TIME_SLICE);
611 #endif
612 /* Release protection of information. */
613 TCT_Unprotect();
614
615 /* Return to user mode */
616 NU_USER_MODE();
617
618 /* Return the previous time slice value. */
619 return(old_time_slice);
620 }
621
622
623 /*************************************************************************/
624 /* */
625 /* FUNCTION */
626 /* */
627 /* TCS_Control_Signals */
628 /* */
629 /* DESCRIPTION */
630 /* */
631 /* This function enables the specified signals and returns the */
632 /* previous enable signal value back to the caller. If a newly */
633 /* enabled signal is present and a signal handler is registered, */
634 /* signal handling is started. */
635 /* */
636 /* CALLED BY */
637 /* */
638 /* Application */
639 /* TCSE_Control_Signals Error checking shell */
640 /* */
641 /* CALLS */
642 /* */
643 /* [HIC_Make_History_Entry] Make entry in history log */
644 /* TCC_Signal_Shell Task signal execution */
645 /* [TCT_Check_Stack] Stack checking function */
646 /* TCT_Protect Protect against other access */
647 /* TCT_Unprotect Release protection */
648 /* */
649 /* INPUTS */
650 /* */
651 /* enable_signal_mask Enable signal mask */
652 /* */
653 /* OUTPUTS */
654 /* */
655 /* Previous signal enable mask */
656 /* */
657 /* HISTORY */
658 /* */
659 /* DATE REMARKS */
660 /* */
661 /* 03-01-1993 Created initial version 1.0 */
662 /* 04-19-1993 Verified version 1.0 */
663 /* 05-15-1993 Corrected problem with a comment */
664 /* 05-15-1993 Verified comment repair */
665 /* 03-01-1994 Added register optimizations, */
666 /* modified protection logic, */
667 /* resulting in version 1.1 */
668 /* */
669 /* 03-18-1994 Verified version 1.1 */
670 /* */
671 /*************************************************************************/
672 UNSIGNED TCS_Control_Signals(UNSIGNED enable_signal_mask)
673 {
674
675 R1 TC_TCB *task; /* Task pointer */
676 UNSIGNED old_enable_mask; /* Old enable signal mask */
677 NU_SUPERV_USER_VARIABLES
678
679 /* Switch to supervisor mode */
680 NU_SUPERVISOR_MODE();
681
682 #ifdef NU_ENABLE_STACK_CHECK
683
684 /* Call stack checking function to check for an overflow condition. */
685 TCT_Check_Stack();
686
687 #endif
688
689 #ifdef NU_ENABLE_HISTORY
690
691 /* Make an entry that corresponds to this function in the system history
692 log. */
693 HIC_Make_History_Entry(NU_CONTROL_SIGNALS_ID,(UNSIGNED) enable_signal_mask,
694 (UNSIGNED) 0, (UNSIGNED) 0);
695
696 #endif
697
698 /* Pickup the task pointer. */
699 task = (TC_TCB *) TCD_Current_Thread;
700
701 /* Protect against simultaneous access. */
702 TCT_Protect(&TCD_System_Protect);
703
704 /* Pickup the old signal mask. */
705 old_enable_mask = task -> tc_enabled_signals;
706
707 /* Put the new mask in. */
708 task -> tc_enabled_signals = enable_signal_mask;
709
710 /* Now, determine if the signal handler needs to be invoked. */
711 if ((enable_signal_mask & task -> tc_signals) &&
712 (!task -> tc_signal_active) &&
713 (task -> tc_signal_handler))
714 {
715
716 /* Signal processing is required. */
717
718 /* Indicate that signal processing is in progress. */
719 task -> tc_signal_active = NU_TRUE;
720
721 /* Clear the saved stack pointer to indicate that this is an
722 in line signal handler call. */
723 task -> tc_saved_stack_ptr = NU_NULL;
724
725 #ifdef INCLUDE_PROVIEW
726 _RTProf_DumpTask(task,RT_PROF_CONTROL_SIGNALS);
727 #endif
728
729 /* Release protection from multiple access. */
730 TCT_Unprotect();
731
732 /* Call the signal handling shell. */
733 TCC_Signal_Shell();
734 }
735 else
736 {
737
738 #ifdef INCLUDE_PROVIEW
739 _RTProf_DumpTask(task,RT_PROF_CONTROL_SIGNALS);
740 #endif
741
742 /* Release protection. */
743 TCT_Unprotect();
744 }
745
746 /* Return to user mode */
747 NU_USER_MODE();
748
749 /* Return the old enable mask. */
750 return(old_enable_mask);
751 }
752
753
754 /*************************************************************************/
755 /* */
756 /* FUNCTION */
757 /* */
758 /* TCS_Receive_Signals */
759 /* */
760 /* DESCRIPTION */
761 /* */
762 /* This function returns the current signals back to the caller. */
763 /* Note that the signals are cleared automatically. */
764 /* */
765 /* CALLED BY */
766 /* */
767 /* Application */
768 /* TCSE_Receive_Signals Error checking shell */
769 /* */
770 /* CALLS */
771 /* */
772 /* [HIC_Make_History_Entry] Make entry in history log */
773 /* [TCT_Check_Stack] Stack checking function */
774 /* TCT_Protect Protect against other access */
775 /* TCT_Unprotect Release protection */
776 /* */
777 /* INPUTS */
778 /* */
779 /* None */
780 /* */
781 /* OUTPUTS */
782 /* */
783 /* Current signals */
784 /* */
785 /* HISTORY */
786 /* */
787 /* DATE REMARKS */
788 /* */
789 /* 03-01-1993 Created initial version 1.0 */
790 /* 04-19-1993 Verified version 1.0 */
791 /* 03-01-1994 Modified protection logic, */
792 /* resulting in version 1.1 */
793 /* */
794 /* 03-18-1994 Verified version 1.1 */
795 /* */
796 /*************************************************************************/
797 UNSIGNED TCS_Receive_Signals(VOID)
798 {
799
800 TC_TCB *task; /* Task pointer */
801 UNSIGNED signals; /* Current signals */
802 NU_SUPERV_USER_VARIABLES
803
804 /* Switch to supervisor mode */
805 NU_SUPERVISOR_MODE();
806
807 #ifdef NU_ENABLE_STACK_CHECK
808
809 /* Call stack checking function to check for an overflow condition. */
810 TCT_Check_Stack();
811
812 #endif
813
814 #ifdef NU_ENABLE_HISTORY
815
816 /* Make an entry that corresponds to this function in the system history
817 log. */
818 HIC_Make_History_Entry(NU_RECEIVE_SIGNALS_ID, (UNSIGNED) 0,
819 (UNSIGNED) 0, (UNSIGNED) 0);
820
821 #endif
822
823 /* Pickup the task pointer. */
824 task = (TC_TCB *) TCD_Current_Thread;
825
826 /* Protect against simultaneous access. */
827 TCT_Protect(&TCD_System_Protect);
828
829 /* Pickup the current events. */
830 signals = task -> tc_signals;
831
832 /* Clear the current signals. */
833 task -> tc_signals = 0;
834
835 #ifdef INCLUDE_PROVIEW
836 _RTProf_DumpTask(task,RT_PROF_RECEIVE_SIGNALS);
837 #endif
838
839 /* Release protection. */
840 TCT_Unprotect();
841
842 /* Return to user mode */
843 NU_USER_MODE();
844
845 /* Return the signals to the caller. */
846 return(signals);
847 }
848
849
850 /*************************************************************************/
851 /* */
852 /* FUNCTION */
853 /* */
854 /* TCS_Register_Signal_Handler */
855 /* */
856 /* DESCRIPTION */
857 /* */
858 /* This function registers a signal handler for the calling task. */
859 /* Note that if an enabled signal is present and this is the first */
860 /* registered signal handler call, the signal is processed */
861 /* immediately. */
862 /* */
863 /* CALLED BY */
864 /* */
865 /* Application */
866 /* TCSE_Register_Signal_Handler Error checking shell */
867 /* */
868 /* CALLS */
869 /* */
870 /* [HIC_Make_History_Entry] Make entry in history log */
871 /* TCC_Signal_Shell Signal execution shell */
872 /* [TCT_Check_Stack] Stack checking function */
873 /* TCT_Protect Protect against other access */
874 /* TCT_Unprotect Release protection */
875 /* */
876 /* INPUTS */
877 /* */
878 /* signal_handler Signal execution shell */
879 /* */
880 /* OUTPUTS */
881 /* */
882 /* NU_SUCCESS */
883 /* */
884 /* HISTORY */
885 /* */
886 /* DATE REMARKS */
887 /* */
888 /* 03-01-1993 Created initial version 1.0 */
889 /* 04-19-1993 Verified version 1.0 */
890 /* 05-15-1993 Corrected problem with a comment */
891 /* 05-15-1993 Verified comment repair */
892 /* 03-01-1994 Added register optimizations, */
893 /* modified protection logic, */
894 /* resulting in version 1.1 */
895 /* */
896 /* 03-18-1994 Verified version 1.1 */
897 /* */
898 /*************************************************************************/
899 STATUS TCS_Register_Signal_Handler(VOID (*signal_handler)(UNSIGNED))
900 {
901
902 R1 TC_TCB *task; /* Task pointer */
903 NU_SUPERV_USER_VARIABLES
904
905 /* Switch to supervisor mode */
906 NU_SUPERVISOR_MODE();
907
908 #ifdef NU_ENABLE_STACK_CHECK
909
910 /* Call stack checking function to check for an overflow condition. */
911 TCT_Check_Stack();
912
913 #endif
914
915 #ifdef NU_ENABLE_HISTORY
916
917 /* Make an entry that corresponds to this function in the system history
918 log. */
919 HIC_Make_History_Entry(NU_REGISTER_SIGNAL_HANDLER_ID,
920 (UNSIGNED) signal_handler, (UNSIGNED) 0, (UNSIGNED) 0);
921
922 #endif
923
924 /* Pickup the task pointer. */
925 task = (TC_TCB *) TCD_Current_Thread;
926
927 /* Protect against simultaneous access. */
928 TCT_Protect(&TCD_System_Protect);
929
930 /* Put the new signal handler in. */
931 task -> tc_signal_handler = signal_handler;
932
933 /* Now, determine if the signal handler needs to be invoked. */
934 if ((task -> tc_enabled_signals & task -> tc_signals) &&
935 (!task -> tc_signal_active) &&
936 (task -> tc_signal_handler))
937 {
938
939 /* Signal processing is required. */
940
941 /* Indicate that signal processing is in progress. */
942 task -> tc_signal_active = NU_TRUE;
943
944 /* Clear the saved stack pointer to indicate that this is an
945 in line signal handler call. */
946 task -> tc_saved_stack_ptr = NU_NULL;
947
948 /* Release protection from multiple access. */
949 TCT_Unprotect();
950
951 /* Call the signal handling shell. */
952 TCC_Signal_Shell();
953 }
954 else
955
956 /* Release protection. */
957 TCT_Unprotect();
958
959 /* Return to user mode */
960 NU_USER_MODE();
961
962 /* Return success. */
963 return(NU_SUCCESS);
964 }
965
966
967 /*************************************************************************/
968 /* */
969 /* FUNCTION */
970 /* */
971 /* TCS_Send_Signals */
972 /* */
973 /* DESCRIPTION */
974 /* */
975 /* This function sends the specified task the specified signals. */
976 /* If enabled, the specified task is setup in order to process the */
977 /* signals. */
978 /* */
979 /* CALLED BY */
980 /* */
981 /* Application */
982 /* TCSE_Send_Signals Error checking shell */
983 /* */
984 /* CALLS */
985 /* */
986 /* [HIC_Make_History_Entry] Make entry in history log */
987 /* TCC_Resume_Task Resume task that is suspended*/
988 /* TCC_Signal_Shell Signal execution shell */
989 /* TCT_Build_Signal_Frame Build a signal frame */
990 /* [TCT_Check_Stack] Stack checking function */
991 /* TCT_Control_To_System Control to system */
992 /* TCT_Protect Protect against other access */
993 /* TCT_Unprotect Release protection */
994 /* */
995 /* INPUTS */
996 /* */
997 /* task_ptr Task pointer */
998 /* signals Signals to send to the task */
999 /* */
1000 /* OUTPUTS */
1001 /* */
1002 /* NU_SUCCESS */
1003 /* */
1004 /* HISTORY */
1005 /* */
1006 /* DATE REMARKS */
1007 /* */
1008 /* 03-01-1993 Created initial version 1.0 */
1009 /* 04-19-1993 Verified version 1.0 */
1010 /* 03-01-1994 Modified function interface, */
1011 /* added register optimizations, */
1012 /* modified protection logic, */
1013 /* resulting in version 1.1 */
1014 /* */
1015 /* 03-18-1994 Verified version 1.1 */
1016 /* 04-04-1996 On line 995, changed tc_signals */
1017 /* to tc_enabled_signals, */
1018 /* resulting in version 1.1+ */
1019 /* (spr 107) */
1020 /* */
1021 /*************************************************************************/
1022 STATUS TCS_Send_Signals(NU_TASK *task_ptr, UNSIGNED signals)
1023 {
1024
1025 R1 TC_TCB *task; /* Task control block ptr */
1026 NU_SUPERV_USER_VARIABLES
1027
1028 /* Switch to supervisor mode */
1029 NU_SUPERVISOR_MODE();
1030
1031 /* Move input task control block pointer into internal pointer. */
1032 task = (TC_TCB *) task_ptr;
1033
1034
1035 #ifdef NU_ENABLE_STACK_CHECK
1036
1037 /* Call stack checking function to check for an overflow condition. */
1038 TCT_Check_Stack();
1039
1040 #endif
1041
1042 #ifdef NU_ENABLE_HISTORY
1043
1044 /* Make an entry that corresponds to this function in the system history
1045 log. */
1046 HIC_Make_History_Entry(NU_SEND_SIGNALS_ID, (UNSIGNED) signals,
1047 (UNSIGNED) 0, (UNSIGNED) 0);
1048
1049 #endif
1050
1051 /* Protect against simultaneous access. */
1052 TCT_Protect(&TCD_System_Protect);
1053
1054 /* Or the new signals into the current signals. */
1055 task -> tc_signals = task -> tc_signals | signals;
1056
1057 #ifdef INCLUDE_PROVIEW
1058 _RTProf_DumpTask(task,RT_PROF_SEND_SIGNALS);
1059 #endif
1060 /* Now, determine if the signal handler needs to be invoked. */
1061 if ((task -> tc_signals & task -> tc_enabled_signals) &&
1062 (!task -> tc_signal_active) &&
1063 (task -> tc_status != NU_TERMINATED) &&
1064 (task -> tc_status != NU_FINISHED) &&
1065 (task -> tc_signal_handler))
1066 {
1067
1068 /* Indicate that signal processing is in progress. */
1069 task -> tc_signal_active = NU_TRUE;
1070
1071 /* Signal processing is required. Determine if the task is sending
1072 signals to itself or if the calling thread is not the current
1073 task. */
1074 if (task == (TC_TCB *) TCD_Current_Thread)
1075 {
1076
1077 /* Task sending signals to itself. */
1078
1079 /* Clear the saved stack pointer to indicate that this is an
1080 in line signal handler call. */
1081 task -> tc_saved_stack_ptr = NU_NULL;
1082
1083 /* Release protection from multiple access. */
1084 TCT_Unprotect();
1085
1086 /* Call the signal handling shell. */
1087 TCC_Signal_Shell();
1088 }
1089 else
1090 {
1091
1092 /* Target task must be prepared to receive the signals. */
1093
1094 /* First, insure that the target task is not in a protected
1095 area. */
1096 do
1097 {
1098
1099 /* Check for protection. Remember that protection is still
1100 in effect. */
1101 if (task -> tc_current_protect)
1102 {
1103
1104 /* Yes, target task is in a protected mode. Release
1105 the protection on the scheduling list and transfer
1106 control briefly to the target task. */
1107 TCT_Unprotect();
1108
1109 /* Switch to the protected task and wait until the
1110 task is not protected. */
1111 TCT_Protect_Switch(task);
1112
1113 /* Restore protection on the scheduling structures. */
1114 TCT_Protect(&TCD_System_Protect);
1115 }
1116 } while (task -> tc_current_protect);
1117
1118 /* Copy the current status and stack pointer to the signal save
1119 areas. */
1120 task -> tc_saved_status = task -> tc_status;
1121 task -> tc_saved_stack_ptr = task -> tc_stack_pointer;
1122
1123 /* Build a stack frame for the signal handling shell function. */
1124 TCT_Build_Signal_Frame(task);
1125
1126 /* Determine if the target task is currently suspended. If it is
1127 suspended for any other reason than a pure suspend, resume
1128 it. */
1129 if ((task -> tc_status != NU_READY) &&
1130 (task -> tc_status != NU_PURE_SUSPEND))
1131 {
1132
1133 /* Resume the target task and check for preemption. */
1134 if (TCC_Resume_Task(task_ptr, task -> tc_status))
1135
1136 /* Preemption needs to take place. */
1137 TCT_Control_To_System();
1138 }
1139 }
1140 }
1141
1142 /* Release protection, no signals are currently enabled. */
1143 TCT_Unprotect();
1144
1145 /* Return to user mode */
1146 NU_USER_MODE();
1147
1148 /* Return a successful status. */
1149 return(NU_SUCCESS);
1150 }
1151
1152
1153
1154