FreeCalypso > hg > ffs-editor
comparison src/nucleus/tcs.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 /* 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 |