comparison src/nucleus/tcc.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 /* tcc.c Nucleus PLUS 1.14 */
17 /* */
18 /* COMPONENT */
19 /* */
20 /* TC - Thread Control */
21 /* */
22 /* DESCRIPTION */
23 /* */
24 /* This file contains the core routines for the Thread Control */
25 /* component. */
26 /* */
27 /* DATA STRUCTURES */
28 /* */
29 /* None */
30 /* */
31 /* FUNCTIONS */
32 /* */
33 /* TCC_Create_Task Create a task */
34 /* TCC_Delete_Task Delete a task */
35 /* TCC_Create_HISR Create HISR */
36 /* TCC_Delete_HISR Delete HISR */
37 /* TCC_Reset_Task Reset the specified task */
38 /* TCC_Terminate_Task Terminate the specified task */
39 /* TCC_Resume_Task Resume a task */
40 /* TCC_Resume_Service Resume a task service call */
41 /* TCC_Suspend_Task Suspend a task */
42 /* TCC_Suspend_Service Suspend a task service call */
43 /* TCC_Task_Timeout Task timeout function */
44 /* TCC_Task_Sleep Task sleep request */
45 /* TCC_Relinquish Relinquish task execution */
46 /* TCC_Time_Slice Process task time-slice */
47 /* TCC_Current_Task_Pointer Retrieve current task pointer*/
48 /* TCC_Current_HISR_Pointer Retrieve current HISR pointer*/
49 /* TCC_Task_Shell Task execution shell */
50 /* TCC_Signal_Shell Signal execution shell */
51 /* TCC_Dispatch_LISR Dispatch LISR routine */
52 /* TCC_Register_LISR Register an LISR */
53 /* */
54 /* DEPENDENCIES */
55 /* */
56 /* cs_extr.h Common Service functions */
57 /* tc_extr.h Thread Control functions */
58 /* in_extr.h Initialization/Interrupt */
59 /* functions */
60 /* tm_extr.h Timer Control function */
61 /* er_extr.h Error handling function */
62 /* hi_extr.h History functions */
63 /* */
64 /* HISTORY */
65 /* */
66 /* DATE REMARKS */
67 /* */
68 /* 03-01-1993 Created initial version 1.0 */
69 /* 04-19-1993 Verified version 1.0 */
70 /* 05-15-1993 Corrected comment problems in */
71 /* TCC_Control_Signals and */
72 /* TCC_Register_Signal_Handler, */
73 /* making version 1.0a */
74 /* 05-15-1993 Verified version 1.0a */
75 /* 06-01-1993 Modified a multi-line comment */
76 /* after a #include directive */
77 /* that gave some compilers a */
78 /* problem, making version 1.0b */
79 /* 06-01-1993 Verified version 1.0b */
80 /* 08-09-1993 Corrected pointer retrieval */
81 /* loop, resulting in version 1.0c */
82 /* 08-09-1993 Verified version 1.0c */
83 /* 09-19-1993 Corrected an initialization */
84 /* problem of de-referencing a */
85 /* NULL pointer, resulting in */
86 /* version 1.0d */
87 /* 09-19-1993 Verified version 1.0d */
88 /* 11-01-1993 Added logic to save unhandled */
89 /* interrupt vector number in */
90 /* a global variable, resulting */
91 /* in version 1.0e */
92 /* 11-01-1993 Verified version 1.0e */
93 /* 02-01-1994 Corrected a suspension with */
94 /* timeout problem that caused */
95 /* unconditional task suspension */
96 /* for timeouts and sleeps for 1 */
97 /* tick, resulting in version 1.0f */
98 /* 02-01-1994 Verified version 1.0f */
99 /* 03-01-1994 Added another routine that */
100 /* validates resume calls with */
101 /* the appropriate protection and */
102 /* added code to clear cleanup */
103 /* information at task create and */
104 /* task resume time, resulting in */
105 /* version 1.0g */
106 /* 03-01-1994 Verified version 1.0g */
107 /* 03-01-1994 Moved non-core functions into */
108 /* supplemental files, changed */
109 /* function interfaces to match */
110 /* those in prototype, added */
111 /* register options, fixed bug */
112 /* in suspending current task from */
113 /* a HISR, added a system protect */
114 /* structure to reduce overhead */
115 /* in protection, moved resume */
116 /* validate to error checking */
117 /* file, resulting in version 1.1 */
118 /* */
119 /* 03-18-1994 Verified version 1.1 */
120 /* 12-18-1995 Modified TCC_Resume_Service, */
121 /* resulting in version 1.1+ */
122 /* (SPR 36, 64, 66, 77) */
123 /* 04-17-1996 updated to version 1.2 */
124 /* 06-01-1996 Modified TCC_Suspend_Task */
125 /* (SPR152) creating version 1.2a */
126 /* 10-29-1997 Modified TCC_Resume_Task */
127 /* (SPR115) creating vresion 1.2b */
128 /* 01-23-1998 Released version 1.2b */
129 /* 03-20-1998 Corrected problem where tasks */
130 /* created with NU_NO_PREEMPT in */
131 /* Application_Initialize would */
132 /* start in the order of creation */
133 /* and not in priority order. */
134 /* SPR455 creates version 1.2c */
135 /* 03-24-1998 Released version 1.3. */
136 /* 10-02-1998 Another protect problem (1.3a) */
137 /* 10-02-1998 Corrected a problem where a */
138 /* a timer expiration occurs */
139 /* during signal handler execution */
140 /* and causes the task to never */
141 /* run again (SPR 923) creating */
142 /* version 1.3b. */
143 /* 03-26-1999 Released 1.11m (new release */
144 /* numbering scheme) */
145 /* 04-17-2002 Released version 1.13m */
146 /* 11-07-2002 Released version 1.14 */
147 /*************************************************************************/
148 #define NU_SOURCE_FILE
149
150 #include "in_defs.h" /* Initialization defines */
151 #include "cs_extr.h" /* Common service functions */
152 #include "tc_extr.h" /* Thread control functions */
153 #include "in_extr.h" /* Initialization/Interrupt */
154 /* functions */
155 #include "tm_extr.h" /* Timer control functions */
156 #include "er_extr.h" /* Error handling function */
157 #include "hi_extr.h" /* History functions */
158 #include "profiler.h" /* Nucleus Profiling header */
159
160 #if ((defined(NU_MODULE_SUPPORT)) && (NU_MODULE_SUPPORT > 0))
161 #include "module/inc/ms_defs.h" /* MS_Module typedef */
162 #endif
163
164 /* Define external inner-component global data references. */
165
166 extern INT INC_Initialize_State;
167 extern CS_NODE *TCD_Created_Tasks_List;
168 extern UNSIGNED TCD_Total_Tasks;
169 extern TC_TCB *TCD_Priority_List[TC_PRIORITIES];
170 extern UNSIGNED TCD_Priority_Groups;
171 extern DATA_ELEMENT TCD_Sub_Priority_Groups[TC_MAX_GROUPS];
172 extern UNSIGNED_CHAR TCD_Lowest_Set_Bit[];
173 extern INT TCD_Highest_Priority;
174 extern TC_TCB *TCD_Execute_Task;
175 extern VOID *TCD_Current_Thread;
176 extern UNSIGNED_CHAR TCD_Registered_LISRs[NU_MAX_VECTORS+1];
177 extern VOID (*TCD_LISR_Pointers[NU_MAX_LISRS+1])(INT vector);
178 extern INT TCD_Interrupt_Count;
179 extern INT TCD_Stack_Switched;
180 extern TC_PROTECT TCD_List_Protect;
181 extern TC_PROTECT TCD_System_Protect;
182 extern TC_PROTECT TCD_LISR_Protect;
183 extern CS_NODE *TCD_Created_HISRs_List;
184 extern UNSIGNED TCD_Total_HISRs;
185 extern TC_PROTECT TCD_HISR_Protect;
186 extern INT TCD_Unhandled_Interrupt;
187
188
189 /* Define external inner-component function calls that are not available to
190 other components. */
191
192 VOID TCT_Build_Task_Stack(TC_TCB *task_ptr);
193 VOID TCT_Build_HISR_Stack(TC_HCB *hisr_ptr);
194 VOID TCT_Build_Signal_Frame(TC_TCB *task_ptr);
195 VOID TCT_Protect_Switch(TC_TCB *task);
196 VOID TCT_Signal_Exit(VOID);
197
198
199 /* Define internal function calls. */
200
201 VOID TCC_Signal_Shell(VOID);
202
203
204 #if defined(NU_MODULE_SUPPORT) && (NU_MODULE_SUPPORT > 0)
205
206 /* Define service routines "privately" imported from other components */
207 extern MS_MODULE* msd_current_module;
208
209 STATUS MSC_Bind_Module_HISR(MS_MODULE* module, TC_HCB* hisr);
210 STATUS MSC_Bind_Module_Task(MS_MODULE* module, TC_TCB* task);
211
212 #endif /* NU_MODULE_SUPPORT */
213
214 /*************************************************************************/
215 /* */
216 /* FUNCTION */
217 /* */
218 /* TCC_Create_Task */
219 /* */
220 /* DESCRIPTION */
221 /* */
222 /* This function creates a task and then places it on the list of */
223 /* created tasks. All the resources necessary to create the task */
224 /* are supplied to this routine. If specified, the newly created */
225 /* task is started. Otherwise, it is left in a suspended state. */
226 /* */
227 /* CALLED BY */
228 /* */
229 /* Application */
230 /* TCCE_Create_Task Error checking shell */
231 /* */
232 /* CALLS */
233 /* */
234 /* CSC_Place_On_List Add TCB to linked-list */
235 /* [HIC_Make_History_Entry] Make entry in history log */
236 /* TCC_Resume_Task Start the created task */
237 /* TCT_Build_Task_Stack Build an initial task stack */
238 /* [TCT_Check_Stack] Stack checking function */
239 /* TCT_Control_To_System Transfer control to system */
240 /* TCT_Protect Protect created task list */
241 /* TCT_Unprotect Release protection of list */
242 /* TMC_Init_Task_Timer Initialize the task's timer */
243 /* */
244 /* INPUTS */
245 /* */
246 /* task_ptr Task control block pointer */
247 /* name Task name */
248 /* task_entry Entry function of the task */
249 /* argc Optional task parameter */
250 /* argv Optional task parameter */
251 /* stack_address Pointer to start of stack */
252 /* stack_size Size of task stack in bytes */
253 /* priority Task priority */
254 /* time_slice Task time slice */
255 /* preempt Task preemptability flag */
256 /* auto_start Automatic task start */
257 /* */
258 /* OUTPUTS */
259 /* */
260 /* NU_SUCCESS */
261 /* */
262 /* HISTORY */
263 /* */
264 /* DATE REMARKS */
265 /* */
266 /* 03-01-1993 Created initial version 1.0 */
267 /* 04-19-1993 Verified version 1.0 */
268 /* 03-01-1994 Modified function interface, */
269 /* added register optimizations, */
270 /* added system protection logic, */
271 /* resulting in version 1.1 */
272 /* */
273 /* 03-18-1994 Verified version 1.1 */
274 /* */
275 /*************************************************************************/
276 STATUS TCC_Create_Task(NU_TASK *task_ptr, CHAR *name,
277 VOID (*task_entry)(UNSIGNED, VOID *), UNSIGNED argc, VOID *argv,
278 VOID *stack_address, UNSIGNED stack_size,
279 OPTION priority, UNSIGNED time_slice,
280 OPTION preempt, OPTION auto_start)
281 {
282
283 R1 TC_TCB *task; /* Task control block ptr */
284 R2 INT i; /* Working index variable */
285 STATUS status = NU_SUCCESS;
286
287 NU_SUPERV_USER_VARIABLES
288
289 /* Switch to supervisor mode */
290 NU_SUPERVISOR_MODE();
291
292 /* Move input task pointer into internal pointer. */
293 task = (TC_TCB *) task_ptr;
294
295
296 #ifdef NU_ENABLE_STACK_CHECK
297
298 /* Call stack checking function to check for an overflow condition. */
299 TCT_Check_Stack();
300
301 #endif
302
303 #ifdef NU_ENABLE_HISTORY
304
305 /* Make an entry that corresponds to this function in the system history
306 log. */
307 HIC_Make_History_Entry(NU_CREATE_TASK_ID, (UNSIGNED) task,
308 (UNSIGNED) name, (UNSIGNED) task_entry);
309
310 #endif
311
312 /* First, clear the task ID just in case it is an old Task
313 Control Block. */
314 task -> tc_id = 0;
315
316 /* Fill in the task name. */
317 for (i = 0; i < NU_MAX_NAME; i++)
318 task -> tc_name[i] = name[i];
319
320 /* Fill in the basic task information. */
321 task -> tc_entry = task_entry;
322 task -> tc_argc = argc;
323 task -> tc_argv = argv;
324 task -> tc_status = NU_PURE_SUSPEND;
325 task -> tc_delayed_suspend = NU_FALSE;
326 task -> tc_scheduled = 0;
327 task -> tc_time_slice = time_slice;
328 task -> tc_cur_time_slice = time_slice;
329 task -> tc_current_protect = NU_NULL;
330 task -> tc_suspend_protect = NU_NULL;
331 task -> tc_cleanup = NU_NULL;
332 task -> tc_cleanup_info = NU_NULL;
333
334 /* Setup task's preemption posture. */
335 if (preempt == NU_PREEMPT)
336 task -> tc_preemption = NU_TRUE;
337 else
338 task -> tc_preemption = NU_FALSE;
339
340 /* Fill in information about the task's stack. */
341 task -> tc_stack_start = stack_address;
342 task -> tc_stack_end = 0;
343 task -> tc_stack_size = stack_size;
344 task -> tc_stack_minimum = stack_size;
345
346 /* Setup priority information for the task. There are two bit maps
347 associated with each task. The first bit map indicates which group
348 of 8-priorities it is. The second bit map indicates the actual
349 priority within the group. */
350 task -> tc_priority = priority;
351 task -> tc_priority_head = &(TCD_Priority_List[priority]);
352 task -> tc_sub_priority = (DATA_ELEMENT) (1 << (priority & 7));
353 priority = priority >> 3;
354 task -> tc_priority_group = ((UNSIGNED) 1) << priority;
355 task -> tc_sub_priority_ptr = &(TCD_Sub_Priority_Groups[priority]);
356
357 /* Initialize link pointers. */
358 task -> tc_created.cs_previous = NU_NULL;
359 task -> tc_created.cs_next = NU_NULL;
360 task -> tc_ready_previous = NU_NULL;
361 task -> tc_ready_next = NU_NULL;
362
363 /* Build a stack frame for this task by calling TCT_Build_Task_Stack. */
364 TCT_Build_Task_Stack(task);
365
366 /* Initialize the signal information of the task. */
367 task -> tc_signals = 0;
368 task -> tc_enabled_signals = 0;
369 task -> tc_signal_handler = 0;
370 task -> tc_signal_active = NU_FALSE;
371 /* Initialize additional kernel options data */
372
373 #if (NU_SUPERV_USER_MODE == 1)
374 task->tc_su_mode = 0; /* Initially in User mode */
375 task->tc_module = 0; /* Not initially bound to a module */
376 #endif
377
378 /* Initialize the task timer. */
379 task -> tc_timer_active = NU_FALSE;
380 TMC_Init_Task_Timer(&(task -> tc_timer_control), (VOID *) task);
381
382 /* Protect the list of created tasks. */
383 TCT_Protect(&TCD_List_Protect);
384
385 /* At this point the task is completely built. The ID can now be
386 set and it can be linked into the created task list. */
387 task -> tc_id = TC_TASK_ID;
388
389 #if defined(NU_MODULE_SUPPORT) && (NU_MODULE_SUPPORT > 0)
390 /* If executing in a thread's context, bind to that thread's module */
391 if(TCD_Current_Thread != NU_NULL)
392 {
393 status = MSC_Bind_Module_Task(
394 (MS_MODULE*)(((TC_TCB*)(TCD_Current_Thread))->tc_module), task);
395 }
396 else /* It must be initialization time, so use the current module */
397 {
398 status = MSC_Bind_Module_Task(msd_current_module, task);
399 }
400 #endif /* NU_MODULE_SUPPORT */
401
402 /* Link the task into the list of created tasks and increment the
403 total number of tasks in the system. */
404 CSC_Place_On_List(&TCD_Created_Tasks_List, &(task -> tc_created));
405 TCD_Total_Tasks++;
406
407 #ifdef INCLUDE_PROVIEW
408 _RTProf_DumpTask(task,RT_PROF_CREATE_TASK);
409 #endif
410
411 /* Release the protection. */
412 TCT_Unprotect();
413
414 /* Determine if the task should be automatically started. */
415 if (auto_start == NU_START)
416 {
417
418 /* Protect the system data structures. */
419 TCT_Protect(&TCD_System_Protect);
420
421 /* Start the task by resuming it. If the preemption is required,
422 leave the current task. */
423 if (TCC_Resume_Task(task_ptr, NU_PURE_SUSPEND))
424
425
426 /* Transfer control back to the system. */
427 TCT_Control_To_System();
428 else
429
430 /* Release the protection. */
431 TCT_Unprotect();
432 }
433
434 /* Return to user mode */
435 NU_USER_MODE();
436
437 /* Return successful completion. */
438 return(status);
439 }
440
441
442 /*************************************************************************/
443 /* */
444 /* FUNCTION */
445 /* */
446 /* TCC_Create_HISR */
447 /* */
448 /* DESCRIPTION */
449 /* */
450 /* This function creates a High-Level Interrupt Service Routine */
451 /* (HISR) and then places it on the list of created HISRs. All */
452 /* the resources necessary to create the HISR are supplied to this */
453 /* routine. HISRs are always created in a dormant state. */
454 /* */
455 /* CALLED BY */
456 /* */
457 /* Application */
458 /* TCCE_Create_HISR Error checking shell */
459 /* */
460 /* CALLS */
461 /* */
462 /* CSC_Place_On_List Add TCB to linked-list */
463 /* [HIC_Make_History_Entry] Make entry in history log */
464 /* TCT_Build_HISR_Stack Build an initial HISR stack */
465 /* [TCT_Check_Stack] Stack checking function */
466 /* TCT_Protect Protect created HISR list */
467 /* TCT_Unprotect Release protection of list */
468 /* */
469 /* INPUTS */
470 /* */
471 /* hisr_ptr HISR control block pointer */
472 /* name HISR name */
473 /* hisr_entry Entry function of the HISR */
474 /* priority Task priority */
475 /* stack_address Pointer to start of stack */
476 /* stack_size Size of HISR stack in bytes */
477 /* */
478 /* OUTPUTS */
479 /* */
480 /* NU_SUCCESS */
481 /* */
482 /* HISTORY */
483 /* */
484 /* DATE REMARKS */
485 /* */
486 /* 03-01-1993 Created initial version 1.0 */
487 /* 04-19-1993 Verified version 1.0 */
488 /* 03-01-1994 Modified function interface, */
489 /* added register optimizations, */
490 /* added more control block */
491 /* initialization, resulting in */
492 /* version 1.1 */
493 /* */
494 /* 03-18-1994 Verified version 1.1 */
495 /* */
496 /*************************************************************************/
497 STATUS TCC_Create_HISR(NU_HISR *hisr_ptr, CHAR *name,
498 VOID (*hisr_entry)(VOID), OPTION priority,
499 VOID *stack_address, UNSIGNED stack_size)
500 {
501
502 R1 TC_HCB *hisr; /* HISR control block ptr */
503 R2 INT i; /* Working index variable */
504 STATUS status = NU_SUCCESS;
505
506 NU_SUPERV_USER_VARIABLES
507
508 /* Switch to supervisor mode */
509 NU_SUPERVISOR_MODE();
510
511 /* Move input HISR pointer into internal pointer. */
512 hisr = (TC_HCB *) hisr_ptr;
513
514
515 #ifdef NU_ENABLE_STACK_CHECK
516
517 /* Call stack checking function to check for an overflow condition. */
518 TCT_Check_Stack();
519
520 #endif
521
522 #ifdef NU_ENABLE_HISTORY
523
524 /* Make an entry that corresponds to this function in the system history
525 log. */
526 HIC_Make_History_Entry(NU_CREATE_HISR_ID, (UNSIGNED) hisr,
527 (UNSIGNED) name, (UNSIGNED) hisr_entry);
528
529 #endif
530
531 /* First, clear the HISR ID just in case it is an old HISR
532 Control Block. */
533 hisr -> tc_id = 0;
534
535 /* Fill in the HISR name. */
536 for (i = 0; i < NU_MAX_NAME; i++)
537 hisr -> tc_name[i] = name[i];
538
539 /* Fill in the basic HISR information. */
540 hisr -> tc_entry = hisr_entry;
541 hisr -> tc_scheduled = 0;
542 hisr -> tc_activation_count = 0;
543 hisr -> tc_cur_time_slice = 0;
544
545 /* Fill in information about the HISR's stack. */
546 hisr -> tc_stack_start = stack_address;
547 hisr -> tc_stack_end = 0;
548 hisr -> tc_stack_size = stack_size;
549 hisr -> tc_stack_minimum = stack_size;
550
551 /* Setup priority information for the HISR. Priorities range from 0 to
552 TC_HISR_PRIORITIES - 1. */
553 hisr -> tc_priority = priority & 3;
554
555 /* Initialize link pointers. */
556 hisr -> tc_created.cs_previous = NU_NULL;
557 hisr -> tc_created.cs_next = NU_NULL;
558 hisr -> tc_active_next = NU_NULL;
559
560 /* Clear protect pointer. */
561 hisr -> tc_current_protect = NU_NULL;
562
563 /* Initialize additional kernel options data */
564 #if (NU_SUPERV_USER_MODE == 1)
565 hisr->tc_su_mode = 1; /* TCT_HISR_Shell in Supervisor mode */
566 hisr->tc_module = 0; /* Not initially bound to a module */
567 #endif
568
569 /* Build a stack frame for this HISR by calling TCT_Build_HISR_Stack. */
570 TCT_Build_HISR_Stack(hisr);
571
572 /* Protect the list of created HISRs. */
573 TCT_Protect(&TCD_HISR_Protect);
574
575 /* At this point the HISR is completely built. The ID can now be
576 set and it can be linked into the created HISR list. */
577 hisr -> tc_id = TC_HISR_ID;
578
579 #if defined(NU_MODULE_SUPPORT) && (NU_MODULE_SUPPORT > 0)
580 /* If executing in a thread's context, bind to that thread's module */
581 if(TCD_Current_Thread != NU_NULL)
582 {
583 status = MSC_Bind_Module_HISR(
584 (MS_MODULE*)(((TC_TCB*)(TCD_Current_Thread))->tc_module), hisr);
585 }
586 else /* It must be initialization time, so use the current module */
587 {
588 status = MSC_Bind_Module_HISR(msd_current_module, hisr);
589 }
590 #endif /* NU_MODULE_SUPPORT */
591
592 /* Link the HISR into the list of created HISRs and increment the
593 total number of HISRs in the system. */
594 CSC_Place_On_List(&TCD_Created_HISRs_List, &(hisr -> tc_created));
595 TCD_Total_HISRs++;
596
597 #ifdef INCLUDE_PROVIEW
598 _RTProf_DumpHisr(hisr,RT_PROF_CREATE_HISR);
599 #endif
600
601 /* Release the protection. */
602 TCT_Unprotect();
603
604 /* Return to user mode */
605 NU_USER_MODE();
606
607 /* Return successful completion. */
608 return(status);
609 }
610
611
612 /*************************************************************************/
613 /* */
614 /* FUNCTION */
615 /* */
616 /* TCC_Delete_Task */
617 /* */
618 /* DESCRIPTION */
619 /* */
620 /* This function deletes a task and removes it from the list of */
621 /* created tasks. It is assumed by this function that the task is */
622 /* in a finished or terminated state. Note that this function */
623 /* does not free memory associated with the task's control block or */
624 /* its stack. This is the responsibility of the application. */
625 /* */
626 /* CALLED BY */
627 /* */
628 /* Application */
629 /* TCCE_Delete_Task Error checking shell */
630 /* */
631 /* CALLS */
632 /* */
633 /* CSC_Remove_From_List Remove node from list */
634 /* [HIC_Make_History_Entry] Make entry in history log */
635 /* [TCT_Check_Stack] Stack checking function */
636 /* TCT_Protect Protect created task list */
637 /* TCT_Unprotect Release protection of list */
638 /* */
639 /* INPUTS */
640 /* */
641 /* task_ptr Task control block pointer */
642 /* */
643 /* OUTPUTS */
644 /* */
645 /* NU_SUCCESS */
646 /* */
647 /* HISTORY */
648 /* */
649 /* DATE REMARKS */
650 /* */
651 /* 03-01-1993 Created initial version 1.0 */
652 /* 04-19-1993 Verified version 1.0 */
653 /* 03-01-1994 Modified function interface, */
654 /* added register optimizations, */
655 /* resulting in version 1.1 */
656 /* */
657 /* 03-18-1994 Verified version 1.1 */
658 /* */
659 /*************************************************************************/
660 STATUS TCC_Delete_Task(NU_TASK *task_ptr)
661 {
662
663 R1 TC_TCB *task; /* Task control block ptr */
664 NU_SUPERV_USER_VARIABLES
665
666 /* Switch to supervisor mode */
667 NU_SUPERVISOR_MODE();
668
669 /* Move input task pointer into internal pointer. */
670 task = (TC_TCB *) task_ptr;
671
672
673 #ifdef NU_ENABLE_STACK_CHECK
674
675 /* Call stack checking function to check for an overflow condition. */
676 TCT_Check_Stack();
677
678 #endif
679
680 #ifdef NU_ENABLE_HISTORY
681
682 /* Make an entry that corresponds to this function in the system history
683 log. */
684 HIC_Make_History_Entry(NU_DELETE_TASK_ID, (UNSIGNED) task,
685 (UNSIGNED) 0, (UNSIGNED) 0);
686
687 #endif
688
689 /* Protect the list of created tasks. */
690 TCT_Protect(&TCD_List_Protect);
691
692 #ifdef INCLUDE_PROVIEW
693 _RTProf_DumpTask(task,RT_PROF_DELETE_TASK);
694 #endif /*INCLUDE_PROVIEW*/
695
696 /* Remove the task from the list of created tasks. */
697 CSC_Remove_From_List(&TCD_Created_Tasks_List, &(task -> tc_created));
698
699 /* Decrement the total number of created tasks. */
700 TCD_Total_Tasks--;
701
702 /* Clear the task ID just in case. */
703 task -> tc_id = 0;
704
705 /* Release protection. */
706 TCT_Unprotect();
707
708 /* Return to user mode */
709 NU_USER_MODE();
710
711 /* Return a successful completion. */
712 return(NU_SUCCESS);
713 }
714
715
716 /*************************************************************************/
717 /* */
718 /* FUNCTION */
719 /* */
720 /* TCC_Delete_HISR */
721 /* */
722 /* DESCRIPTION */
723 /* */
724 /* This function deletes a HISR and removes it from the list of */
725 /* created HISRs. It is assumed by this function that the HISR is */
726 /* in a non-active state. Note that this function does not free */
727 /* memory associated with the HISR's control block or its stack. */
728 /* This is the responsibility of the application. */
729 /* */
730 /* CALLED BY */
731 /* */
732 /* Application */
733 /* TCCE_Delete_HISR Error checking shell */
734 /* */
735 /* CALLS */
736 /* */
737 /* CSC_Remove_From_List Remove node from list */
738 /* [HIC_Make_History_Entry] Make entry in history log */
739 /* [TCT_Check_Stack] Stack checking function */
740 /* TCT_Protect Protect created HISR list */
741 /* TCT_Unprotect Release protection of list */
742 /* */
743 /* INPUTS */
744 /* */
745 /* hisr_ptr HISR control block pointer */
746 /* */
747 /* OUTPUTS */
748 /* */
749 /* NU_SUCCESS */
750 /* */
751 /* HISTORY */
752 /* */
753 /* DATE REMARKS */
754 /* */
755 /* 03-01-1993 Created initial version 1.0 */
756 /* 04-19-1993 Verified version 1.0 */
757 /* 03-01-1994 Modified function interface, */
758 /* added register optimizations, */
759 /* resulting in version 1.1 */
760 /* */
761 /* 03-18-1994 Verified version 1.1 */
762 /* */
763 /*************************************************************************/
764 STATUS TCC_Delete_HISR(NU_HISR *hisr_ptr)
765 {
766
767 R1 TC_HCB *hisr; /* HISR control block ptr */
768 NU_SUPERV_USER_VARIABLES
769
770 /* Switch to supervisor mode */
771 NU_SUPERVISOR_MODE();
772
773 /* Move input HISR pointer into internal pointer. */
774 hisr = (TC_HCB *) hisr_ptr;
775
776
777 #ifdef NU_ENABLE_STACK_CHECK
778
779 /* Call stack checking function to check for an overflow condition. */
780 TCT_Check_Stack();
781
782 #endif
783
784 #ifdef NU_ENABLE_HISTORY
785
786 /* Make an entry that corresponds to this function in the system history
787 log. */
788 HIC_Make_History_Entry(NU_DELETE_HISR_ID, (UNSIGNED) hisr,
789 (UNSIGNED) 0, (UNSIGNED) 0);
790
791 #endif
792
793 /* Protect the list of created HISRs. */
794 TCT_Protect(&TCD_HISR_Protect);
795
796 #ifdef INCLUDE_PROVIEW
797 _RTProf_DumpHisr(hisr,RT_PROF_DELETE_HISR);
798 #endif /*INCLUDE_PROVIEW*/
799
800 /* Remove the HISR from the list of created HISRs. */
801 CSC_Remove_From_List(&TCD_Created_HISRs_List, &(hisr -> tc_created));
802
803 /* Decrement the total number of created HISRs. */
804 TCD_Total_HISRs--;
805
806 /* Clear the HISR ID just in case. */
807 hisr -> tc_id = 0;
808
809 /* Release protection. */
810 TCT_Unprotect();
811
812 /* Return to user mode */
813 NU_USER_MODE();
814
815 /* Return a successful completion. */
816 return(NU_SUCCESS);
817 }
818
819
820 /*************************************************************************/
821 /* */
822 /* FUNCTION */
823 /* */
824 /* TCC_Reset_Task */
825 /* */
826 /* DESCRIPTION */
827 /* */
828 /* This function resets the specified task. Note that a task reset */
829 /* can only be performed on tasks in a finished or terminated state.*/
830 /* The task is left in an unconditional suspended state. */
831 /* */
832 /* CALLED BY */
833 /* */
834 /* Application */
835 /* TCCE_Reset_Task Error checking shell */
836 /* */
837 /* CALLS */
838 /* */
839 /* [HIC_Make_History_Entry] Make entry in history log */
840 /* TCT_Build_Task_Stack Build an initial task stack */
841 /* [TCT_Check_Stack] Stack checking function */
842 /* TCT_Protect Protect created task list */
843 /* TCT_Unprotect Release protection of list */
844 /* */
845 /* INPUTS */
846 /* */
847 /* task_ptr Task control block pointer */
848 /* argc Optional task parameter */
849 /* argv Optional task parameter */
850 /* */
851 /* OUTPUTS */
852 /* */
853 /* NU_SUCCESS Indicates successful request */
854 /* NU_NOT_TERMINATED Indicates task was not */
855 /* finished or terminated */
856 /* */
857 /* HISTORY */
858 /* */
859 /* DATE REMARKS */
860 /* */
861 /* 03-01-1993 Created initial version 1.0 */
862 /* 04-19-1993 Verified version 1.0 */
863 /* 03-01-1994 Modified function interface, */
864 /* added register optimizations, */
865 /* added system protection logic, */
866 /* resulting in version 1.1 */
867 /* */
868 /* 03-18-1994 Verified version 1.1 */
869 /* */
870 /*************************************************************************/
871 STATUS TCC_Reset_Task(NU_TASK *task_ptr, UNSIGNED argc, VOID *argv)
872 {
873
874 R1 TC_TCB *task; /* Task control block ptr */
875 STATUS status; /* Status of the request */
876 NU_SUPERV_USER_VARIABLES
877
878 /* Switch to supervisor mode */
879 NU_SUPERVISOR_MODE();
880
881 /* Move input task pointer into internal pointer. */
882 task = (TC_TCB *) task_ptr;
883
884 #ifdef NU_ENABLE_STACK_CHECK
885
886 /* Call stack checking function to check for an overflow condition. */
887 TCT_Check_Stack();
888
889 #endif
890
891 #ifdef NU_ENABLE_HISTORY
892
893 /* Make an entry that corresponds to this function in the system history
894 log. */
895 HIC_Make_History_Entry(NU_RESET_TASK_ID, (UNSIGNED) task,
896 (UNSIGNED) argc, (UNSIGNED) argv);
897
898 #endif
899
900 /* Protect system structures. */
901 TCT_Protect(&TCD_System_Protect);
902
903 /* Determine if the task is in the proper state. */
904 if ((task -> tc_status == NU_FINISHED) ||
905 (task -> tc_status == NU_TERMINATED))
906 {
907
908 /* Yes, a valid reset is present. Indicate this in the status. */
909 status = NU_SUCCESS;
910
911 /* Fill in the new argument information and reset some of the other
912 fields. */
913 task -> tc_argc = argc;
914 task -> tc_argv = argv;
915 task -> tc_status = NU_PURE_SUSPEND;
916 task -> tc_delayed_suspend = NU_FALSE;
917 task -> tc_scheduled = 0;
918 task -> tc_stack_minimum = task -> tc_stack_size;
919
920 #if (NU_SUPERV_USER_MODE == 1)
921 /* Since we are doing a complete reset we need to ensure
922 that this field is 0 since the task will be started in
923 user mode. TCC_Task_Shell can not return and therefore
924 left the task in supervisor mode when the task completed.
925 If we were to not re-initialize this field the task would
926 become locked in user mode and API would fail. */
927 task -> tc_su_mode = 0;
928 #endif
929
930 /* Build a stack frame for this task by calling
931 TCT_Build_Task_Stack. */
932 TCT_Build_Task_Stack(task);
933 }
934 else
935
936 /* The requested task is not in a finished or terminated state. */
937 status = NU_NOT_TERMINATED;
938
939 #ifdef INCLUDE_PROVIEW
940 _RTProf_DumpTask(task,RT_PROF_RESET_TASK);
941 #endif /*INCLUDE_PROVIEW*/
942
943 /* Release the protection. */
944 TCT_Unprotect();
945
946 /* Return to user mode */
947 NU_USER_MODE();
948
949 /* Return completion status. */
950 return(status);
951 }
952
953
954 /*************************************************************************/
955 /* */
956 /* FUNCTION */
957 /* */
958 /* TCC_Terminate_Task */
959 /* */
960 /* DESCRIPTION */
961 /* */
962 /* This function terminates the specified task. If the task is */
963 /* already terminated, this function does nothing. If the task */
964 /* to terminate is currently suspended, the specified cleanup */
965 /* routine is also invoked to cleanup suspension data structures. */
966 /* */
967 /* CALLED BY */
968 /* */
969 /* Application */
970 /* TCCE_Terminate_Task Error checking shell */
971 /* */
972 /* CALLS */
973 /* */
974 /* Cleanup routine Task's suspend cleanup funct */
975 /* [HIC_Make_History_Entry] Make entry in history log */
976 /* TCC_Suspend_Task Suspend a ready task */
977 /* [TCT_Check_Stack] Stack checking function */
978 /* TCT_Protect Protect created task list */
979 /* TCT_Unprotect Release protection of list */
980 /* TCT_Unprotect_Specific Specific unprotection */
981 /* TMC_Stop_Task_Timer Stop a task timer */
982 /* */
983 /* INPUTS */
984 /* */
985 /* task_ptr Task control block pointer */
986 /* */
987 /* OUTPUTS */
988 /* */
989 /* NU_SUCCESS */
990 /* */
991 /* HISTORY */
992 /* */
993 /* DATE REMARKS */
994 /* */
995 /* 03-01-1993 Created initial version 1.0 */
996 /* 04-19-1993 Verified version 1.0 */
997 /* 03-01-1994 Modified function interface, */
998 /* added register optimizations, */
999 /* added system protection logic, */
1000 /* resulting in version 1.1 */
1001 /* */
1002 /* 03-18-1994 Verified version 1.1 */
1003 /* */
1004 /*************************************************************************/
1005 STATUS TCC_Terminate_Task(NU_TASK *task_ptr)
1006 {
1007
1008 R1 TC_TCB *task; /* Task control block ptr */
1009 TC_PROTECT *suspend_protect; /* Suspension protection ptr */
1010 DATA_ELEMENT status; /* Task status */
1011 NU_SUPERV_USER_VARIABLES
1012
1013 /* Switch to supervisor mode */
1014 NU_SUPERVISOR_MODE();
1015
1016 /* Move task pointer into internal pointer. */
1017 task = (TC_TCB *) task_ptr;
1018
1019
1020 #ifdef NU_ENABLE_STACK_CHECK
1021
1022 /* Call stack checking function to check for an overflow condition. */
1023 TCT_Check_Stack();
1024
1025 #endif
1026
1027 #ifdef NU_ENABLE_HISTORY
1028
1029 /* Make an entry that corresponds to this function in the system history
1030 log. */
1031 HIC_Make_History_Entry(NU_TERMINATE_TASK_ID, (UNSIGNED) task,
1032 (UNSIGNED) 0, (UNSIGNED) 0);
1033
1034 #endif
1035
1036 /* Determine if the calling task is the current task. */
1037 if (task == (TC_TCB *) TCD_Current_Thread)
1038 {
1039
1040 /* Protect system data structures. */
1041 TCT_Protect(&TCD_System_Protect);
1042
1043 #ifdef INCLUDE_PROVIEW
1044 _RTProf_DumpTask(task,RT_PROF_TERMINATE_TASK);
1045 #endif /*INCLUDE_PROVIEW*/
1046
1047 /* Suspend the calling task with the NU_TERMINATED status. */
1048 TCC_Suspend_Task(task_ptr, NU_TERMINATED, NU_NULL, NU_NULL,
1049 NU_SUSPEND);
1050
1051 /* No need to un-protect, since control never comes back to this
1052 point and the protection is cleared in TCT_Control_To_System. */
1053 }
1054 else
1055 {
1056
1057 /* Protect scheduling structures. */
1058 TCT_Protect(&TCD_System_Protect);
1059
1060 #ifdef INCLUDE_PROVIEW
1061 _RTProf_DumpTask(task,RT_PROF_TERMINATE_TASK);
1062 #endif /*INCLUDE_PROVIEW*/
1063
1064 /* Keep trying to terminate the specified task until its status
1065 indicates that it is terminated or finished. */
1066 while ((task -> tc_status != NU_FINISHED) &&
1067 task -> tc_status != NU_TERMINATED)
1068 {
1069
1070 /* Is the task in a ready state? */
1071 if (task -> tc_status == NU_READY)
1072 {
1073
1074 /* Terminate the specified task. */
1075 TCC_Suspend_Task(task_ptr, NU_TERMINATED, NU_NULL,
1076 NU_NULL,NU_SUSPEND);
1077
1078 /* Clear system protection. */
1079 TCT_Unprotect();
1080 }
1081 else
1082 {
1083
1084 /* Task is suspended currently. Pickup the suspension
1085 protection. */
1086 suspend_protect = task -> tc_suspend_protect;
1087
1088 /* Save the current status. */
1089 status = task -> tc_status;
1090
1091 /* Release protection on system structures. */
1092 TCT_Unprotect();
1093
1094 /* Determine if there was a suspension protection. If so
1095 protect it first before the scheduling list protection.
1096 This avoids a deadlock situation. */
1097 if (suspend_protect)
1098
1099 /* Protect the terminated task's last suspension
1100 structures. */
1101 TCT_Protect(suspend_protect);
1102
1103 /* Protect the system structures again. */
1104 TCT_Protect(&TCD_System_Protect);
1105
1106 /* Now determine if the same suspension is in force. */
1107 if ((task -> tc_status == status) &&
1108 (task -> tc_suspend_protect == suspend_protect))
1109 {
1110
1111 /* Yes, same suspension is in force. */
1112
1113 /* Call cleanup routine, if there is one. */
1114 if (task -> tc_cleanup)
1115
1116 /* Call cleanup function. */
1117 (*(task -> tc_cleanup)) (task -> tc_cleanup_info);
1118
1119 /* Status the task as terminated. */
1120 task -> tc_status = NU_TERMINATED;
1121
1122 /* Determine if there is a timer active. */
1123 if (task -> tc_timer_active)
1124 {
1125
1126 /* Call the stop timer function. */
1127 TMC_Stop_Task_Timer(&(task -> tc_timer_control));
1128
1129 /* Clear the timer active flag. */
1130 task -> tc_timer_active = NU_FALSE;
1131 }
1132 }
1133
1134 /* Cleanup the protection. */
1135 if (suspend_protect)
1136 {
1137
1138 /* Release specific protection. */
1139 TCT_Unprotect_Specific(suspend_protect);
1140
1141 /* Clear the suspend protect field. */
1142 task -> tc_suspend_protect = NU_NULL;
1143 }
1144
1145 /* Release current protection. */
1146 TCT_Unprotect();
1147 }
1148
1149 /* Protect the scheduling list again. */
1150 TCT_Protect(&TCD_System_Protect);
1151 }
1152
1153 /* Release the protection. */
1154 TCT_Unprotect();
1155 }
1156
1157 /* Return to user mode */
1158 NU_USER_MODE();
1159
1160 /* Return successful completion. */
1161 return(NU_SUCCESS);
1162 }
1163
1164
1165 /*************************************************************************/
1166 /* */
1167 /* FUNCTION */
1168 /* */
1169 /* TCC_Resume_Task */
1170 /* */
1171 /* DESCRIPTION */
1172 /* */
1173 /* This function resumes a previously suspended task. The task */
1174 /* task must currently be suspended for the same reason indicated */
1175 /* by this request. If the task resumed is higher priority than */
1176 /* the calling task and the current task is preemptable, this */
1177 /* function returns a value of NU_TRUE. Otherwise, if no */
1178 /* preemption is required, a NU_FALSE is returned. This routine */
1179 /* must be called from Supervisor mode in a Supervisor/User mode */
1180 /* switching kernel. */
1181 /* */
1182 /* CALLED BY */
1183 /* */
1184 /* Other Components */
1185 /* TCC_Resume_Service Resume service function */
1186 /* */
1187 /* CALLS */
1188 /* */
1189 /* [TCT_Check_Stack] Stack checking function */
1190 /* TCT_Set_Current_Protect Set current protection field */
1191 /* TCT_Set_Execute_Task Set TCD_Execute_Task pointer */
1192 /* TMC_Stop_Task_Timer Stop task timer */
1193 /* */
1194 /* INPUTS */
1195 /* */
1196 /* task_ptr Task control block pointer */
1197 /* suspend_type Type of suspension to lift */
1198 /* */
1199 /* OUTPUTS */
1200 /* */
1201 /* NU_TRUE A higher priority task is */
1202 /* ready to execute */
1203 /* NU_FALSE No change in the task to */
1204 /* execute */
1205 /* */
1206 /* HISTORY */
1207 /* */
1208 /* DATE REMARKS */
1209 /* */
1210 /* 03-01-1993 Created initial version 1.0 */
1211 /* 04-19-1993 Verified version 1.0 */
1212 /* 09-19-1993 Corrected an initialization */
1213 /* problem of de-referencing a */
1214 /* NULL pointer, resulting in */
1215 /* version 1.0d */
1216 /* 09-19-1993 Verified version 1.0d */
1217 /* 03-01-1994 Modified function interface, */
1218 /* added register optimizations, */
1219 /* modified protection logic to */
1220 /* assume that system protection */
1221 /* is already in force, resulting */
1222 /* in version 1.1 */
1223 /* */
1224 /* 03-18-1994 Verified version 1.1 */
1225 /* 10-29-1997 Changed so that tc_cleanup, */
1226 /* tc_cleanup_info, and */
1227 /* tc_suspend_protect are cleared */
1228 /* only if a signal is not active */
1229 /* (SPR115) */
1230 /* 03-20-1998 Corrected SPR455. */
1231 /* */
1232 /*************************************************************************/
1233 STATUS TCC_Resume_Task(NU_TASK *task_ptr, OPTION suspend_type)
1234 {
1235
1236 R1 TC_TCB *task; /* Task control block ptr */
1237 R2 TC_TCB *head; /* Pointer to priority list */
1238 STATUS status = NU_FALSE; /* Status variable */
1239
1240 /* Move task pointer into internal pointer. */
1241 task = (TC_TCB *) task_ptr;
1242
1243
1244 #ifdef NU_ENABLE_STACK_CHECK
1245
1246 /* Call stack checking function to check for an overflow condition. */
1247 TCT_Check_Stack();
1248
1249 #endif
1250
1251
1252 /* Check to see if the task is suspended for the reason that this
1253 resume is attempting to clear. */
1254 if (task -> tc_status == suspend_type)
1255 {
1256
1257 /* Yes, this resume call is valid. */
1258
1259 /* If signals are not active, clear any suspend or cleanup
1260 information (SPR115). */
1261 if (!task -> tc_signal_active)
1262 {
1263 task -> tc_suspend_protect = NU_NULL;
1264 task -> tc_cleanup = NU_NULL;
1265 task -> tc_cleanup_info = NU_NULL;
1266 }
1267
1268 /* Determine if there is a timer active and the task is not being
1269 resumed to handle a signal. */
1270 if ((task -> tc_timer_active) && (!task -> tc_signal_active))
1271 {
1272
1273 /* Call the stop timer function. */
1274 TMC_Stop_Task_Timer(&(task -> tc_timer_control));
1275
1276 /* Clear the timer active flag. */
1277 task -> tc_timer_active = NU_FALSE;
1278 }
1279
1280 /* Check to see if there is a pending pure suspension. If so,
1281 change the cause of the suspension and leave in a suspended
1282 state. */
1283 if (task -> tc_delayed_suspend)
1284 {
1285
1286 /* Leave suspended but change the task's status and clear the
1287 delayed suspension flag. */
1288 task -> tc_delayed_suspend = NU_FALSE;
1289 task -> tc_status = NU_PURE_SUSPEND;
1290 }
1291 else
1292 {
1293
1294 /* Lift the suspension of the specified task. */
1295
1296 /* Clear the status of the task. */
1297 task -> tc_status = NU_READY;
1298
1299 #ifdef INCLUDE_PROVIEW
1300 _RTProf_TaskStatus(task,RT_TASK_READY);
1301 #endif /*INCLUDE_PROVIEW*/
1302
1303 /* Link the task into the appropriate priority list. */
1304 head = *(task -> tc_priority_head);
1305
1306 /* Determine if the list is non-empty. */
1307 if (head)
1308 {
1309
1310 /* Add the new TCB to the end of the ready list. */
1311 task -> tc_ready_previous = head -> tc_ready_previous;
1312 (task -> tc_ready_previous) -> tc_ready_next = task;
1313 task -> tc_ready_next = head;
1314 (task -> tc_ready_next) -> tc_ready_previous = task;
1315
1316 /* Note that the priority bit map does not need to be
1317 modified since there are other active tasks at the
1318 same priority. */
1319 }
1320 else
1321 {
1322
1323 /* Add the new TCB to an empty list. */
1324 task -> tc_ready_previous = task;
1325 task -> tc_ready_next = task;
1326 *(task -> tc_priority_head)= task;
1327
1328 /* Update the priority group bit map to indicate that this
1329 priority now has a task ready. */
1330 TCD_Priority_Groups =
1331 TCD_Priority_Groups | (task -> tc_priority_group);
1332
1333 /* Update the sub-priority bit map to show that this priority
1334 is ready. */
1335 *(task -> tc_sub_priority_ptr) =
1336 (*(task -> tc_sub_priority_ptr)) | task -> tc_sub_priority;
1337
1338 /* Determine if this newly ready task is higher priority
1339 than the current task. */
1340 if ((INT) (task -> tc_priority) < TCD_Highest_Priority)
1341 {
1342
1343 /* Update the highest priority field. */
1344 TCD_Highest_Priority = (INT) task -> tc_priority;
1345
1346 /* See if there is a task to execute. */
1347 if (TCD_Execute_Task == NU_NULL)
1348
1349 /* Make this task the current. */
1350 TCT_Set_Execute_Task(task);
1351
1352 /* Check to see if the task to execute is preemptable. */
1353 /* SPR455 checks if we are in Application_Initialize */
1354 else if ((TCD_Execute_Task -> tc_preemption)
1355 || (INC_Initialize_State == INC_START_INITIALIZE))
1356 {
1357
1358 /* Yes, the task to execute is preemptable. Replace
1359 it with the new task. */
1360 TCT_Set_Execute_Task(task);
1361
1362 /* Now, check and see if the current thread is a task.
1363 If so, return a status that indicates a context
1364 switch is needed. */
1365 if ((TCD_Current_Thread) &&
1366 (((TC_TCB *) TCD_Current_Thread) -> tc_id ==
1367 TC_TASK_ID))
1368
1369 /* Yes, a context switch is needed. */
1370 status = NU_TRUE;
1371 }
1372 }
1373 }
1374 }
1375 }
1376 else
1377 {
1378
1379 /* Check for a resumption of a delayed pure suspend. */
1380 if (suspend_type == NU_PURE_SUSPEND)
1381
1382 /* Clear the delayed suspension. */
1383 task -> tc_delayed_suspend = NU_FALSE;
1384
1385 /* Check for a signal active and the saved status the same as
1386 the resume request. */
1387 if ((suspend_type == task -> tc_saved_status) &&
1388 (task -> tc_signal_active))
1389 {
1390
1391 /* Indicate the saved status as ready. */
1392 task -> tc_saved_status = NU_READY;
1393
1394 /* Determine if the task's timer is active. */
1395 if (task -> tc_timer_active)
1396 {
1397
1398 /* Stop the timer. */
1399 TMC_Stop_Task_Timer(&(task -> tc_timer_control));
1400
1401 /* Clear the timer active flag. */
1402 task -> tc_timer_active = NU_FALSE;
1403 }
1404 }
1405 }
1406
1407 #ifdef INCLUDE_PROVIEW
1408 _RTProf_DumpTask(task,RT_PROF_RESUME_TASK);
1409 #endif /*INCLUDE_PROVIEW*/
1410
1411 /* Return back the status. */
1412 return(status);
1413 }
1414
1415
1416 /*************************************************************************/
1417 /* */
1418 /* FUNCTION */
1419 /* */
1420 /* TCC_Resume_Service */
1421 /* */
1422 /* DESCRIPTION */
1423 /* */
1424 /* This function provides an interface identical to the application */
1425 /* service call to resume a task. */
1426 /* */
1427 /* CALLED BY */
1428 /* */
1429 /* Application */
1430 /* TCCE_Resume_Service Error checking function */
1431 /* */
1432 /* CALLS */
1433 /* */
1434 /* [HIC_Make_History_Entry] Make entry in history log */
1435 /* TCC_Resume_Task Resume a task */
1436 /* [TCT_Check_Stack] Stack checking function */
1437 /* TCT_Control_To_System Transfer control to system */
1438 /* TCT_Protect Protect system structures */
1439 /* TCT_Unprotect Release system protection */
1440 /* */
1441 /* INPUTS */
1442 /* */
1443 /* task_ptr Task control block pointer */
1444 /* */
1445 /* OUTPUTS */
1446 /* */
1447 /* NU_SUCCESS Always returns success */
1448 /* */
1449 /* HISTORY */
1450 /* */
1451 /* DATE REMARKS */
1452 /* */
1453 /* 03-01-1993 Created initial version 1.0 */
1454 /* 04-19-1993 Verified version 1.0 */
1455 /* 03-01-1994 Modified function interface, */
1456 /* added register optimizations, */
1457 /* added system protection logic, */
1458 /* resulting in version 1.1 */
1459 /* */
1460 /* 03-18-1994 Verified version 1.1 */
1461 /* 12-19-1995 Changed the "task" parameter to */
1462 /* "task_ptr" in the */
1463 /* HIC_Make_History_Entry call, */
1464 /* resulting in version 1.1+ */
1465 /* (SPR 36, 64, 66, 77) */
1466 /* 10-02-1998 Another protect problem (1.3a) */
1467 /* */
1468 /*************************************************************************/
1469 STATUS TCC_Resume_Service(NU_TASK *task_ptr)
1470 {
1471
1472 TC_PROTECT *save_protect; /* Save current protection */
1473 NU_SUPERV_USER_VARIABLES
1474
1475 /* Switch to supervisor mode */
1476 NU_SUPERVISOR_MODE();
1477
1478 #ifdef NU_ENABLE_STACK_CHECK
1479
1480 /* Call stack checking function to check for an overflow condition. */
1481 TCT_Check_Stack();
1482
1483 #endif
1484
1485 #ifdef NU_ENABLE_HISTORY
1486
1487 /* Make an entry that corresponds to this function in the system history
1488 log. */
1489 HIC_Make_History_Entry(NU_RESUME_TASK_ID, (UNSIGNED) task_ptr,
1490 (UNSIGNED) 0, (UNSIGNED) 0);
1491
1492 #endif
1493
1494 /* Save current protection. */
1495 if (TCD_Current_Thread != NU_NULL)
1496 {
1497 save_protect = TCT_Get_Current_Protect();
1498 }
1499 else
1500 {
1501 save_protect = NU_NULL;
1502 }
1503
1504 /* Protect system structures. */
1505 TCT_Protect(&TCD_System_Protect);
1506
1507 /* Call the actual resume task function. If the function returns a
1508 NU_TRUE, context switching is needed. */
1509 if (TCC_Resume_Task(task_ptr, NU_PURE_SUSPEND))
1510 {
1511
1512 /* Transfer control back to the system for a context switch. */
1513 TCT_Control_To_System();
1514 }
1515
1516 /* Determine how to get out of protection. */
1517 if (save_protect)
1518 {
1519
1520 /* Restore current protection. */
1521 TCT_Set_Current_Protect(save_protect);
1522
1523 /* Release system protect. */
1524 TCT_Unprotect_Specific(&TCD_System_Protect);
1525 }
1526 else
1527
1528 /* Release protection of system structures. */
1529 TCT_Unprotect();
1530
1531 /* Return to user mode */
1532 NU_USER_MODE();
1533
1534 /* Always return a successful status. */
1535 return(NU_SUCCESS);
1536 }
1537
1538
1539
1540
1541 /*************************************************************************/
1542 /* */
1543 /* FUNCTION */
1544 /* */
1545 /* TCC_Suspend_Task */
1546 /* */
1547 /* DESCRIPTION */
1548 /* */
1549 /* This function suspends the specified task. If the specified */
1550 /* task is the calling task, control is transferred back to the */
1551 /* system. */
1552 /* */
1553 /* CALLED BY */
1554 /* */
1555 /* Other Components */
1556 /* TCC_Suspend_Service Task suspend service */
1557 /* */
1558 /* CALLS */
1559 /* */
1560 /* [HIC_Make_History_Entry] Make entry in history log */
1561 /* TCT_Control_To_System Transfer control to system */
1562 /* TCT_Protect Protect system structures */
1563 /* TCT_Set_Execute_Task Set TCD_Execute_Task pointer */
1564 /* TCT_Protect_Switch Allow protected task to run */
1565 /* briefly */
1566 /* TCT_Unprotect Release system protection */
1567 /* TMC_Start_Task_Timer Start a task timer */
1568 /* */
1569 /* INPUTS */
1570 /* */
1571 /* task_ptr Task control block pointer */
1572 /* suspend_type Type of suspension to lift */
1573 /* cleanup Cleanup routine */
1574 /* information Information for cleanup */
1575 /* timeout Timeout on the suspension */
1576 /* */
1577 /* OUTPUTS */
1578 /* */
1579 /* None */
1580 /* */
1581 /* HISTORY */
1582 /* */
1583 /* DATE REMARKS */
1584 /* */
1585 /* 03-01-1993 Created initial version 1.0 */
1586 /* 04-19-1993 Verified version 1.0 */
1587 /* 02-01-1994 Corrected a suspension with */
1588 /* timeout problem that caused */
1589 /* unconditional task suspension */
1590 /* for timeouts and sleeps for 1 */
1591 /* tick, resulting in version 1.0f */
1592 /* 02-01-1994 Verified version 1.0f */
1593 /* 03-01-1994 Modified function interface, */
1594 /* added register optimizations, */
1595 /* fixed a possible suspending an */
1596 /* executing task from a HISR, */
1597 /* removed excessive protection */
1598 /* logic since protection is now */
1599 /* in force upon function entry, */
1600 /* resulting in version 1.1 */
1601 /* */
1602 /* 03-18-1994 Verified version 1.1 */
1603 /* 06-01-1996 Checked to see whether */
1604 /* task == TCD_Current_Thread */
1605 /* regardless of whether task == */
1606 /* TCD_Execute_Task (SPR152) */
1607 /* */
1608 /*************************************************************************/
1609 VOID TCC_Suspend_Task(NU_TASK *task_ptr, OPTION suspend_type,
1610 VOID (*cleanup) (VOID *), VOID *information, UNSIGNED timeout)
1611 {
1612
1613 R1 TC_TCB *task; /* Task control block ptr */
1614 R2 INT index; /* Working index variable */
1615 DATA_ELEMENT temp; /* Temporary variable */
1616
1617
1618
1619 /* Move input task pointer into internal pointer. */
1620 task = (TC_TCB *) task_ptr;
1621
1622
1623 #ifdef NU_ENABLE_STACK_CHECK
1624
1625 /* Call stack checking function to check for an overflow condition. */
1626 TCT_Check_Stack();
1627
1628 #endif
1629
1630
1631 /* Determine if there is a timeout to initiate. */
1632 if (timeout != NU_SUSPEND)
1633 {
1634
1635 /* Indicate that a task timer is active. */
1636 task -> tc_timer_active = NU_TRUE;
1637
1638 /* Start a timeout on the suspension. */
1639 TMC_Start_Task_Timer(&(task -> tc_timer_control),timeout);
1640 }
1641
1642
1643 /* Check for a non self-suspension. In such cases, the target task
1644 cannot have any type of protection in force. */
1645 if (task != (TC_TCB *) TCD_Current_Thread)
1646 {
1647
1648 do
1649 {
1650
1651 /* Check for protection. Remember that system protection is
1652 in effect. */
1653 if (task -> tc_current_protect)
1654 {
1655
1656 /* Yes, target task is in a protected mode. Release
1657 the protection on the scheduling list and transfer
1658 control briefly to the target task. */
1659 TCT_Unprotect();
1660
1661 /* Switch to the protected task and wait until the
1662 task is not protected. */
1663 TCT_Protect_Switch(task);
1664
1665 /* Restore protection of the system structures. */
1666 TCT_Protect(&TCD_System_Protect);
1667 }
1668 } while (task -> tc_current_protect);
1669 }
1670
1671 /* Check to see if the task is currently ready. */
1672 if (task -> tc_status == NU_READY)
1673 {
1674
1675 /* Mark the task with the appropriate suspension code. */
1676 task -> tc_status = suspend_type;
1677
1678 /* Store off termination information in the tasks control block. */
1679 task -> tc_cleanup = cleanup;
1680 task -> tc_cleanup_info = information;
1681
1682 /* Remove the task from the ready list. */
1683
1684 /* Determine if the task is the only one on the list. */
1685 if (task -> tc_ready_next == task)
1686 {
1687
1688 /* Only task on the list. Clear the task's pointers and
1689 clear the entry in the priority table. */
1690 task -> tc_ready_next = NU_NULL;
1691 task -> tc_ready_previous = NU_NULL;
1692 *(task -> tc_priority_head) = NU_NULL;
1693
1694 /* Clear the sub-priority group. */
1695 *(task -> tc_sub_priority_ptr) =
1696 (*(task -> tc_sub_priority_ptr)) & ~(task -> tc_sub_priority);
1697
1698 /* Determine if the main priority group needs to be cleared.
1699 This is only true if there are no other bits set in this
1700 sub-priority. */
1701 if (*(task -> tc_sub_priority_ptr) == 0)
1702
1703 /* Clear the main priority group bit. */
1704 TCD_Priority_Groups =
1705 TCD_Priority_Groups & ~(task -> tc_priority_group);
1706
1707 /* Determine if this priority group was the highest in the
1708 system. */
1709 if (task -> tc_priority == (DATA_ELEMENT) TCD_Highest_Priority)
1710 {
1711
1712 /* Determine the highest priority task in the system. */
1713 if (TCD_Priority_Groups == 0)
1714 {
1715
1716 /* Re-initialize the highest priority variable and
1717 clear the current task pointer. */
1718 TCD_Highest_Priority = TC_PRIORITIES;
1719 }
1720 else
1721 {
1722
1723 /* Find the next highest priority task. */
1724 if (TCD_Priority_Groups & TC_HIGHEST_MASK)
1725
1726 /* Base of sub-group is 0. */
1727 index = 0;
1728
1729 else if (TCD_Priority_Groups & TC_NEXT_HIGHEST_MASK)
1730
1731 /* Base of sub-group is 8. */
1732 index = 8;
1733
1734 else if (TCD_Priority_Groups & TC_NEXT_LOWEST_MASK)
1735
1736 /* Base of sub-group is 16. */
1737 index = 16;
1738 else
1739
1740 /* Base of sub-group is 24. */
1741 index = 24;
1742
1743 /* Calculate the highest available priority. */
1744 index = index + TCD_Lowest_Set_Bit[(INT)
1745 ((TCD_Priority_Groups >> index) & TC_HIGHEST_MASK)];
1746
1747 /* Get the mask of the priority within the group of
1748 8 priorities. */
1749 temp = TCD_Sub_Priority_Groups[index];
1750
1751 /* Calculate the actual priority. */
1752 TCD_Highest_Priority =
1753 (index << 3) + TCD_Lowest_Set_Bit[temp];
1754 }
1755 }
1756 }
1757 else
1758 {
1759
1760 /* Not the only task ready at the same priority level. */
1761
1762 /* Remove from the linked-list. */
1763 (task -> tc_ready_previous) -> tc_ready_next =
1764 task -> tc_ready_next;
1765 (task -> tc_ready_next) -> tc_ready_previous =
1766 task -> tc_ready_previous;
1767
1768 /* See if the task being suspended is the current. */
1769 if (*(task -> tc_priority_head) == task)
1770
1771 /* Update the head of this priority list. */
1772 *(task -> tc_priority_head) = task -> tc_ready_next;
1773
1774 /* Clear the task's pointers. */
1775 task -> tc_ready_next = NU_NULL;
1776 task -> tc_ready_previous = NU_NULL;
1777 }
1778
1779 /* Determine if this task the highest priority task. */
1780 if (task == TCD_Execute_Task)
1781 {
1782
1783 /* Determine the next task to execute. */
1784 if (TCD_Highest_Priority < TC_PRIORITIES)
1785
1786 /* Put the next task to execute in TCD_Execute_Task. */
1787 TCT_Set_Execute_Task(TCD_Priority_List[TCD_Highest_Priority]);
1788 else
1789
1790 /* No other task is ready for execution. */
1791 TCT_Set_Execute_Task(NU_NULL);
1792 }
1793
1794 #ifdef INCLUDE_PROVIEW
1795 _RTProf_DumpTask(task,RT_PROF_SUSPEND_TASK);
1796
1797 if (suspend_type == NU_SLEEP_SUSPEND)
1798 {
1799 _RTProf_TaskStatus(task,RT_TASK_SLEEPING);
1800 }
1801 else if (suspend_type == NU_PURE_SUSPEND)
1802 {
1803 _RTProf_TaskStatus(task,RT_TASK_SUSPENDED);
1804 }
1805 else
1806 {
1807 _RTProf_TaskStatus(task,RT_TASK_WAITING);
1808 }
1809 #endif /*INCLUDE_PROVIEW*/
1810
1811 /* See if the suspending task is the current thread. (SPR152) */
1812 if (task == (TC_TCB *) TCD_Current_Thread)
1813
1814 /* Leave the task, transfer control to the system. */
1815 TCT_Control_To_System();
1816
1817 }
1818 else
1819 {
1820
1821 /* Check for a pure suspension request. If present, the delayed
1822 suspension flag is set. */
1823 if (suspend_type == NU_PURE_SUSPEND)
1824
1825 /* Setup the delayed suspension flag. */
1826 task -> tc_delayed_suspend = NU_TRUE;
1827 #ifdef INCLUDE_PROVIEW
1828 _RTProf_DumpTask(task,RT_PROF_SUSPEND_TASK);
1829 #endif /*INCLUDE_PROVIEW*/
1830
1831 }
1832 }
1833
1834
1835 /*************************************************************************/
1836 /* */
1837 /* FUNCTION */
1838 /* */
1839 /* TCC_Suspend_Service */
1840 /* */
1841 /* DESCRIPTION */
1842 /* */
1843 /* This function provides a suitable interface to the actual */
1844 /* service to suspend a task. */
1845 /* */
1846 /* CALLED BY */
1847 /* */
1848 /* Application */
1849 /* TCCE_Suspend_Service Error checking function */
1850 /* */
1851 /* CALLS */
1852 /* */
1853 /* [HIC_Make_History_Entry] Make entry in history log */
1854 /* TCC_Suspend_Task Suspend a task */
1855 /* [TCT_Check_Stack] Stack checking function */
1856 /* TCT_Protect Protect system structures */
1857 /* TCT_Unprotect Release system structures */
1858 /* */
1859 /* INPUTS */
1860 /* */
1861 /* task_ptr Task control block pointer */
1862 /* */
1863 /* OUTPUTS */
1864 /* */
1865 /* NU_SUCCESS Always a successful status */
1866 /* */
1867 /* HISTORY */
1868 /* */
1869 /* DATE REMARKS */
1870 /* */
1871 /* 03-01-1993 Created initial version 1.0 */
1872 /* 04-19-1993 Verified version 1.0 */
1873 /* 03-01-1994 Modified function interface, */
1874 /* added register optimizations, */
1875 /* added system protection logic, */
1876 /* resulting in version 1.1 */
1877 /* */
1878 /* 03-18-1994 Verified version 1.1 */
1879 /* */
1880 /*************************************************************************/
1881 STATUS TCC_Suspend_Service(NU_TASK *task_ptr)
1882 {
1883
1884 NU_SUPERV_USER_VARIABLES
1885
1886 /* Switch to supervisor mode */
1887 NU_SUPERVISOR_MODE();
1888
1889 #ifdef NU_ENABLE_STACK_CHECK
1890
1891 /* Call stack checking function to check for an overflow condition. */
1892 TCT_Check_Stack();
1893
1894 #endif
1895
1896 #ifdef NU_ENABLE_HISTORY
1897
1898 /* Make an entry that corresponds to this function in the system history
1899 log. */
1900 HIC_Make_History_Entry(NU_SUSPEND_TASK_ID, (UNSIGNED) task_ptr,
1901 (UNSIGNED) 0, (UNSIGNED) 0);
1902
1903 #endif
1904
1905
1906 /* Protect system data structures. */
1907 TCT_Protect(&TCD_System_Protect);
1908
1909 /* Call the actual routine to suspend the task. */
1910 TCC_Suspend_Task(task_ptr, NU_PURE_SUSPEND, NU_NULL, NU_NULL, NU_SUSPEND);
1911
1912 /* Release system protection. */
1913 TCT_Unprotect();
1914
1915 /* Return to user mode */
1916 NU_USER_MODE();
1917
1918 /* Always return a successful status. */
1919 return(NU_SUCCESS);
1920 }
1921
1922
1923 /*************************************************************************/
1924 /* */
1925 /* FUNCTION */
1926 /* */
1927 /* TCC_Task_Timeout */
1928 /* */
1929 /* DESCRIPTION */
1930 /* */
1931 /* This function processes task suspension timeout conditions. */
1932 /* Note that task sleep requests are also considered a timeout */
1933 /* condition. This routine must be called from Supervisor mode in */
1934 /* a Supervisor/User mode switching kernel. */
1935 /* */
1936 /* CALLED BY */
1937 /* */
1938 /* TMC_Timer_Task Timer expiration task */
1939 /* */
1940 /* CALLS */
1941 /* */
1942 /* Caller's cleanup function */
1943 /* TCC_Resume_Task Resume a suspended task */
1944 /* [TCT_Check_Stack] Stack checking function */
1945 /* TCT_Protect Protect scheduling list */
1946 /* TCT_Set_Current_Protect Setup current protection */
1947 /* TCT_Unprotect Release protection */
1948 /* TCT_Unprotect_Specific Release specific protection */
1949 /* */
1950 /* INPUTS */
1951 /* */
1952 /* task_ptr Task control block pointer */
1953 /* */
1954 /* OUTPUTS */
1955 /* */
1956 /* None */
1957 /* */
1958 /* HISTORY */
1959 /* */
1960 /* DATE REMARKS */
1961 /* */
1962 /* 03-01-1993 Created initial version 1.0 */
1963 /* 04-19-1993 Verified version 1.0 */
1964 /* 02-01-1994 Added logic to clear the timer */
1965 /* active flag when the target */
1966 /* task is already in a ready */
1967 /* state, resulting in */
1968 /* version 1.0f */
1969 /* 02-01-1994 Verified version 1.0f */
1970 /* 03-01-1994 Modified function interface, */
1971 /* added register optimizations, */
1972 /* removed logic for timeout */
1973 /* before suspension because new */
1974 /* protection logic eliminates */
1975 /* the possibility, */
1976 /* resulting in version 1.1 */
1977 /* */
1978 /* 03-18-1994 Verified version 1.1 */
1979 /* */
1980 /*************************************************************************/
1981 VOID TCC_Task_Timeout(NU_TASK *task_ptr)
1982 {
1983
1984 R1 TC_TCB *task; /* Task control block ptr */
1985 TC_PROTECT *suspend_protect; /* Suspension protect ptr */
1986 DATA_ELEMENT task_status; /* Task status variable */
1987
1988
1989
1990 /* Move task control block pointer into internal pointer. */
1991 task = (TC_TCB *) task_ptr;
1992
1993
1994 #ifdef NU_ENABLE_STACK_CHECK
1995
1996 /* Call stack checking function to check for an overflow condition. */
1997 TCT_Check_Stack();
1998
1999 #endif
2000
2001 /* Protect system data structures. */
2002 TCT_Protect(&TCD_System_Protect);
2003
2004 /* Pickup the suspension protection saved-off when the task was
2005 suspended. */
2006 suspend_protect = task -> tc_suspend_protect;
2007
2008 /* Is a signal handler currently running? */
2009 if (task -> tc_signal_active)
2010
2011 /* Use the saved status for current task status */
2012 task_status = task -> tc_saved_status;
2013 else
2014
2015 /* Just use the current task status */
2016 task_status = task -> tc_status;
2017
2018 /* Release protection of the scheduling list. */
2019 TCT_Unprotect();
2020
2021 /* Determine if there is a suspend protect. */
2022 if (suspend_protect)
2023
2024 /* Protect the suspended protection. */
2025 TCT_Protect(suspend_protect);
2026
2027 /* Now protect the system structures again. Note that the order the
2028 protections are made prevents deadlocks. */
2029 TCT_Protect(&TCD_System_Protect);
2030
2031 /* Determine if the task is still suspended in the same manner. */
2032 if ((task -> tc_status == task_status) ||
2033 ((task -> tc_signal_active) && (task -> tc_saved_status == task_status)))
2034 {
2035
2036 /* Make sure that this timeout processing is still valid. */
2037 if ((task -> tc_timer_active) &&
2038 (task -> tc_timer_control.tm_remaining_time == 0))
2039 {
2040
2041 /* Clear the timer active flag. */
2042 task -> tc_timer_active = NU_FALSE;
2043
2044 /* Call the cleanup function, if there is one. */
2045 if (task -> tc_cleanup)
2046
2047 /* Call cleanup function. */
2048 (*(task -> tc_cleanup)) (task -> tc_cleanup_info);
2049
2050 /* Resume the task. */
2051 TCC_Resume_Task(task_ptr, task_status);
2052 }
2053 }
2054
2055 /* Determine if a suspend protection was in force. */
2056 if (suspend_protect)
2057 {
2058
2059 /* Set the current protection to the suspend protect. */
2060 TCT_Set_Current_Protect(suspend_protect);
2061 TCT_Unprotect_Specific(&TCD_System_Protect);
2062 }
2063
2064 /* Release current protection. */
2065 TCT_Unprotect();
2066 }
2067
2068
2069 /*************************************************************************/
2070 /* */
2071 /* FUNCTION */
2072 /* */
2073 /* TCC_Task_Sleep */
2074 /* */
2075 /* DESCRIPTION */
2076 /* */
2077 /* This function provides task sleep suspensions. Its primary */
2078 /* purpose is to interface with the actual task suspension function.*/
2079 /* */
2080 /* CALLED BY */
2081 /* */
2082 /* Application */
2083 /* */
2084 /* CALLS */
2085 /* */
2086 /* [HIC_Make_History_Entry] Make entry in history log */
2087 /* TCC_Suspend_Task Suspend a task */
2088 /* [TCT_Check_Stack] Stack checking function */
2089 /* TCT_Protect Protect system structures */
2090 /* TCT_Unprotect Release system structures */
2091 /* */
2092 /* INPUTS */
2093 /* */
2094 /* ticks Number of timer ticks */
2095 /* */
2096 /* OUTPUTS */
2097 /* */
2098 /* None */
2099 /* */
2100 /* HISTORY */
2101 /* */
2102 /* DATE REMARKS */
2103 /* */
2104 /* 03-01-1993 Created initial version 1.0 */
2105 /* 04-19-1993 Verified version 1.0 */
2106 /* 03-01-1994 Modified call to suspend the */
2107 /* calling task, resulting in */
2108 /* version 1.1 */
2109 /* */
2110 /* 03-18-1994 Verified version 1.1 */
2111 /* */
2112 /*************************************************************************/
2113 VOID TCC_Task_Sleep(UNSIGNED ticks)
2114 {
2115
2116 NU_SUPERV_USER_VARIABLES
2117
2118 /* Switch to supervisor mode */
2119 NU_SUPERVISOR_MODE();
2120
2121 #ifdef NU_ENABLE_STACK_CHECK
2122
2123 /* Call stack checking function to check for an overflow condition. */
2124 TCT_Check_Stack();
2125
2126 #endif
2127
2128 #ifdef NU_ENABLE_HISTORY
2129
2130 /* Make an entry that corresponds to this function in the system history
2131 log. */
2132 HIC_Make_History_Entry(NU_SLEEP_ID, (UNSIGNED) ticks,
2133 (UNSIGNED) 0, (UNSIGNED) 0);
2134
2135 #endif
2136
2137
2138 /* Protect system data structures. */
2139 TCT_Protect(&TCD_System_Protect);
2140
2141 #ifdef INCLUDE_PROVIEW
2142 _RTProf_DumpTask((TC_TCB *)TCD_Current_Thread,RT_PROF_SLEEP);
2143 #endif /*INCLUDE_PROVIEW*/
2144
2145 /* Call the actual routine to suspend the task. */
2146 TCC_Suspend_Task((NU_TASK *) TCD_Current_Thread, NU_SLEEP_SUSPEND,
2147 NU_NULL, NU_NULL, ticks);
2148
2149 /* Release system protection. */
2150 TCT_Unprotect();
2151
2152 /* Return to user mode */
2153 NU_USER_MODE();
2154 }
2155
2156
2157 /*************************************************************************/
2158 /* */
2159 /* FUNCTION */
2160 /* */
2161 /* TCC_Relinquish */
2162 /* */
2163 /* DESCRIPTION */
2164 /* */
2165 /* This function moves the calling task to the end of other tasks */
2166 /* at the same priority level. The calling task does not execute */
2167 /* again until all the other tasks of the same priority get a */
2168 /* chance to execute. */
2169 /* */
2170 /* CALLED BY */
2171 /* */
2172 /* Application */
2173 /* TCCE_Relinquish Error checking shell */
2174 /* */
2175 /* CALLS */
2176 /* */
2177 /* [HIC_Make_History_Entry] Make entry in history log */
2178 /* [TCT_Check_Stack] Stack checking function */
2179 /* TCT_Control_To_System Transfer control to system */
2180 /* TCT_Protect Protect system structures */
2181 /* TCT_Set_Execute_Task Set TCD_Execute_Task pointer */
2182 /* TCT_Unprotect Release protection */
2183 /* */
2184 /* INPUTS */
2185 /* */
2186 /* None */
2187 /* */
2188 /* OUTPUTS */
2189 /* */
2190 /* None */
2191 /* */
2192 /* HISTORY */
2193 /* */
2194 /* DATE REMARKS */
2195 /* */
2196 /* 03-01-1993 Created initial version 1.0 */
2197 /* 04-19-1993 Verified version 1.0 */
2198 /* 03-01-1994 Modified protection logic, */
2199 /* resulting in version 1.1 */
2200 /* */
2201 /* 03-18-1994 Verified version 1.1 */
2202 /* */
2203 /*************************************************************************/
2204 VOID TCC_Relinquish(VOID)
2205 {
2206
2207 TC_TCB *task; /* Pointer to task */
2208 NU_SUPERV_USER_VARIABLES
2209
2210 /* Switch to supervisor mode */
2211 NU_SUPERVISOR_MODE();
2212
2213 #ifdef NU_ENABLE_STACK_CHECK
2214
2215 /* Call stack checking function to check for an overflow condition. */
2216 TCT_Check_Stack();
2217
2218 #endif
2219
2220 #ifdef NU_ENABLE_HISTORY
2221
2222 /* Make an entry that corresponds to this function in the system history
2223 log. */
2224 HIC_Make_History_Entry(NU_RELINQUISH_ID, (UNSIGNED) 0,
2225 (UNSIGNED) 0, (UNSIGNED) 0);
2226
2227 #endif
2228
2229 /* Protect against multiple access to the system structures. */
2230 TCT_Protect(&TCD_System_Protect);
2231
2232 /* Pickup the current thread and place it in the task pointer. */
2233 task = (TC_TCB *) TCD_Current_Thread;
2234
2235 #ifdef INCLUDE_PROVIEW
2236 _RTProf_DumpTask(task,RT_PROF_RELINQUISH);
2237 #endif /*INCLUDE_PROVIEW*/
2238
2239 /* Determine if another task is ready to run. */
2240 if ((task -> tc_ready_next != task) ||
2241 (task -> tc_priority != (DATA_ELEMENT) TCD_Highest_Priority))
2242 {
2243
2244 /* Move the executing task to the end of tasks having the same
2245 priority. */
2246 *(task -> tc_priority_head) = task -> tc_ready_next;
2247
2248 /* Setup the next task to execute. */
2249 TCT_Set_Execute_Task(TCD_Priority_List[TCD_Highest_Priority]);
2250
2251 /* Transfer control back to the system. */
2252 TCT_Control_To_System();
2253 }
2254
2255 /* Release protection of system structures. */
2256 TCT_Unprotect();
2257
2258 /* Return to user mode */
2259 NU_USER_MODE();
2260 }
2261
2262
2263 /*************************************************************************/
2264 /* */
2265 /* FUNCTION */
2266 /* */
2267 /* TCC_Time_Slice */
2268 /* */
2269 /* DESCRIPTION */
2270 /* */
2271 /* This function moves the specified task to the end of the other */
2272 /* tasks at the same priority level. If the specified task is no */
2273 /* longer ready, this request is ignored. This routine must be */
2274 /* called from Supervisor mode in a Supervisor/User mode */
2275 /* switching kernel. */
2276 /* */
2277 /* CALLED BY */
2278 /* */
2279 /* TMC_Timer_HISR Time-slice interrupt */
2280 /* */
2281 /* CALLS */
2282 /* */
2283 /* [TCT_Check_Stack] Stack checking function */
2284 /* TCT_Protect Protect the scheduling data */
2285 /* TCT_Set_Execute_Task Set TCD_Execute_Task pointer */
2286 /* TCT_Unprotect Release protection */
2287 /* */
2288 /* INPUTS */
2289 /* */
2290 /* task Task control block pointer */
2291 /* */
2292 /* OUTPUTS */
2293 /* */
2294 /* None */
2295 /* */
2296 /* HISTORY */
2297 /* */
2298 /* DATE REMARKS */
2299 /* */
2300 /* 03-01-1993 Created initial version 1.0 */
2301 /* 04-19-1993 Verified version 1.0 */
2302 /* 03-01-1994 Modified function interface, */
2303 /* added register optimizations, */
2304 /* slightly modified protection */
2305 /* logic, resulting in version 1.1 */
2306 /* */
2307 /* 03-18-1994 Verified version 1.1 */
2308 /* */
2309 /*************************************************************************/
2310 VOID TCC_Time_Slice(NU_TASK *task_ptr)
2311 {
2312
2313 R1 TC_TCB *task; /* Task control block ptr */
2314
2315
2316 /* Move input task control block pointer into internal pointer. */
2317 task = (TC_TCB *) task_ptr;
2318
2319
2320 #ifdef NU_ENABLE_STACK_CHECK
2321
2322 /* Call stack checking function to check for an overflow condition. */
2323 TCT_Check_Stack();
2324
2325 #endif
2326
2327 /* Protect against multiple access to the system structures. */
2328 TCT_Protect(&TCD_System_Protect);
2329
2330 /* Determine if another task is ready to run. */
2331 if (((task -> tc_status == NU_READY) && (task -> tc_preemption)) &&
2332 ((task -> tc_ready_next != task) ||
2333 (task -> tc_priority != (DATA_ELEMENT) TCD_Highest_Priority)))
2334 {
2335
2336 /* Move the executing task to the end of tasks having the same
2337 priority. */
2338 *(task -> tc_priority_head) = task -> tc_ready_next;
2339
2340 /* Setup the next task to execute. */
2341 TCT_Set_Execute_Task(TCD_Priority_List[TCD_Highest_Priority]);
2342
2343 }
2344
2345 /* Release protection of the system structures. */
2346 TCT_Unprotect();
2347 }
2348
2349
2350 /*************************************************************************/
2351 /* */
2352 /* FUNCTION */
2353 /* */
2354 /* TCC_Current_Task_Pointer */
2355 /* */
2356 /* DESCRIPTION */
2357 /* */
2358 /* This function returns the pointer of the currently executing */
2359 /* task. If the current thread is not a task thread, a NU_NULL */
2360 /* is returned. */
2361 /* */
2362 /* CALLED BY */
2363 /* */
2364 /* Application */
2365 /* Other Components */
2366 /* */
2367 /* CALLS */
2368 /* */
2369 /* None */
2370 /* */
2371 /* INPUTS */
2372 /* */
2373 /* None */
2374 /* */
2375 /* OUTPUTS */
2376 /* */
2377 /* Task Pointer Active tasks pointer or */
2378 /* NU_NULL if not a task */
2379 /* */
2380 /* HISTORY */
2381 /* */
2382 /* DATE REMARKS */
2383 /* */
2384 /* 03-01-1993 Created initial version 1.0 */
2385 /* 04-19-1993 Verified version 1.0 */
2386 /* 03-01-1994 Modified function interface, */
2387 /* resulting in version 1.1 */
2388 /* */
2389 /* 03-18-1994 Verified version 1.1 */
2390 /* */
2391 /*************************************************************************/
2392 NU_TASK *TCC_Current_Task_Pointer(VOID)
2393 {
2394
2395
2396 /* Determine if a task thread is executing. */
2397 if ((TCD_Current_Thread) &&
2398 (((TC_TCB *) TCD_Current_Thread) -> tc_id == TC_TASK_ID))
2399
2400 /* Task thread is running, return the pointer. */
2401 return((NU_TASK *) TCD_Current_Thread);
2402 else
2403
2404 /* No, task thread is not running, return a NU_NULL. */
2405 return(NU_NULL);
2406 }
2407
2408
2409 /*************************************************************************/
2410 /* */
2411 /* FUNCTION */
2412 /* */
2413 /* TCC_Current_HISR_Pointer */
2414 /* */
2415 /* DESCRIPTION */
2416 /* */
2417 /* This function returns the pointer of the currently executing */
2418 /* HISR. If the current thread is not a HISR thread, a NU_NULL */
2419 /* is returned. */
2420 /* */
2421 /* CALLED BY */
2422 /* */
2423 /* Application */
2424 /* Other Components */
2425 /* */
2426 /* CALLS */
2427 /* */
2428 /* None */
2429 /* */
2430 /* INPUTS */
2431 /* */
2432 /* None */
2433 /* */
2434 /* OUTPUTS */
2435 /* */
2436 /* HISR Pointer Active HISR pointer or */
2437 /* NU_NULL if not a HISR */
2438 /* */
2439 /* HISTORY */
2440 /* */
2441 /* DATE REMARKS */
2442 /* */
2443 /* 03-01-1993 Created initial version 1.0 */
2444 /* 04-19-1993 Verified version 1.0 */
2445 /* 03-01-1994 Modified function interface, */
2446 /* resulting in version 1.1 */
2447 /* */
2448 /* 03-18-1994 Verified version 1.1 */
2449 /* */
2450 /*************************************************************************/
2451 NU_HISR *TCC_Current_HISR_Pointer(VOID)
2452 {
2453
2454
2455 /* Determine if a HISR thread is executing. */
2456 if ((TCD_Current_Thread) &&
2457 (((TC_HCB *) TCD_Current_Thread) -> tc_id == TC_HISR_ID))
2458
2459 /* HISR thread is running, return the pointer. */
2460 return((NU_HISR *) TCD_Current_Thread);
2461 else
2462
2463 /* No, HISR thread is not running, return a NU_NULL. */
2464 return(NU_NULL);
2465 }
2466
2467
2468 /*************************************************************************/
2469 /* */
2470 /* FUNCTION */
2471 /* */
2472 /* TCC_Task_Shell */
2473 /* */
2474 /* DESCRIPTION */
2475 /* */
2476 /* This function is shell from which all application tasks are */
2477 /* initially executed. The shell causes the task to finish when */
2478 /* control is returned from the application task. Also, the shell */
2479 /* passes argc and argv arguments to the task's entry function. */
2480 /* */
2481 /* CALLED BY */
2482 /* */
2483 /* TCC_Control_To_Task Control to task routine */
2484 /* */
2485 /* CALLS */
2486 /* */
2487 /* Task Entry Function */
2488 /* TCC_Suspend_Task Suspend task when finished */
2489 /* TCT_Protect Protect system structures */
2490 /* */
2491 /* INPUTS */
2492 /* */
2493 /* None */
2494 /* */
2495 /* OUTPUTS */
2496 /* */
2497 /* None */
2498 /* */
2499 /* HISTORY */
2500 /* */
2501 /* DATE REMARKS */
2502 /* */
2503 /* 03-01-1993 Created initial version 1.0 */
2504 /* 04-19-1993 Verified version 1.0 */
2505 /* 03-01-1994 Added protection logic prior to */
2506 /* suspending the task, resulting */
2507 /* in version 1.1 */
2508 /* */
2509 /* 03-18-1994 Verified version 1.1 */
2510 /* */
2511 /*************************************************************************/
2512 VOID TCC_Task_Shell(VOID)
2513 {
2514 NU_SUPERV_USER_VARIABLES
2515
2516 /* Call the task's entry function with the argc and argv parameters
2517 supplied during task creation or reset. */
2518 (*(TCD_Execute_Task -> tc_entry)) (TCD_Execute_Task -> tc_argc,
2519 TCD_Execute_Task -> tc_argv);
2520
2521 /* Switch to supervisor mode */
2522 NU_SUPERVISOR_MODE();
2523
2524 /* Protect system data structures. */
2525 TCT_Protect(&TCD_System_Protect);
2526
2527 /* If the task returns, suspend it in a finished state. Note that
2528 the task cannot execute again until it is reset. Therefore, this
2529 call never returns. */
2530 TCC_Suspend_Task((NU_TASK *) TCD_Execute_Task, NU_FINISHED,
2531 NU_NULL, NU_NULL, NU_SUSPEND);
2532
2533 /* Return to user mode */
2534 NU_USER_MODE();
2535 }
2536
2537
2538 /*************************************************************************/
2539 /* */
2540 /* FUNCTION */
2541 /* */
2542 /* TCC_Signal_Shell */
2543 /* */
2544 /* DESCRIPTION */
2545 /* */
2546 /* This function processes signals by calling the task supplied */
2547 /* signal handling function. When signal handling is completed, */
2548 /* the task is placed in the appropriate state. */
2549 /* */
2550 /* CALLED BY */
2551 /* */
2552 /* TCC_Control_Signals Control task's signals */
2553 /* TCC_Register_Signal_Handler Register a signal handler */
2554 /* */
2555 /* CALLS */
2556 /* */
2557 /* task's signal handling routine */
2558 /* [TCT_Check_Stack] Stack checking function */
2559 /* TCT_Signal_Exit Signal handling exit routine */
2560 /* TCT_Protect Protect against other access */
2561 /* TCT_Set_Execute_Task Set TCD_Execute_Task pointer */
2562 /* TCT_Unprotect Release protection */
2563 /* */
2564 /* INPUTS */
2565 /* */
2566 /* None */
2567 /* */
2568 /* OUTPUTS */
2569 /* */
2570 /* None */
2571 /* */
2572 /* HISTORY */
2573 /* */
2574 /* DATE REMARKS */
2575 /* */
2576 /* 03-01-1993 Created initial version 1.0 */
2577 /* 04-19-1993 Verified version 1.0 */
2578 /* 03-01-1994 Added register optimizations, */
2579 /* modified protection logic, */
2580 /* resulting in version 1.1 */
2581 /* */
2582 /* 03-18-1994 Verified version 1.1 */
2583 /* */
2584 /*************************************************************************/
2585 VOID TCC_Signal_Shell(VOID)
2586 {
2587
2588 R2 UNSIGNED signals; /* Signals to send to task */
2589 INT index; /* Working index variable */
2590 DATA_ELEMENT temp; /* Temporary variable */
2591 R1 TC_TCB *task; /* Task pointer */
2592
2593
2594 #ifdef NU_ENABLE_STACK_CHECK
2595
2596 /* Call stack checking function to check for an overflow condition. */
2597 TCT_Check_Stack();
2598
2599 #endif
2600
2601 /* Point at the current task. */
2602 task = (TC_TCB *) TCD_Current_Thread;
2603
2604 /* Protect against simultaneous access. */
2605 TCT_Protect(&TCD_System_Protect);
2606
2607 /* Process while there are signals to handle. */
2608 while (task -> tc_signals & task -> tc_enabled_signals)
2609 {
2610
2611 /* Pickup the signals and clear them. */
2612 signals = task -> tc_signals;
2613 task -> tc_signals = 0;
2614
2615 /* Release protection. */
2616 TCT_Unprotect();
2617
2618 /* Call the application signal handling function, if there still is
2619 one. */
2620 if (task -> tc_signal_handler)
2621 {
2622 NU_SUPERV_USER_VARIABLES
2623
2624 #if (defined(NU_SUPERV_USER_MODE)) && (NU_SUPERV_USER_MODE > 0)
2625 UNSIGNED savedMode = task->tc_su_mode;
2626 task->tc_su_mode = 1; /* Force transition to User mode */
2627 #endif
2628 /* Switch to user mode */
2629 NU_USER_MODE();
2630
2631 /* Call signal handler. (always in User mode) */
2632 (*(task -> tc_signal_handler))(signals);
2633
2634 /* Return to supervisor mode */
2635 NU_SUPERVISOR_MODE();
2636
2637 #if (defined(NU_SUPERV_USER_MODE)) && (NU_SUPERV_USER_MODE > 0)
2638 task->tc_su_mode = savedMode; /* Restore original nesting count */
2639 #endif
2640 }
2641
2642 /* Protect against simultaneous access again. */
2643 TCT_Protect(&TCD_System_Protect);
2644 }
2645
2646 /* At this point, signals have been exhausted and protection is in
2647 force. */
2648
2649 /* Clear the signal in process flag. */
2650 task -> tc_signal_active = NU_FALSE;
2651
2652 /* Determine how the signal handler was called. Either in a solicited or
2653 an unsolicited manner. */
2654 if (task -> tc_saved_stack_ptr)
2655 {
2656
2657 /* Determine if the saved status still indicates that the task should
2658 be suspended. */
2659 if (task -> tc_saved_status != NU_READY)
2660 {
2661
2662 /* Suspend the task. */
2663 task -> tc_status = task -> tc_saved_status;
2664
2665 /* Remove the task from the ready list. */
2666
2667 /* Determine if the task is the only one on the list. */
2668 if (task -> tc_ready_next == task)
2669 {
2670
2671 /* Only task on the list. Clear the task's pointers and
2672 clear the entry in the priority table. */
2673 task -> tc_ready_next = NU_NULL;
2674 task -> tc_ready_previous = NU_NULL;
2675 *(task -> tc_priority_head) = NU_NULL;
2676
2677 /* Clear the sub-priority group. */
2678 *(task -> tc_sub_priority_ptr) =
2679 (*(task -> tc_sub_priority_ptr)) & ~(task -> tc_sub_priority);
2680
2681 /* Determine if the main priority group needs to be cleared.
2682 This is only true if there are no other bits set in this
2683 sub-priority. */
2684 if (*(task -> tc_sub_priority_ptr) == 0)
2685
2686 /* Clear the main priority group bit. */
2687 TCD_Priority_Groups =
2688 TCD_Priority_Groups & ~(task -> tc_priority_group);
2689
2690 /* Determine if this priority group was the highest in the
2691 system. */
2692 if (task -> tc_priority == (DATA_ELEMENT) TCD_Highest_Priority)
2693 {
2694
2695 /* Determine the highest priority task in the system. */
2696 if (TCD_Priority_Groups == 0)
2697 {
2698
2699 /* Re-initialize the highest priority variable and
2700 clear the current task pointer. */
2701 TCD_Highest_Priority = TC_PRIORITIES;
2702 }
2703 else
2704 {
2705
2706 /* Find the next highest priority task. */
2707 if (TCD_Priority_Groups & TC_HIGHEST_MASK)
2708
2709 /* Base of sub-group is 0. */
2710 index = 0;
2711
2712 else if (TCD_Priority_Groups & TC_NEXT_HIGHEST_MASK)
2713
2714 /* Base of sub-group is 8. */
2715 index = 8;
2716
2717 else if (TCD_Priority_Groups & TC_NEXT_LOWEST_MASK)
2718
2719 /* Base of sub-group is 16. */
2720 index = 16;
2721 else
2722
2723 /* Base of sub-group is 24. */
2724 index = 24;
2725
2726 /* Calculate the highest available priority. */
2727 index = index + TCD_Lowest_Set_Bit[(INT)
2728 ((TCD_Priority_Groups >> index) & TC_HIGHEST_MASK)];
2729
2730 /* Get the mask of the priority within the group of
2731 8 priorities. */
2732 temp = TCD_Sub_Priority_Groups[index];
2733
2734 /* Calculate the actual priority. */
2735 TCD_Highest_Priority =
2736 (index << 3) + TCD_Lowest_Set_Bit[temp];
2737 }
2738 }
2739 }
2740 else
2741 {
2742
2743 /* Not the only task ready at the same priority level. */
2744
2745 /* Remove from the linked-list. */
2746 (task -> tc_ready_previous) -> tc_ready_next =
2747 task -> tc_ready_next;
2748 (task -> tc_ready_next) -> tc_ready_previous =
2749 task -> tc_ready_previous;
2750
2751 /* See if the task being suspended is the current. */
2752 if (*(task -> tc_priority_head) == task)
2753
2754 /* Update the head of this priority list. */
2755 *(task -> tc_priority_head) = task -> tc_ready_next;
2756
2757 /* Clear the task's pointers. */
2758 task -> tc_ready_next = NU_NULL;
2759 task -> tc_ready_previous = NU_NULL;
2760 }
2761
2762 /* Determine the next task to execute. */
2763 if (TCD_Highest_Priority < TC_PRIORITIES)
2764
2765 /* Put the next task to execute in TCD_Execute_Task. */
2766 TCT_Set_Execute_Task(TCD_Priority_List[TCD_Highest_Priority]);
2767 else
2768
2769 /* No other task is ready for execution. */
2770 TCT_Set_Execute_Task(NU_NULL);
2771 }
2772
2773 /* At this point, just exit back to the system. Note that the
2774 signal exit routine clears the scheduling protection. */
2775 TCT_Signal_Exit();
2776 }
2777
2778 /* A signal handler was called from the current task. Nothing needs
2779 to be done except to release protection. */
2780 TCT_Unprotect();
2781 }
2782
2783
2784 /*************************************************************************/
2785 /* */
2786 /* FUNCTION */
2787 /* */
2788 /* TCC_Dispatch_LISR */
2789 /* */
2790 /* DESCRIPTION */
2791 /* */
2792 /* This function dispatches the LISR associated with the specified */
2793 /* interrupt vector. Note that this function is called during */
2794 /* the interrupt thread. This routine must be called from */
2795 /* Supervisor mode in a Supervisor/User mode switching kernel. */
2796 /* */
2797 /* CALLED BY */
2798 /* */
2799 /* INT_Interrupt_Shell Shell of interrupt routine */
2800 /* */
2801 /* CALLS */
2802 /* */
2803 /* application LISR */
2804 /* ERC_System_Error Unhandled interrupt error */
2805 /* */
2806 /* INPUTS */
2807 /* */
2808 /* vector Vector number of interrupt */
2809 /* */
2810 /* OUTPUTS */
2811 /* */
2812 /* None */
2813 /* */
2814 /* HISTORY */
2815 /* */
2816 /* DATE REMARKS */
2817 /* */
2818 /* 03-01-1993 Created initial version 1.0 */
2819 /* 04-19-1993 Verified version 1.0 */
2820 /* 11-01-1993 Added logic to save unhandled */
2821 /* interrupt vector number in */
2822 /* a global variable, resulting */
2823 /* in version 1.0e */
2824 /* 11-01-1993 Verified version 1.0e */
2825 /* */
2826 /*************************************************************************/
2827 VOID TCC_Dispatch_LISR(INT vector)
2828 {
2829
2830 INT index; /* Working index variable */
2831
2832
2833 /* Determine if the specified vector has an LISR registered to it. */
2834 index = (INT) TCD_Registered_LISRs[vector];
2835 if (index <= NU_MAX_LISRS)
2836 {
2837 #ifdef INCLUDE_PROVIEW
2838 _RTProf_Dispatch_LISR_No_INT_Lock(vector);
2839 #endif /*INCLUDE_PROVIEW*/
2840
2841 /* Yes, an LISR is associated with this vector. Call the actual
2842 registered LISR routine. */
2843 (*(TCD_LISR_Pointers[index])) (vector);
2844 }
2845 else
2846 {
2847
2848 /* Save interrupt vector number in TCD_Unhandled_Interrupt. */
2849 TCD_Unhandled_Interrupt = vector;
2850
2851 /* System error, unhandled interrupt. */
2852 ERC_System_Error(NU_UNHANDLED_INTERRUPT);
2853 }
2854 }
2855
2856
2857 /*************************************************************************/
2858 /* */
2859 /* FUNCTION */
2860 /* */
2861 /* TCC_Register_LISR */
2862 /* */
2863 /* DESCRIPTION */
2864 /* */
2865 /* This function registers the supplied LISR with the supplied */
2866 /* vector number. If the supplied LISR is NU_NULL, the supplied */
2867 /* vector is de-registered. The previously registered LISR is */
2868 /* returned to the caller, along with the completion status. This */
2869 /* routine must be called from Supervisor mode in a Supervisor/ */
2870 /* User mode switching kernel. */
2871 /* */
2872 /* CALLED BY */
2873 /* */
2874 /* Application */
2875 /* */
2876 /* CALLS */
2877 /* */
2878 /* [HIC_Make_History_Entry] Make entry in history log */
2879 /* INT_Retrieve_Shell Retrieve vector shell pointer*/
2880 /* INT_Setup_Vector Setup the actual vector */
2881 /* INT_Vectors_Loaded Determine if interrupt shell */
2882 /* routines are loaded */
2883 /* [TCT_Check_Stack] Stack checking function */
2884 /* TCT_Protect Protect LISR registration */
2885 /* TCT_Unprotect Release LISR protection */
2886 /* */
2887 /* INPUTS */
2888 /* */
2889 /* vector Vector number of interrupt */
2890 /* new_lisr New LISR function */
2891 /* old_lisr Previous LISR function ptr */
2892 /* */
2893 /* OUTPUTS */
2894 /* */
2895 /* NU_SUCCESS Successful registration */
2896 /* NU_INVALID_VECTOR Invalid interrupt vector */
2897 /* NU_NO_MORE_LISRS LISR registration table is */
2898 /* full */
2899 /* NU_NOT_REGISTERED LISR was not registered */
2900 /* */
2901 /* HISTORY */
2902 /* */
2903 /* DATE REMARKS */
2904 /* */
2905 /* 03-01-1993 Created initial version 1.0 */
2906 /* 04-19-1993 Verified version 1.0 */
2907 /* 03-01-1994 Added appropriate casting, */
2908 /* resulting in version 1.1 */
2909 /* */
2910 /* 03-18-1994 Verified version 1.1 */
2911 /* */
2912 /*************************************************************************/
2913 STATUS TCC_Register_LISR(INT vector, VOID (*new_lisr)(INT),
2914 VOID (**old_lisr)(INT))
2915 {
2916
2917 INT index; /* Working index variable */
2918 STATUS status; /* Completion status */
2919
2920
2921 #ifdef NU_ENABLE_STACK_CHECK
2922
2923 /* Call stack checking function to check for an overflow condition. */
2924 TCT_Check_Stack();
2925
2926 #endif
2927
2928 #ifdef NU_ENABLE_HISTORY
2929
2930 /* Make an entry that corresponds to this function in the system history
2931 log. */
2932 HIC_Make_History_Entry(NU_REGISTER_LISR_ID, (UNSIGNED) vector,
2933 (UNSIGNED) new_lisr, (UNSIGNED) old_lisr);
2934
2935 #endif
2936
2937 /* Determine if the vector is legal. */
2938 if (vector > NU_MAX_VECTORS)
2939 return(NU_INVALID_VECTOR);
2940
2941 /* Initialize the completion status to successful. */
2942 status = NU_SUCCESS;
2943
2944 /* Protect against LISR registration list access. */
2945 TCT_Protect(&TCD_LISR_Protect);
2946
2947 /* Determine if a registration or deregistration is requested. This is
2948 determined by the value of new_lisr. A NULL value indicates
2949 deregistration. */
2950 if (new_lisr)
2951 {
2952
2953 /* Register the new LISR. */
2954
2955 /* Determine if the vector already has a registration. */
2956 if (TCD_Registered_LISRs[vector])
2957 {
2958
2959 /* Yes, a registration exists. */
2960
2961 /* Pickup the index into the LISR pointer list. */
2962 index = (INT) TCD_Registered_LISRs[vector];
2963
2964 /* Temporarily indicate that the LISR is not registered. */
2965 TCD_Registered_LISRs[vector] = 0;
2966
2967 /* Copy the currently registered LISR into the old_lisr return
2968 area. */
2969 *old_lisr = TCD_LISR_Pointers[index];
2970
2971 /* Place the new LISR into the list. */
2972 TCD_LISR_Pointers[index] = new_lisr;
2973
2974 /* Indicate the LISR is registered again. */
2975 TCD_Registered_LISRs[vector] = (UNSIGNED_CHAR) index;
2976 }
2977 else
2978 {
2979
2980 /* An empty slot needs to be found in the LISR pointers list. */
2981
2982 index = 0;
2983 while ((index <= NU_MAX_LISRS) &&
2984 (TCD_LISR_Pointers[index] != NU_NULL))
2985 index++;
2986
2987 /* Determine if an empty slot was found. */
2988 if (index <= NU_MAX_LISRS)
2989 {
2990
2991 /* Yes, an empty slot was found. */
2992
2993 /* Place the new LISR in the LISR pointers list. */
2994 TCD_LISR_Pointers[index] = new_lisr;
2995
2996 /* Associate the index into the pointers list to the actual
2997 vector. */
2998 TCD_Registered_LISRs[vector] = (UNSIGNED_CHAR) index;
2999
3000 /* Indicate that there was no previous LISR registered. */
3001 *old_lisr = NU_NULL;
3002
3003 /* Determine if the actual vector needs to be stolen. */
3004 if (!INT_Vectors_Loaded())
3005
3006 /* Actual vector needs to be replaced with the
3007 appropriate ISR shell. */
3008 INT_Setup_Vector(vector, INT_Retrieve_Shell(vector));
3009 }
3010 else
3011
3012 /* Return the completion status that indicates that there
3013 is no more room in the LISR pointers list. */
3014 status = NU_NO_MORE_LISRS;
3015 }
3016 }
3017 else
3018 {
3019
3020 /* De-register the specified vector. */
3021
3022 /* Determine if the vector has a registration current. */
3023 if (TCD_Registered_LISRs[vector])
3024 {
3025
3026 /* Pickup the index into the LISR pointer list. */
3027 index = (INT) TCD_Registered_LISRs[vector];
3028
3029 /* Clear the registration table. */
3030 TCD_Registered_LISRs[vector] = 0;
3031
3032 /* Return the previously registered LISR. */
3033 *old_lisr = TCD_LISR_Pointers[index];
3034
3035 /* Clear the LISR pointer list entry. */
3036 TCD_LISR_Pointers[index] = NU_NULL;
3037 }
3038 else
3039
3040 /* The vector is not registered. Return an error completion
3041 status. */
3042 status = NU_NOT_REGISTERED;
3043 }
3044
3045 #ifdef INCLUDE_PROVIEW
3046 _RTProf_RegisterLisr(vector);
3047 #endif /*INCLUDE_PROVIEW*/
3048
3049 /* Release protection on the LISR registration list. */
3050 TCT_Unprotect();
3051
3052 /* Return the completion status. */
3053 return(status);
3054 }
3055
3056
3057
3058
3059
3060