FreeCalypso > hg > freecalypso-sw
comparison nuc-fw/nucleus/tcc.c @ 79:947b1f473960
beginning of nuc-fw
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 11 Aug 2013 07:17:25 +0000 |
parents | |
children | 2c5160a9d652 |
comparison
equal
deleted
inserted
replaced
78:2c266d4339ff | 79:947b1f473960 |
---|---|
1 /*************************************************************************/ | |
2 /* */ | |
3 /* Copyright Mentor Graphics Corporation 2002 */ | |
4 /* All Rights Reserved. */ | |
5 /* */ | |
6 /* THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS */ | |
7 /* THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS */ | |
8 /* SUBJECT TO LICENSE TERMS. */ | |
9 /* */ | |
10 /*************************************************************************/ | |
11 | |
12 /*************************************************************************/ | |
13 /* */ | |
14 /* FILE NAME VERSION */ | |
15 /* */ | |
16 /* 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 |