view src/nucleus/tcc.c @ 276:4221c724c664

R2D: preparations for adding LCD hardware suspend handling
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 07 Sep 2021 21:05:38 +0000
parents 4e78acac3d88
children
line wrap: on
line source

/*************************************************************************/
/*                                                                       */
/*               Copyright Mentor Graphics Corporation 2002              */
/*                         All Rights Reserved.                          */
/*                                                                       */
/* THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS  */
/* THE PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS   */
/* SUBJECT TO LICENSE TERMS.                                             */
/*                                                                       */
/*************************************************************************/

/*************************************************************************/
/*                                                                       */
/* FILE NAME                                               VERSION       */
/*                                                                       */
/*      tcc.c                                          Nucleus PLUS 1.14 */
/*                                                                       */
/* COMPONENT                                                             */
/*                                                                       */
/*      TC - Thread Control                                              */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This file contains the core routines for the Thread Control      */
/*      component.                                                       */
/*                                                                       */
/* DATA STRUCTURES                                                       */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* FUNCTIONS                                                             */
/*                                                                       */
/*      TCC_Create_Task                     Create a task                */
/*      TCC_Delete_Task                     Delete a task                */
/*      TCC_Create_HISR                     Create HISR                  */
/*      TCC_Delete_HISR                     Delete HISR                  */
/*      TCC_Reset_Task                      Reset the specified task     */
/*      TCC_Terminate_Task                  Terminate the specified task */
/*      TCC_Resume_Task                     Resume a task                */
/*      TCC_Resume_Service                  Resume a task service call   */
/*      TCC_Suspend_Task                    Suspend a task               */
/*      TCC_Suspend_Service                 Suspend a task service call  */
/*      TCC_Task_Timeout                    Task timeout function        */
/*      TCC_Task_Sleep                      Task sleep request           */
/*      TCC_Relinquish                      Relinquish task execution    */
/*      TCC_Time_Slice                      Process task time-slice      */
/*      TCC_Current_Task_Pointer            Retrieve current task pointer*/
/*      TCC_Current_HISR_Pointer            Retrieve current HISR pointer*/
/*      TCC_Task_Shell                      Task execution shell         */
/*      TCC_Signal_Shell                    Signal execution shell       */
/*      TCC_Dispatch_LISR                   Dispatch LISR routine        */
/*      TCC_Register_LISR                   Register an LISR             */
/*                                                                       */
/* DEPENDENCIES                                                          */
/*                                                                       */
/*      cs_extr.h                           Common Service functions     */
/*      tc_extr.h                           Thread Control functions     */
/*      in_extr.h                           Initialization/Interrupt     */
/*                                            functions                  */
/*      tm_extr.h                           Timer Control function       */
/*      er_extr.h                           Error handling function      */
/*      hi_extr.h                           History functions            */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      05-15-1993      Corrected comment problems in                    */
/*                      TCC_Control_Signals and                          */
/*                      TCC_Register_Signal_Handler,                     */
/*                      making version 1.0a                              */
/*      05-15-1993      Verified version 1.0a                            */
/*      06-01-1993      Modified a multi-line comment                    */
/*                      after a #include directive                       */
/*                      that gave some compilers a                       */
/*                      problem, making version 1.0b                     */
/*      06-01-1993      Verified version 1.0b                            */
/*      08-09-1993      Corrected pointer retrieval                      */
/*                      loop, resulting in version 1.0c                  */
/*      08-09-1993      Verified version 1.0c                            */
/*      09-19-1993      Corrected an initialization                      */
/*                      problem of de-referencing a                      */
/*                      NULL pointer, resulting in                       */
/*                      version 1.0d                                     */
/*      09-19-1993      Verified version 1.0d                            */
/*      11-01-1993      Added logic to save unhandled                    */
/*                      interrupt vector number in                       */
/*                      a global variable, resulting                     */
/*                      in version 1.0e                                  */
/*      11-01-1993      Verified version 1.0e                            */
/*      02-01-1994      Corrected a suspension with                      */
/*                      timeout problem that caused                      */
/*                      unconditional task suspension                    */
/*                      for timeouts and sleeps for 1                    */
/*                      tick, resulting in version 1.0f                  */
/*      02-01-1994      Verified version 1.0f                            */
/*      03-01-1994      Added another routine that                       */
/*                      validates resume calls with                      */
/*                      the appropriate protection and                   */
/*                      added code to clear cleanup                      */
/*                      information at task create and                   */
/*                      task resume time, resulting in                   */
/*                      version 1.0g                                     */
/*      03-01-1994      Verified version 1.0g                            */
/*      03-01-1994      Moved non-core functions into                    */
/*                      supplemental files, changed                      */
/*                      function interfaces to match                     */
/*                      those in prototype, added                        */
/*                      register options, fixed bug                      */
/*                      in suspending current task from                  */
/*                      a HISR, added a system protect                   */
/*                      structure to reduce overhead                     */
/*                      in protection, moved resume                      */
/*                      validate to error checking                       */
/*                      file, resulting in version 1.1                   */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*      12-18-1995      Modified TCC_Resume_Service,                     */
/*                      resulting in version 1.1+                        */
/*                      (SPR 36, 64, 66, 77)                             */
/*      04-17-1996      updated to version 1.2                           */
/*      06-01-1996      Modified TCC_Suspend_Task                        */
/*                      (SPR152) creating version 1.2a                   */
/*      10-29-1997      Modified TCC_Resume_Task                         */
/*                      (SPR115) creating vresion 1.2b                   */
/*      01-23-1998      Released version 1.2b                            */
/*      03-20-1998      Corrected problem where tasks                    */
/*                      created with NU_NO_PREEMPT in                    */
/*                      Application_Initialize would                     */
/*                      start in the order of creation                   */
/*                      and not in priority order.                       */
/*                      SPR455 creates version 1.2c                      */
/*      03-24-1998      Released version 1.3.                            */
/*      10-02-1998      Another protect problem (1.3a)                   */
/*      10-02-1998      Corrected a problem where a                      */
/*                      a timer expiration occurs                        */
/*                      during signal handler execution                  */
/*                      and causes the task to never                     */
/*                      run again (SPR 923) creating                     */
/*                      version 1.3b.                                    */
/*      03-26-1999      Released 1.11m (new release                      */
/*                        numbering scheme)                              */
/*      04-17-2002      Released version 1.13m                           */
/*      11-07-2002      Released version 1.14                            */
/*************************************************************************/
#define         NU_SOURCE_FILE

#include        "in_defs.h"                 /* Initialization defines    */
#include        "cs_extr.h"                 /* Common service functions  */
#include        "tc_extr.h"                 /* Thread control functions  */
#include        "in_extr.h"                 /* Initialization/Interrupt  */
                                            /*   functions               */
#include        "tm_extr.h"                 /* Timer control functions   */
#include        "er_extr.h"                 /* Error handling function   */
#include        "hi_extr.h"                 /* History functions         */
#include        "profiler.h"                /* Nucleus Profiling header  */

#if ((defined(NU_MODULE_SUPPORT)) && (NU_MODULE_SUPPORT > 0))
#include        "module/inc/ms_defs.h"      /* MS_Module typedef */
#endif

/* Define external inner-component global data references.  */

extern INT              INC_Initialize_State;
extern CS_NODE         *TCD_Created_Tasks_List;
extern UNSIGNED         TCD_Total_Tasks;
extern TC_TCB          *TCD_Priority_List[TC_PRIORITIES];
extern UNSIGNED         TCD_Priority_Groups;
extern DATA_ELEMENT     TCD_Sub_Priority_Groups[TC_MAX_GROUPS];
extern UNSIGNED_CHAR    TCD_Lowest_Set_Bit[];
extern INT              TCD_Highest_Priority;
extern TC_TCB          *TCD_Execute_Task;
extern VOID            *TCD_Current_Thread;
extern UNSIGNED_CHAR    TCD_Registered_LISRs[NU_MAX_VECTORS+1];
extern VOID           (*TCD_LISR_Pointers[NU_MAX_LISRS+1])(INT vector);
extern INT              TCD_Interrupt_Count;
extern INT              TCD_Stack_Switched;
extern TC_PROTECT       TCD_List_Protect;
extern TC_PROTECT       TCD_System_Protect;
extern TC_PROTECT       TCD_LISR_Protect;
extern CS_NODE         *TCD_Created_HISRs_List;
extern UNSIGNED         TCD_Total_HISRs;
extern TC_PROTECT       TCD_HISR_Protect;
extern INT              TCD_Unhandled_Interrupt;


/* Define external inner-component function calls that are not available to
   other components.  */

VOID            TCT_Build_Task_Stack(TC_TCB *task_ptr);
VOID            TCT_Build_HISR_Stack(TC_HCB *hisr_ptr);
VOID            TCT_Build_Signal_Frame(TC_TCB *task_ptr);
VOID            TCT_Protect_Switch(TC_TCB *task);
VOID            TCT_Signal_Exit(VOID);


/* Define internal function calls.  */

VOID            TCC_Signal_Shell(VOID);


#if defined(NU_MODULE_SUPPORT) && (NU_MODULE_SUPPORT > 0)

/* Define service routines "privately" imported from other components */
extern MS_MODULE* msd_current_module;

STATUS MSC_Bind_Module_HISR(MS_MODULE* module, TC_HCB* hisr);
STATUS MSC_Bind_Module_Task(MS_MODULE* module, TC_TCB* task);

#endif /* NU_MODULE_SUPPORT */

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Create_Task                                                  */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function creates a task and then places it on the list of   */
/*      created tasks.  All the resources necessary to create the task   */
/*      are supplied to this routine.  If specified, the newly created   */
/*      task is started.  Otherwise, it is left in a suspended state.    */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      TCCE_Create_Task                    Error checking shell         */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      CSC_Place_On_List                   Add TCB to linked-list       */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      TCC_Resume_Task                     Start the created task       */
/*      TCT_Build_Task_Stack                Build an initial task stack  */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Control_To_System               Transfer control to system   */
/*      TCT_Protect                         Protect created task list    */
/*      TCT_Unprotect                       Release protection of list   */
/*      TMC_Init_Task_Timer                 Initialize the task's timer  */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      task_ptr                            Task control block pointer   */
/*      name                                Task name                    */
/*      task_entry                          Entry function of the task   */
/*      argc                                Optional task parameter      */
/*      argv                                Optional task parameter      */
/*      stack_address                       Pointer to start of stack    */
/*      stack_size                          Size of task stack in bytes  */
/*      priority                            Task priority                */
/*      time_slice                          Task time slice              */
/*      preempt                             Task preemptability flag     */
/*      auto_start                          Automatic task start         */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                                                       */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified function interface,                     */
/*                      added register optimizations,                    */
/*                      added system protection logic,                   */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
STATUS  TCC_Create_Task(NU_TASK *task_ptr, CHAR *name,
          VOID (*task_entry)(UNSIGNED, VOID *), UNSIGNED argc, VOID *argv,
          VOID *stack_address, UNSIGNED stack_size,
          OPTION priority, UNSIGNED time_slice,
          OPTION preempt, OPTION auto_start)
{

R1 TC_TCB      *task;                       /* Task control block ptr    */
R2 INT          i;                          /* Working index variable    */
STATUS          status = NU_SUCCESS;

NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

    /* Move input task pointer into internal pointer.  */
    task =  (TC_TCB *) task_ptr;


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_CREATE_TASK_ID, (UNSIGNED) task,
                                (UNSIGNED) name, (UNSIGNED) task_entry);

#endif

    /* First, clear the task ID just in case it is an old Task
       Control Block.  */
    task -> tc_id =             0;

    /* Fill in the task name.  */
    for (i = 0; i < NU_MAX_NAME; i++)
        task -> tc_name[i] =  name[i];

    /* Fill in the basic task information.  */
    task -> tc_entry =                  task_entry;
    task -> tc_argc =                   argc;
    task -> tc_argv =                   argv;
    task -> tc_status =                 NU_PURE_SUSPEND;
    task -> tc_delayed_suspend =        NU_FALSE;
    task -> tc_scheduled =              0;
    task -> tc_time_slice =             time_slice;
    task -> tc_cur_time_slice =         time_slice;
    task -> tc_current_protect =        NU_NULL;
    task -> tc_suspend_protect =        NU_NULL;
    task -> tc_cleanup =                NU_NULL;
    task -> tc_cleanup_info =           NU_NULL;

    /* Setup task's preemption posture.  */
    if (preempt == NU_PREEMPT)
        task -> tc_preemption =  NU_TRUE;
    else
        task -> tc_preemption =  NU_FALSE;

    /* Fill in information about the task's stack.  */
    task -> tc_stack_start =            stack_address;
    task -> tc_stack_end =              0;
    task -> tc_stack_size =             stack_size;
    task -> tc_stack_minimum =          stack_size;

    /* Setup priority information for the task.  There are two bit maps
       associated with each task.  The first bit map indicates which group
       of 8-priorities it is.  The second bit map indicates the actual
       priority within the group.  */
    task -> tc_priority =               priority;
    task -> tc_priority_head =          &(TCD_Priority_List[priority]);
    task -> tc_sub_priority =           (DATA_ELEMENT) (1 << (priority & 7));
    priority =                          priority >> 3;
    task -> tc_priority_group =         ((UNSIGNED) 1) << priority;
    task -> tc_sub_priority_ptr =       &(TCD_Sub_Priority_Groups[priority]);

    /* Initialize link pointers.  */
    task -> tc_created.cs_previous =    NU_NULL;
    task -> tc_created.cs_next =        NU_NULL;
    task -> tc_ready_previous =         NU_NULL;
    task -> tc_ready_next =             NU_NULL;

    /* Build a stack frame for this task by calling TCT_Build_Task_Stack.  */
    TCT_Build_Task_Stack(task);

    /* Initialize the signal information of the task.  */
    task -> tc_signals =                0;
    task -> tc_enabled_signals =        0;
    task -> tc_signal_handler =         0;
    task -> tc_signal_active =          NU_FALSE;
    /* Initialize additional kernel options data */

#if (NU_SUPERV_USER_MODE == 1)
    task->tc_su_mode = 0;              /* Initially in User mode */
    task->tc_module = 0;               /* Not initially bound to a module */
#endif

    /* Initialize the task timer.  */
    task -> tc_timer_active =           NU_FALSE;
    TMC_Init_Task_Timer(&(task -> tc_timer_control), (VOID *) task);

    /* Protect the list of created tasks.  */
    TCT_Protect(&TCD_List_Protect);

    /* At this point the task is completely built.  The ID can now be
       set and it can be linked into the created task list.  */
    task -> tc_id =                     TC_TASK_ID;

#if defined(NU_MODULE_SUPPORT) && (NU_MODULE_SUPPORT > 0)
    /* If executing in a thread's context, bind to that thread's module */
    if(TCD_Current_Thread != NU_NULL)
    {
        status = MSC_Bind_Module_Task(
          (MS_MODULE*)(((TC_TCB*)(TCD_Current_Thread))->tc_module), task);
    }
    else /* It must be initialization time, so use the current module */
    {
        status = MSC_Bind_Module_Task(msd_current_module, task);
    }
#endif /* NU_MODULE_SUPPORT */

    /* Link the task into the list of created tasks and increment the
       total number of tasks in the system.  */
    CSC_Place_On_List(&TCD_Created_Tasks_List, &(task -> tc_created));
    TCD_Total_Tasks++;

#ifdef INCLUDE_PROVIEW
    _RTProf_DumpTask(task,RT_PROF_CREATE_TASK);
#endif

    /* Release the protection.  */
    TCT_Unprotect();

    /* Determine if the task should be automatically started.  */
    if (auto_start == NU_START)
    {

        /* Protect the system data structures.  */
        TCT_Protect(&TCD_System_Protect);

        /* Start the task by resuming it.  If the preemption is required,
           leave the current task.  */
        if (TCC_Resume_Task(task_ptr, NU_PURE_SUSPEND))


            /* Transfer control back to the system.  */
            TCT_Control_To_System();
        else

            /* Release the protection.  */
            TCT_Unprotect();
    }

    /* Return to user mode */
    NU_USER_MODE();

    /* Return successful completion.  */
    return(status);
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Create_HISR                                                  */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function creates a High-Level Interrupt Service Routine     */
/*      (HISR) and then places it on the list of created HISRs.  All     */
/*      the resources necessary to create the HISR are supplied to this  */
/*      routine.  HISRs are always created in a dormant state.           */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      TCCE_Create_HISR                    Error checking shell         */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      CSC_Place_On_List                   Add TCB to linked-list       */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      TCT_Build_HISR_Stack                Build an initial HISR stack  */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Protect                         Protect created HISR list    */
/*      TCT_Unprotect                       Release protection of list   */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      hisr_ptr                            HISR control block pointer   */
/*      name                                HISR name                    */
/*      hisr_entry                          Entry function of the HISR   */
/*      priority                            Task priority                */
/*      stack_address                       Pointer to start of stack    */
/*      stack_size                          Size of HISR stack in bytes  */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                                                       */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified function interface,                     */
/*                      added register optimizations,                    */
/*                      added more control block                         */
/*                      initialization, resulting in                     */
/*                      version 1.1                                      */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
STATUS  TCC_Create_HISR(NU_HISR *hisr_ptr, CHAR *name,
          VOID (*hisr_entry)(VOID), OPTION priority,
          VOID *stack_address, UNSIGNED stack_size)
{

R1 TC_HCB      *hisr;                       /* HISR control block ptr    */
R2 INT          i;                          /* Working index variable    */
STATUS          status = NU_SUCCESS;

NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

    /* Move input HISR pointer into internal pointer.  */
    hisr =  (TC_HCB *) hisr_ptr;


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_CREATE_HISR_ID, (UNSIGNED) hisr,
                                (UNSIGNED) name, (UNSIGNED) hisr_entry);

#endif

    /* First, clear the HISR ID just in case it is an old HISR
       Control Block.  */
    hisr -> tc_id =             0;

    /* Fill in the HISR name.  */
    for (i = 0; i < NU_MAX_NAME; i++)
        hisr -> tc_name[i] =  name[i];

    /* Fill in the basic HISR information.  */
    hisr -> tc_entry =                  hisr_entry;
    hisr -> tc_scheduled =              0;
    hisr -> tc_activation_count =       0;
    hisr -> tc_cur_time_slice =         0;

    /* Fill in information about the HISR's stack.  */
    hisr -> tc_stack_start =            stack_address;
    hisr -> tc_stack_end =              0;
    hisr -> tc_stack_size =             stack_size;
    hisr -> tc_stack_minimum =          stack_size;

    /* Setup priority information for the HISR.  Priorities range from 0 to
       TC_HISR_PRIORITIES - 1.  */
    hisr -> tc_priority =               priority & 3;

    /* Initialize link pointers.  */
    hisr -> tc_created.cs_previous =    NU_NULL;
    hisr -> tc_created.cs_next =        NU_NULL;
    hisr -> tc_active_next =            NU_NULL;

    /* Clear protect pointer.  */
    hisr -> tc_current_protect =        NU_NULL;

    /* Initialize additional kernel options data */
#if (NU_SUPERV_USER_MODE == 1)
    hisr->tc_su_mode = 1;                   /* TCT_HISR_Shell in Supervisor mode */
    hisr->tc_module = 0;                    /* Not initially bound to a module */
#endif

    /* Build a stack frame for this HISR by calling TCT_Build_HISR_Stack.  */
    TCT_Build_HISR_Stack(hisr);

    /* Protect the list of created HISRs.  */
    TCT_Protect(&TCD_HISR_Protect);

    /* At this point the HISR is completely built.  The ID can now be
       set and it can be linked into the created HISR list.  */
    hisr -> tc_id =                     TC_HISR_ID;

#if defined(NU_MODULE_SUPPORT) && (NU_MODULE_SUPPORT > 0)
    /* If executing in a thread's context, bind to that thread's module */
    if(TCD_Current_Thread != NU_NULL)
    {
        status = MSC_Bind_Module_HISR(
          (MS_MODULE*)(((TC_TCB*)(TCD_Current_Thread))->tc_module), hisr);
    }
    else /* It must be initialization time, so use the current module */
    {
        status = MSC_Bind_Module_HISR(msd_current_module, hisr);
    }
#endif /* NU_MODULE_SUPPORT */

    /* Link the HISR into the list of created HISRs and increment the
       total number of HISRs in the system.  */
    CSC_Place_On_List(&TCD_Created_HISRs_List, &(hisr -> tc_created));
    TCD_Total_HISRs++;

#ifdef INCLUDE_PROVIEW
    _RTProf_DumpHisr(hisr,RT_PROF_CREATE_HISR);
#endif

    /* Release the protection.  */
    TCT_Unprotect();

    /* Return to user mode */
    NU_USER_MODE();

    /* Return successful completion.  */
    return(status);
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Delete_Task                                                  */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function deletes a task and removes it from the list of     */
/*      created tasks.  It is assumed by this function that the task is  */
/*      in a finished or terminated state.  Note that this function      */
/*      does not free memory associated with the task's control block or */
/*      its stack.  This is the responsibility of the application.       */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      TCCE_Delete_Task                    Error checking shell         */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      CSC_Remove_From_List                Remove node from list        */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Protect                         Protect created task list    */
/*      TCT_Unprotect                       Release protection of list   */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      task_ptr                            Task control block pointer   */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                                                       */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified function interface,                     */
/*                      added register optimizations,                    */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
STATUS  TCC_Delete_Task(NU_TASK *task_ptr)
{

R1 TC_TCB  *task;                           /* Task control block ptr    */
NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

    /* Move input task pointer into internal pointer.  */
    task =  (TC_TCB *) task_ptr;


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_DELETE_TASK_ID, (UNSIGNED) task,
                                        (UNSIGNED) 0, (UNSIGNED) 0);

#endif

    /* Protect the list of created tasks.  */
    TCT_Protect(&TCD_List_Protect);

#ifdef INCLUDE_PROVIEW
    _RTProf_DumpTask(task,RT_PROF_DELETE_TASK);
#endif /*INCLUDE_PROVIEW*/

    /* Remove the task from the list of created tasks.  */
    CSC_Remove_From_List(&TCD_Created_Tasks_List, &(task -> tc_created));

    /* Decrement the total number of created tasks.  */
    TCD_Total_Tasks--;

    /* Clear the task ID just in case.  */
    task -> tc_id =  0;

    /* Release protection.  */
    TCT_Unprotect();

    /* Return to user mode */
    NU_USER_MODE();

    /* Return a successful completion.  */
    return(NU_SUCCESS);
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Delete_HISR                                                  */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function deletes a HISR and removes it from the list of     */
/*      created HISRs.  It is assumed by this function that the HISR is  */
/*      in a non-active state.  Note that this function does not free    */
/*      memory associated with the HISR's control block or its stack.    */
/*      This is the responsibility of the application.                   */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      TCCE_Delete_HISR                    Error checking shell         */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      CSC_Remove_From_List                Remove node from list        */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Protect                         Protect created HISR list    */
/*      TCT_Unprotect                       Release protection of list   */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      hisr_ptr                            HISR control block pointer   */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                                                       */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified function interface,                     */
/*                      added register optimizations,                    */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
STATUS  TCC_Delete_HISR(NU_HISR *hisr_ptr)
{

R1 TC_HCB  *hisr;                           /* HISR control block ptr    */
NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

    /* Move input HISR pointer into internal pointer.  */
    hisr =  (TC_HCB *) hisr_ptr;


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_DELETE_HISR_ID, (UNSIGNED) hisr,
                                        (UNSIGNED) 0, (UNSIGNED) 0);

#endif

    /* Protect the list of created HISRs.  */
    TCT_Protect(&TCD_HISR_Protect);

#ifdef INCLUDE_PROVIEW
    _RTProf_DumpHisr(hisr,RT_PROF_DELETE_HISR);
#endif /*INCLUDE_PROVIEW*/

    /* Remove the HISR from the list of created HISRs.  */
    CSC_Remove_From_List(&TCD_Created_HISRs_List, &(hisr -> tc_created));

    /* Decrement the total number of created HISRs.  */
    TCD_Total_HISRs--;

    /* Clear the HISR ID just in case.  */
    hisr -> tc_id =  0;

    /* Release protection.  */
    TCT_Unprotect();

    /* Return to user mode */
    NU_USER_MODE();

    /* Return a successful completion.  */
    return(NU_SUCCESS);
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Reset_Task                                                   */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function resets the specified task.  Note that a task reset */
/*      can only be performed on tasks in a finished or terminated state.*/
/*      The task is left in an unconditional suspended state.            */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      TCCE_Reset_Task                     Error checking shell         */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      TCT_Build_Task_Stack                Build an initial task stack  */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Protect                         Protect created task list    */
/*      TCT_Unprotect                       Release protection of list   */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      task_ptr                            Task control block pointer   */
/*      argc                                Optional task parameter      */
/*      argv                                Optional task parameter      */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                          Indicates successful request */
/*      NU_NOT_TERMINATED                   Indicates task was not       */
/*                                            finished or terminated     */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*        DATE                    REMARKS                                */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified function interface,                     */
/*                      added register optimizations,                    */
/*                      added system protection logic,                   */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
STATUS  TCC_Reset_Task(NU_TASK *task_ptr, UNSIGNED argc, VOID *argv)
{

R1 TC_TCB      *task;                       /* Task control block ptr   */
STATUS          status;                     /* Status of the request    */
NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

    /* Move input task pointer into internal pointer.  */
    task =  (TC_TCB *) task_ptr;

#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_RESET_TASK_ID, (UNSIGNED) task,
                                        (UNSIGNED) argc, (UNSIGNED) argv);

#endif

    /* Protect system structures.  */
    TCT_Protect(&TCD_System_Protect);

    /* Determine if the task is in the proper state.  */
    if ((task -> tc_status == NU_FINISHED) ||
                        (task -> tc_status == NU_TERMINATED))
    {

        /* Yes, a valid reset is present.  Indicate this in the status.  */
        status =  NU_SUCCESS;

        /* Fill in the new argument information and reset some of the other
           fields.  */
        task -> tc_argc =                   argc;
        task -> tc_argv =                   argv;
        task -> tc_status =                 NU_PURE_SUSPEND;
        task -> tc_delayed_suspend =        NU_FALSE;
        task -> tc_scheduled =              0;
        task -> tc_stack_minimum =          task -> tc_stack_size;

#if (NU_SUPERV_USER_MODE == 1)
        /* Since we are doing a complete reset we need to ensure 
           that this field is 0 since the task will be started in
           user mode.  TCC_Task_Shell can not return and therefore
           left the task in supervisor mode when the task completed.
           If we were to not re-initialize this field the task would
           become locked in user mode and API would fail. */
        task -> tc_su_mode = 0;
#endif

        /* Build a stack frame for this task by calling
           TCT_Build_Task_Stack.  */
        TCT_Build_Task_Stack(task);
    }
    else

        /* The requested task is not in a finished or terminated state.  */
        status =  NU_NOT_TERMINATED;

#ifdef INCLUDE_PROVIEW
    _RTProf_DumpTask(task,RT_PROF_RESET_TASK);
#endif /*INCLUDE_PROVIEW*/

    /* Release the protection.  */
    TCT_Unprotect();

    /* Return to user mode */
    NU_USER_MODE();

    /* Return completion status.  */
    return(status);
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Terminate_Task                                               */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function terminates the specified task.  If the task is     */
/*      already terminated, this function does nothing.  If the task     */
/*      to terminate is currently suspended, the specified cleanup       */
/*      routine is also invoked to cleanup suspension data structures.   */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      TCCE_Terminate_Task                 Error checking shell         */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      Cleanup routine                     Task's suspend cleanup funct */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      TCC_Suspend_Task                    Suspend a ready task         */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Protect                         Protect created task list    */
/*      TCT_Unprotect                       Release protection of list   */
/*      TCT_Unprotect_Specific              Specific unprotection        */
/*      TMC_Stop_Task_Timer                 Stop a task timer            */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      task_ptr                            Task control block pointer   */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                                                       */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified function interface,                     */
/*                      added register optimizations,                    */
/*                      added system protection logic,                   */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
STATUS  TCC_Terminate_Task(NU_TASK *task_ptr)
{

R1 TC_TCB      *task;                       /* Task control block ptr    */
TC_PROTECT     *suspend_protect;            /* Suspension protection ptr */
DATA_ELEMENT    status;                     /* Task status               */
NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

    /* Move task pointer into internal pointer.  */
    task =  (TC_TCB *) task_ptr;


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_TERMINATE_TASK_ID, (UNSIGNED) task,
                                        (UNSIGNED) 0, (UNSIGNED) 0);

#endif

    /* Determine if the calling task is the current task.  */
    if (task == (TC_TCB *) TCD_Current_Thread)
    {

        /* Protect system  data structures.  */
        TCT_Protect(&TCD_System_Protect);

#ifdef INCLUDE_PROVIEW
    _RTProf_DumpTask(task,RT_PROF_TERMINATE_TASK);
#endif /*INCLUDE_PROVIEW*/

        /* Suspend the calling task with the NU_TERMINATED status.  */
        TCC_Suspend_Task(task_ptr, NU_TERMINATED, NU_NULL, NU_NULL,
                                                            NU_SUSPEND);

        /* No need to un-protect, since control never comes back to this
           point and the protection is cleared in TCT_Control_To_System.  */
    }
    else
    {

        /* Protect scheduling structures.  */
        TCT_Protect(&TCD_System_Protect);

#ifdef INCLUDE_PROVIEW
    _RTProf_DumpTask(task,RT_PROF_TERMINATE_TASK);
#endif /*INCLUDE_PROVIEW*/

        /* Keep trying to terminate the specified task until its status
           indicates that it is terminated or finished.  */
        while ((task -> tc_status != NU_FINISHED) &&
                  task -> tc_status != NU_TERMINATED)
        {

            /* Is the task in a ready state?  */
            if (task -> tc_status == NU_READY)
            {

                /* Terminate the specified task.  */
                TCC_Suspend_Task(task_ptr, NU_TERMINATED, NU_NULL,
                                                        NU_NULL,NU_SUSPEND);

                /* Clear system protection.  */
                TCT_Unprotect();
            }
            else
            {

                /* Task is suspended currently.  Pickup the suspension
                   protection.  */
                suspend_protect =  task -> tc_suspend_protect;

                /* Save the current status.  */
                status =           task -> tc_status;

                /* Release protection on system structures.  */
                TCT_Unprotect();

                /* Determine if there was a suspension protection.  If so
                   protect it first before the scheduling list protection.
                   This avoids a deadlock situation.  */
                if (suspend_protect)

                    /* Protect the terminated task's last suspension
                       structures.  */
                    TCT_Protect(suspend_protect);

                /* Protect the system structures again.  */
                TCT_Protect(&TCD_System_Protect);

                /* Now determine if the same suspension is in force.  */
                if ((task -> tc_status == status) &&
                    (task -> tc_suspend_protect == suspend_protect))
                {

                    /* Yes, same suspension is in force.  */

                    /* Call cleanup routine, if there is one.  */
                    if (task -> tc_cleanup)

                        /* Call cleanup function.  */
                        (*(task -> tc_cleanup)) (task -> tc_cleanup_info);

                    /* Status the task as terminated.  */
                    task -> tc_status =  NU_TERMINATED;

                    /* Determine if there is a timer active.  */
                    if (task -> tc_timer_active)
                    {

                        /* Call the stop timer function.  */
                        TMC_Stop_Task_Timer(&(task -> tc_timer_control));

                        /* Clear the timer active flag.  */
                        task -> tc_timer_active =  NU_FALSE;
                    }
                }

                /* Cleanup the protection.  */
                if (suspend_protect)
                {

                    /* Release specific protection.  */
                    TCT_Unprotect_Specific(suspend_protect);

                    /* Clear the suspend protect field.  */
                    task -> tc_suspend_protect =  NU_NULL;
                }

                /* Release current protection.  */
                TCT_Unprotect();
            }

            /* Protect the scheduling list again.  */
            TCT_Protect(&TCD_System_Protect);
        }

        /* Release the protection.  */
        TCT_Unprotect();
    }

    /* Return to user mode */
    NU_USER_MODE();

    /* Return successful completion.  */
    return(NU_SUCCESS);
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Resume_Task                                                  */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function resumes a previously suspended task.  The task     */
/*      task must currently be suspended for the same reason indicated   */
/*      by this request.  If the task resumed is higher priority than    */
/*      the calling task and the current task is preemptable, this       */
/*      function returns a value of NU_TRUE.  Otherwise, if no           */
/*      preemption is required, a NU_FALSE is returned.  This routine    */
/*      must be called from Supervisor mode in a Supervisor/User mode    */
/*      switching kernel.                                                */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Other Components                                                 */
/*      TCC_Resume_Service                  Resume service function      */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Set_Current_Protect             Set current protection field */
/*      TCT_Set_Execute_Task                Set TCD_Execute_Task pointer */
/*      TMC_Stop_Task_Timer                 Stop task timer              */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      task_ptr                            Task control block pointer   */
/*      suspend_type                        Type of suspension to lift   */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_TRUE                             A higher priority task is    */
/*                                            ready to execute           */
/*      NU_FALSE                            No change in the task to     */
/*                                            execute                    */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*        DATE                    REMARKS                                */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      09-19-1993      Corrected an initialization                      */
/*                      problem of de-referencing a                      */
/*                      NULL pointer, resulting in                       */
/*                      version 1.0d                                     */
/*      09-19-1993      Verified version 1.0d                            */
/*      03-01-1994      Modified function interface,                     */
/*                      added register optimizations,                    */
/*                      modified protection logic to                     */
/*                      assume that system protection                    */
/*                      is already in force, resulting                   */
/*                      in version 1.1                                   */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*      10-29-1997      Changed so that tc_cleanup,                      */
/*                      tc_cleanup_info, and                             */
/*                      tc_suspend_protect are cleared                   */
/*                      only if a signal is not active                   */
/*                      (SPR115)                                         */
/*      03-20-1998      Corrected SPR455.                                */
/*                                                                       */
/*************************************************************************/
STATUS  TCC_Resume_Task(NU_TASK *task_ptr, OPTION suspend_type)
{

R1 TC_TCB      *task;                       /* Task control block ptr    */
R2 TC_TCB      *head;                       /* Pointer to priority list  */
STATUS          status =  NU_FALSE;         /* Status variable           */

    /* Move task pointer into internal pointer.  */
    task =  (TC_TCB *) task_ptr;


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif


    /* Check to see if the task is suspended for the reason that this
       resume is attempting to clear.  */
    if (task -> tc_status == suspend_type)
    {

        /* Yes, this resume call is valid.  */

        /* If signals are not active, clear any suspend or cleanup
           information (SPR115).  */
        if (!task -> tc_signal_active)
        {
            task -> tc_suspend_protect =        NU_NULL;
            task -> tc_cleanup =                NU_NULL;
            task -> tc_cleanup_info =           NU_NULL;
        }

        /* Determine if there is a timer active and the task is not being
           resumed to handle a signal.  */
        if ((task -> tc_timer_active) && (!task -> tc_signal_active))
        {

            /* Call the stop timer function.  */
            TMC_Stop_Task_Timer(&(task -> tc_timer_control));

            /* Clear the timer active flag.  */
            task -> tc_timer_active =  NU_FALSE;
        }

        /* Check to see if there is a pending pure suspension.  If so,
           change the cause of the suspension and leave in a suspended
           state.  */
        if (task -> tc_delayed_suspend)
        {

            /* Leave suspended but change the task's status and clear the
               delayed suspension flag.  */
            task -> tc_delayed_suspend =  NU_FALSE;
            task -> tc_status =  NU_PURE_SUSPEND;
        }
        else
        {

            /* Lift the suspension of the specified task.  */

            /* Clear the status of the task.  */
            task -> tc_status =  NU_READY;

#ifdef INCLUDE_PROVIEW
            _RTProf_TaskStatus(task,RT_TASK_READY);
#endif /*INCLUDE_PROVIEW*/

            /* Link the task into the appropriate priority list.  */
            head =  *(task -> tc_priority_head);

            /* Determine if the list is non-empty.  */
            if (head)
            {

                /* Add the new TCB to the end of the ready list.  */
                task -> tc_ready_previous =      head -> tc_ready_previous;
                (task -> tc_ready_previous) -> tc_ready_next =  task;
                task -> tc_ready_next =          head;
                (task -> tc_ready_next) -> tc_ready_previous =  task;

                /* Note that the priority bit map does not need to be
                   modified since there are other active tasks at the
                   same priority.  */
            }
            else
            {

                /* Add the new TCB to an empty list.  */
                task -> tc_ready_previous =  task;
                task -> tc_ready_next =      task;
                *(task -> tc_priority_head)= task;

                /* Update the priority group bit map to indicate that this
                   priority now has a task ready.  */
                TCD_Priority_Groups =
                        TCD_Priority_Groups | (task -> tc_priority_group);

                /* Update the sub-priority bit map to show that this priority
                   is ready.  */
                *(task -> tc_sub_priority_ptr) =
                   (*(task -> tc_sub_priority_ptr)) | task -> tc_sub_priority;

                /* Determine if this newly ready task is higher priority
                   than the current task.  */
                if ((INT) (task -> tc_priority) < TCD_Highest_Priority)
                {

                    /* Update the highest priority field.  */
                    TCD_Highest_Priority = (INT) task -> tc_priority;

                    /* See if there is a task to execute.  */
                    if (TCD_Execute_Task == NU_NULL)

                        /* Make this task the current.  */
                        TCT_Set_Execute_Task(task);

                    /* Check to see if the task to execute is preemptable.  */
                    /* SPR455 checks if we are in Application_Initialize */
                    else if ((TCD_Execute_Task -> tc_preemption)
                             || (INC_Initialize_State == INC_START_INITIALIZE))
                    {

                        /* Yes, the task to execute is preemptable.  Replace
                           it with the new task.  */
                        TCT_Set_Execute_Task(task);

                        /* Now, check and see if the current thread is a task.
                           If so, return a status that indicates a context
                           switch is needed.  */
                        if ((TCD_Current_Thread) &&
                           (((TC_TCB *) TCD_Current_Thread) -> tc_id ==
                                TC_TASK_ID))

                            /* Yes, a context switch is needed.  */
                            status =  NU_TRUE;
                    }
                }
            }
        }
    }
    else
    {

        /* Check for a resumption of a delayed pure suspend.  */
        if (suspend_type == NU_PURE_SUSPEND)

            /* Clear the delayed suspension.  */
            task -> tc_delayed_suspend =  NU_FALSE;

        /* Check for a signal active and the saved status the same as
           the resume request.  */
        if ((suspend_type == task -> tc_saved_status) &&
            (task -> tc_signal_active))
        {

            /* Indicate the saved status as ready.  */
            task -> tc_saved_status =  NU_READY;

            /* Determine if the task's timer is active.  */
            if (task -> tc_timer_active)
            {

                /* Stop the timer.  */
                TMC_Stop_Task_Timer(&(task -> tc_timer_control));

                /* Clear the timer active flag.  */
                task -> tc_timer_active =  NU_FALSE;
            }
        }
    }

#ifdef INCLUDE_PROVIEW
    _RTProf_DumpTask(task,RT_PROF_RESUME_TASK);
#endif /*INCLUDE_PROVIEW*/

    /* Return back the status.  */
    return(status);
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Resume_Service                                               */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function provides an interface identical to the application */
/*      service call to resume a task.                                   */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      TCCE_Resume_Service                 Error checking function      */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      TCC_Resume_Task                     Resume a task                */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Control_To_System               Transfer control to system   */
/*      TCT_Protect                         Protect system structures    */
/*      TCT_Unprotect                       Release system protection    */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      task_ptr                            Task control block pointer   */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                          Always returns success       */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified function interface,                     */
/*                      added register optimizations,                    */
/*                      added system protection logic,                   */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*      12-19-1995      Changed the "task" parameter to                  */
/*                      "task_ptr" in the                                */
/*                      HIC_Make_History_Entry call,                     */
/*                      resulting in version 1.1+                        */
/*                      (SPR 36, 64, 66, 77)                             */
/*      10-02-1998      Another protect problem (1.3a)                   */
/*                                                                       */
/*************************************************************************/
STATUS  TCC_Resume_Service(NU_TASK *task_ptr)
{

TC_PROTECT     *save_protect;               /* Save current protection   */
NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_RESUME_TASK_ID, (UNSIGNED) task_ptr,
                                        (UNSIGNED) 0, (UNSIGNED) 0);

#endif

    /* Save current protection.  */
    if (TCD_Current_Thread != NU_NULL)
    {
        save_protect = TCT_Get_Current_Protect();
    }
    else
    {
        save_protect = NU_NULL;
    }

    /* Protect system structures.  */
    TCT_Protect(&TCD_System_Protect);

    /* Call the actual resume task function.  If the function returns a
       NU_TRUE, context switching is needed.  */
    if (TCC_Resume_Task(task_ptr, NU_PURE_SUSPEND))
    {

        /* Transfer control back to the system for a context switch.  */
        TCT_Control_To_System();
    }

    /* Determine how to get out of protection.  */
    if (save_protect)
    {

        /* Restore current protection.  */
        TCT_Set_Current_Protect(save_protect);

        /* Release system protect.  */
        TCT_Unprotect_Specific(&TCD_System_Protect);
    }
    else

        /* Release protection of system structures.  */
        TCT_Unprotect();

    /* Return to user mode */
    NU_USER_MODE();

    /* Always return a successful status.  */
    return(NU_SUCCESS);
}




/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Suspend_Task                                                 */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function suspends the specified task.  If the specified     */
/*      task is the calling task, control is transferred back to the     */
/*      system.                                                          */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Other Components                                                 */
/*      TCC_Suspend_Service                 Task suspend service         */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      TCT_Control_To_System               Transfer control to system   */
/*      TCT_Protect                         Protect system structures    */
/*      TCT_Set_Execute_Task                Set TCD_Execute_Task pointer */
/*      TCT_Protect_Switch                  Allow protected task to run  */
/*                                            briefly                    */
/*      TCT_Unprotect                       Release system protection    */
/*      TMC_Start_Task_Timer                Start a task timer           */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      task_ptr                            Task control block pointer   */
/*      suspend_type                        Type of suspension to lift   */
/*      cleanup                             Cleanup routine              */
/*      information                         Information for cleanup      */
/*      timeout                             Timeout on the suspension    */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*        DATE                    REMARKS                                */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      02-01-1994      Corrected a suspension with                      */
/*                      timeout problem that caused                      */
/*                      unconditional task suspension                    */
/*                      for timeouts and sleeps for 1                    */
/*                      tick, resulting in version 1.0f                  */
/*      02-01-1994      Verified version 1.0f                            */
/*      03-01-1994      Modified function interface,                     */
/*                      added register optimizations,                    */
/*                      fixed a possible suspending an                   */
/*                      executing task from a HISR,                      */
/*                      removed excessive protection                     */
/*                      logic since protection is now                    */
/*                      in force upon function entry,                    */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*      06-01-1996      Checked to see whether                           */
/*                      task == TCD_Current_Thread                       */
/*                      regardless of whether task ==                    */
/*                      TCD_Execute_Task (SPR152)                        */
/*                                                                       */
/*************************************************************************/
VOID  TCC_Suspend_Task(NU_TASK *task_ptr, OPTION suspend_type,
                VOID (*cleanup) (VOID *), VOID *information, UNSIGNED timeout)
{

R1 TC_TCB      *task;                       /* Task control block ptr    */
R2 INT          index;                      /* Working index variable    */
DATA_ELEMENT    temp;                       /* Temporary variable        */



    /* Move input task pointer into internal pointer.  */
    task =  (TC_TCB *) task_ptr;


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif


    /* Determine if there is a timeout to initiate.  */
    if (timeout != NU_SUSPEND)
    {

        /* Indicate that a task timer is active.  */
        task -> tc_timer_active =  NU_TRUE;

        /* Start a timeout on the suspension.  */
        TMC_Start_Task_Timer(&(task -> tc_timer_control),timeout);
    }


    /* Check for a non self-suspension.  In such cases, the target task
       cannot have any type of protection in force.  */
    if (task != (TC_TCB *) TCD_Current_Thread)
    {

        do
        {

            /* Check for protection.  Remember that system protection is
               in effect.  */
            if (task -> tc_current_protect)
            {

                /* Yes, target task is in a protected mode.  Release
                   the protection on the scheduling list and transfer
                   control briefly to the target task.  */
                TCT_Unprotect();

                /* Switch to the protected task and wait until the
                   task is not protected.  */
                TCT_Protect_Switch(task);

                /* Restore protection of the system structures.  */
                TCT_Protect(&TCD_System_Protect);
            }
        } while (task -> tc_current_protect);
    }

    /* Check to see if the task is currently ready.  */
    if (task -> tc_status == NU_READY)
    {

        /* Mark the task with the appropriate suspension code.  */
        task -> tc_status =        suspend_type;

        /* Store off termination information in the tasks control block. */
        task -> tc_cleanup =       cleanup;
        task -> tc_cleanup_info =  information;

        /* Remove the task from the ready list.  */

        /* Determine if the task is the only one on the list.  */
        if (task -> tc_ready_next == task)
        {

            /* Only task on the list.  Clear the task's pointers and
               clear the entry in the priority table.  */
            task -> tc_ready_next =        NU_NULL;
            task -> tc_ready_previous =    NU_NULL;
            *(task -> tc_priority_head) =  NU_NULL;

            /* Clear the sub-priority group.  */
            *(task -> tc_sub_priority_ptr) =
                (*(task -> tc_sub_priority_ptr)) & ~(task -> tc_sub_priority);

            /* Determine if the main priority group needs to be cleared.
               This is only true if there are no other bits set in this
               sub-priority.  */
            if (*(task -> tc_sub_priority_ptr) == 0)

                /* Clear the main priority group bit.  */
                TCD_Priority_Groups =
                    TCD_Priority_Groups & ~(task -> tc_priority_group);

            /* Determine if this priority group was the highest in the
               system.  */
            if (task -> tc_priority == (DATA_ELEMENT) TCD_Highest_Priority)
            {

                /* Determine the highest priority task in the system.  */
                if (TCD_Priority_Groups == 0)
                {

                    /* Re-initialize the highest priority variable and
                       clear the current task pointer.  */
                    TCD_Highest_Priority =  TC_PRIORITIES;
                }
                else
                {

                    /* Find the next highest priority task.  */
                    if (TCD_Priority_Groups & TC_HIGHEST_MASK)

                        /* Base of sub-group is 0.  */
                       index =  0;

                    else if (TCD_Priority_Groups & TC_NEXT_HIGHEST_MASK)

                        /* Base of sub-group is 8.  */
                        index =  8;

                    else if (TCD_Priority_Groups & TC_NEXT_LOWEST_MASK)

                        /* Base of sub-group is 16.  */
                        index =  16;
                    else

                        /* Base of sub-group is 24.  */
                        index =  24;

                    /* Calculate the highest available priority.  */
                    index =  index + TCD_Lowest_Set_Bit[(INT)
                        ((TCD_Priority_Groups >> index) & TC_HIGHEST_MASK)];

                    /* Get the mask of the priority within the group of
                       8 priorities.  */
                    temp =  TCD_Sub_Priority_Groups[index];

                    /* Calculate the actual priority.  */
                    TCD_Highest_Priority =
                        (index << 3) + TCD_Lowest_Set_Bit[temp];
                }
            }
        }
        else
        {

            /* Not the only task ready at the same priority level.  */

            /* Remove from the linked-list.  */
            (task -> tc_ready_previous) -> tc_ready_next =
                                                 task -> tc_ready_next;
            (task -> tc_ready_next) -> tc_ready_previous =
                                                 task -> tc_ready_previous;

            /* See if the task being suspended is the current.  */
            if (*(task -> tc_priority_head) == task)

                /* Update the head of this priority list.  */
                *(task -> tc_priority_head) =  task -> tc_ready_next;

            /* Clear the task's pointers.  */
            task -> tc_ready_next =        NU_NULL;
            task -> tc_ready_previous =    NU_NULL;
        }

        /* Determine if this task the highest priority task.  */
        if (task == TCD_Execute_Task)
        {

            /* Determine the next task to execute.  */
            if (TCD_Highest_Priority < TC_PRIORITIES)

                /* Put the next task to execute in TCD_Execute_Task.  */
                TCT_Set_Execute_Task(TCD_Priority_List[TCD_Highest_Priority]);
            else

                /* No other task is ready for execution.  */
                TCT_Set_Execute_Task(NU_NULL);
        }

#ifdef INCLUDE_PROVIEW
        _RTProf_DumpTask(task,RT_PROF_SUSPEND_TASK);

        if (suspend_type == NU_SLEEP_SUSPEND)
        {
            _RTProf_TaskStatus(task,RT_TASK_SLEEPING);
        }
        else if (suspend_type == NU_PURE_SUSPEND)
        {
            _RTProf_TaskStatus(task,RT_TASK_SUSPENDED);
        }
        else
        {
            _RTProf_TaskStatus(task,RT_TASK_WAITING);
        }
#endif /*INCLUDE_PROVIEW*/

        /* See if the suspending task is the current thread. (SPR152) */
        if (task == (TC_TCB *) TCD_Current_Thread)

            /* Leave the task, transfer control to the system.  */
            TCT_Control_To_System();

    }
    else
    {

        /* Check for a pure suspension request.  If present, the delayed
           suspension flag is set.  */
        if (suspend_type == NU_PURE_SUSPEND)

            /* Setup the delayed suspension flag.  */
            task -> tc_delayed_suspend =  NU_TRUE;
#ifdef INCLUDE_PROVIEW
    _RTProf_DumpTask(task,RT_PROF_SUSPEND_TASK);
#endif /*INCLUDE_PROVIEW*/

    }
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Suspend_Service                                              */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function provides a suitable interface to the actual        */
/*      service to suspend a task.                                       */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      TCCE_Suspend_Service                Error checking function      */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      TCC_Suspend_Task                    Suspend a task               */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Protect                         Protect system structures    */
/*      TCT_Unprotect                       Release system structures    */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      task_ptr                            Task control block pointer   */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                          Always a successful status   */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*        DATE                    REMARKS                                */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified function interface,                     */
/*                      added register optimizations,                    */
/*                      added system protection logic,                   */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
STATUS  TCC_Suspend_Service(NU_TASK *task_ptr)
{

NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_SUSPEND_TASK_ID, (UNSIGNED) task_ptr,
                                        (UNSIGNED) 0, (UNSIGNED) 0);

#endif


    /* Protect system data structures.  */
    TCT_Protect(&TCD_System_Protect);

    /* Call the actual routine to suspend the task.  */
    TCC_Suspend_Task(task_ptr, NU_PURE_SUSPEND, NU_NULL, NU_NULL, NU_SUSPEND);

    /* Release system protection.  */
    TCT_Unprotect();

    /* Return to user mode */
    NU_USER_MODE();

    /* Always return a successful status.  */
    return(NU_SUCCESS);
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Task_Timeout                                                 */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function processes task suspension timeout conditions.      */
/*      Note that task sleep requests are also considered a timeout      */
/*      condition.  This routine must be called from Supervisor mode in  */
/*      a Supervisor/User mode switching kernel.                         */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      TMC_Timer_Task                      Timer expiration task        */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      Caller's cleanup function                                        */
/*      TCC_Resume_Task                     Resume a suspended task      */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Protect                         Protect scheduling list      */
/*      TCT_Set_Current_Protect             Setup current protection     */
/*      TCT_Unprotect                       Release protection           */
/*      TCT_Unprotect_Specific              Release specific protection  */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      task_ptr                            Task control block pointer   */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*        DATE                    REMARKS                                */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      02-01-1994      Added logic to clear the timer                   */
/*                      active flag when the target                      */
/*                      task is already in a ready                       */
/*                      state, resulting in                              */
/*                      version 1.0f                                     */
/*      02-01-1994      Verified version 1.0f                            */
/*      03-01-1994      Modified function interface,                     */
/*                      added register optimizations,                    */
/*                      removed logic for timeout                        */
/*                      before suspension because new                    */
/*                      protection logic eliminates                      */
/*                      the possibility,                                 */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
VOID  TCC_Task_Timeout(NU_TASK *task_ptr)
{

R1 TC_TCB       *task;                      /* Task control block ptr    */
TC_PROTECT      *suspend_protect;           /* Suspension protect ptr    */
DATA_ELEMENT     task_status;               /* Task status variable      */



    /* Move task control block pointer into internal pointer.  */
    task =  (TC_TCB *) task_ptr;


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

    /* Protect system data structures.  */
    TCT_Protect(&TCD_System_Protect);

    /* Pickup the suspension protection saved-off when the task was
       suspended.  */
    suspend_protect =  task -> tc_suspend_protect;

    /* Is a signal handler currently running? */
    if (task -> tc_signal_active)

        /* Use the saved status for current task status */
        task_status =      task -> tc_saved_status;
    else

        /* Just use the current task status */
        task_status =      task -> tc_status;

    /* Release protection of the scheduling list.  */
    TCT_Unprotect();

    /* Determine if there is a suspend protect.  */
    if (suspend_protect)

        /* Protect the suspended protection.  */
        TCT_Protect(suspend_protect);

    /* Now protect the system structures again.  Note that the order the
       protections are made prevents deadlocks.  */
    TCT_Protect(&TCD_System_Protect);

    /* Determine if the task is still suspended in the same manner.  */
    if ((task -> tc_status == task_status) ||
      ((task -> tc_signal_active) && (task -> tc_saved_status == task_status)))
    {

        /* Make sure that this timeout processing is still valid. */
        if ((task -> tc_timer_active) &&
                 (task -> tc_timer_control.tm_remaining_time == 0))
        {

            /* Clear the timer active flag.  */
            task -> tc_timer_active =  NU_FALSE;

            /* Call the cleanup function, if there is one.  */
            if (task -> tc_cleanup)

                /* Call cleanup function.  */
                (*(task -> tc_cleanup)) (task -> tc_cleanup_info);

            /* Resume the task.  */
            TCC_Resume_Task(task_ptr, task_status);
        }
    }

    /* Determine if a suspend protection was in force.  */
    if (suspend_protect)
    {

        /* Set the current protection to the suspend protect.  */
        TCT_Set_Current_Protect(suspend_protect);
        TCT_Unprotect_Specific(&TCD_System_Protect);
    }

    /* Release current protection.  */
    TCT_Unprotect();
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Task_Sleep                                                   */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function provides task sleep suspensions.  Its primary      */
/*      purpose is to interface with the actual task suspension function.*/
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      TCC_Suspend_Task                    Suspend a task               */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Protect                         Protect system structures    */
/*      TCT_Unprotect                       Release system structures    */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      ticks                               Number of timer ticks        */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*        DATE                    REMARKS                                */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified call to suspend the                     */
/*                      calling task, resulting in                       */
/*                      version 1.1                                      */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
VOID  TCC_Task_Sleep(UNSIGNED ticks)
{

NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_SLEEP_ID, (UNSIGNED) ticks,
                                        (UNSIGNED) 0, (UNSIGNED) 0);

#endif


    /* Protect system data structures.  */
    TCT_Protect(&TCD_System_Protect);

#ifdef INCLUDE_PROVIEW
    _RTProf_DumpTask((TC_TCB *)TCD_Current_Thread,RT_PROF_SLEEP);
#endif /*INCLUDE_PROVIEW*/

    /* Call the actual routine to suspend the task.  */
    TCC_Suspend_Task((NU_TASK *) TCD_Current_Thread, NU_SLEEP_SUSPEND,
                                                NU_NULL, NU_NULL, ticks);

    /* Release system protection.  */
    TCT_Unprotect();

    /* Return to user mode */
    NU_USER_MODE();
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Relinquish                                                   */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function moves the calling task to the end of other tasks   */
/*      at the same priority level.  The calling task does not execute   */
/*      again until all the other tasks of the same priority get a       */
/*      chance to execute.                                               */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      TCCE_Relinquish                     Error checking shell         */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Control_To_System               Transfer control to system   */
/*      TCT_Protect                         Protect system structures    */
/*      TCT_Set_Execute_Task                Set TCD_Execute_Task pointer */
/*      TCT_Unprotect                       Release protection           */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*        DATE                    REMARKS                                */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified protection logic,                       */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
VOID  TCC_Relinquish(VOID)
{

TC_TCB         *task;                       /* Pointer to task           */
NU_SUPERV_USER_VARIABLES

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_RELINQUISH_ID, (UNSIGNED) 0,
                                        (UNSIGNED) 0, (UNSIGNED) 0);

#endif

    /* Protect against multiple access to the system structures.  */
    TCT_Protect(&TCD_System_Protect);

    /* Pickup the current thread and place it in the task pointer.  */
    task =  (TC_TCB *) TCD_Current_Thread;

#ifdef INCLUDE_PROVIEW
    _RTProf_DumpTask(task,RT_PROF_RELINQUISH);
#endif /*INCLUDE_PROVIEW*/
     
    /* Determine if another task is ready to run.  */
    if ((task -> tc_ready_next != task) ||
        (task -> tc_priority != (DATA_ELEMENT) TCD_Highest_Priority))
    {

        /* Move the executing task to the end of tasks having the same
           priority. */
        *(task -> tc_priority_head) =  task -> tc_ready_next;

        /* Setup the next task to execute.  */
        TCT_Set_Execute_Task(TCD_Priority_List[TCD_Highest_Priority]);

        /* Transfer control back to the system.  */
        TCT_Control_To_System();
    }

    /* Release protection of system structures.  */
    TCT_Unprotect();

    /* Return to user mode */
    NU_USER_MODE();
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Time_Slice                                                   */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function moves the specified task to the end of the other   */
/*      tasks at the same priority level.  If the specified task is no   */
/*      longer ready, this request is ignored.  This routine must be     */
/*      called from Supervisor mode in a Supervisor/User mode            */
/*      switching kernel.                                                */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      TMC_Timer_HISR                      Time-slice interrupt         */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Protect                         Protect the scheduling data  */
/*      TCT_Set_Execute_Task                Set TCD_Execute_Task pointer */
/*      TCT_Unprotect                       Release protection           */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      task                                Task control block pointer   */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified function interface,                     */
/*                      added register optimizations,                    */
/*                      slightly modified protection                     */
/*                      logic, resulting in version 1.1                  */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
VOID  TCC_Time_Slice(NU_TASK *task_ptr)
{

R1 TC_TCB      *task;                       /* Task control block ptr    */


    /* Move input task control block pointer into internal pointer.  */
    task =  (TC_TCB *) task_ptr;


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

    /* Protect against multiple access to the system structures.  */
    TCT_Protect(&TCD_System_Protect);

    /* Determine if another task is ready to run.  */
    if (((task -> tc_status == NU_READY) && (task -> tc_preemption)) &&
        ((task -> tc_ready_next != task) ||
         (task -> tc_priority != (DATA_ELEMENT) TCD_Highest_Priority)))
    {

        /* Move the executing task to the end of tasks having the same
           priority. */
        *(task -> tc_priority_head) =  task -> tc_ready_next;

        /* Setup the next task to execute.  */
        TCT_Set_Execute_Task(TCD_Priority_List[TCD_Highest_Priority]);

    }

    /* Release protection of the system structures.  */
    TCT_Unprotect();
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Current_Task_Pointer                                         */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function returns the pointer of the currently executing     */
/*      task.  If the current thread is not a task thread, a NU_NULL     */
/*      is returned.                                                     */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      Other Components                                                 */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      Task Pointer                        Active tasks pointer or      */
/*                                            NU_NULL if not a task      */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified function interface,                     */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
NU_TASK  *TCC_Current_Task_Pointer(VOID)
{


    /* Determine if a task thread is executing.  */
    if ((TCD_Current_Thread) &&
        (((TC_TCB *) TCD_Current_Thread) -> tc_id == TC_TASK_ID))

        /* Task thread is running, return the pointer.  */
        return((NU_TASK *) TCD_Current_Thread);
    else

        /* No, task thread is not running, return a NU_NULL.  */
        return(NU_NULL);
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Current_HISR_Pointer                                         */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function returns the pointer of the currently executing     */
/*      HISR.  If the current thread is not a HISR thread, a NU_NULL     */
/*      is returned.                                                     */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*      Other Components                                                 */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      HISR Pointer                        Active HISR pointer or       */
/*                                            NU_NULL if not a HISR      */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Modified function interface,                     */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
NU_HISR  *TCC_Current_HISR_Pointer(VOID)
{


    /* Determine if a HISR thread is executing.  */
    if ((TCD_Current_Thread) &&
        (((TC_HCB *) TCD_Current_Thread) -> tc_id == TC_HISR_ID))

        /* HISR thread is running, return the pointer.  */
        return((NU_HISR *) TCD_Current_Thread);
    else

        /* No, HISR thread is not running, return a NU_NULL.  */
        return(NU_NULL);
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Task_Shell                                                   */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function is shell from which all application tasks are      */
/*      initially executed.  The shell causes the task to finish when    */
/*      control is returned from the application task.  Also, the shell  */
/*      passes argc and argv arguments to the task's entry function.     */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      TCC_Control_To_Task                 Control to task routine      */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      Task Entry Function                                              */
/*      TCC_Suspend_Task                    Suspend task when finished   */
/*      TCT_Protect                         Protect system structures    */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*        DATE                    REMARKS                                */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Added protection logic prior to                  */
/*                      suspending the task, resulting                   */
/*                      in version 1.1                                   */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
VOID  TCC_Task_Shell(VOID)
{
NU_SUPERV_USER_VARIABLES

    /* Call the task's entry function with the argc and argv parameters
       supplied during task creation or reset.  */
    (*(TCD_Execute_Task -> tc_entry)) (TCD_Execute_Task -> tc_argc,
                                       TCD_Execute_Task -> tc_argv);

    /* Switch to supervisor mode */
    NU_SUPERVISOR_MODE();

    /* Protect system data structures.  */
    TCT_Protect(&TCD_System_Protect);

    /* If the task returns, suspend it in a finished state.  Note that
       the task cannot execute again until it is reset.  Therefore, this
       call never returns.  */
    TCC_Suspend_Task((NU_TASK *) TCD_Execute_Task, NU_FINISHED,
                                NU_NULL, NU_NULL, NU_SUSPEND);

    /* Return to user mode */
    NU_USER_MODE();
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Signal_Shell                                                 */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function processes signals by calling the task supplied     */
/*      signal handling function.  When signal handling is completed,    */
/*      the task is placed in the appropriate state.                     */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      TCC_Control_Signals                 Control task's signals       */
/*      TCC_Register_Signal_Handler         Register a signal handler    */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      task's signal handling routine                                   */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Signal_Exit                     Signal handling exit routine */
/*      TCT_Protect                         Protect against other access */
/*      TCT_Set_Execute_Task                Set TCD_Execute_Task pointer */
/*      TCT_Unprotect                       Release protection           */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*         DATE                    REMARKS                               */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Added register optimizations,                    */
/*                      modified protection logic,                       */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
VOID  TCC_Signal_Shell(VOID)
{

R2 UNSIGNED     signals;                    /* Signals to send to task   */
INT             index;                      /* Working index variable    */
DATA_ELEMENT    temp;                       /* Temporary variable        */
R1 TC_TCB      *task;                       /* Task pointer              */


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

    /* Point at the current task.  */
    task =  (TC_TCB *) TCD_Current_Thread;

    /* Protect against simultaneous access.  */
    TCT_Protect(&TCD_System_Protect);

    /* Process while there are signals to handle.  */
    while (task -> tc_signals & task -> tc_enabled_signals)
    {

        /* Pickup the signals and clear them.  */
        signals =  task -> tc_signals;
        task -> tc_signals =  0;

        /* Release protection.  */
        TCT_Unprotect();

        /* Call the application signal handling function, if there still is
           one.  */
        if (task -> tc_signal_handler)
        {
            NU_SUPERV_USER_VARIABLES

#if (defined(NU_SUPERV_USER_MODE)) && (NU_SUPERV_USER_MODE > 0)
            UNSIGNED savedMode = task->tc_su_mode;
            task->tc_su_mode = 1;         /* Force transition to User mode */
#endif
            /* Switch to user mode */
            NU_USER_MODE();

            /* Call signal handler.  (always in User mode) */
            (*(task -> tc_signal_handler))(signals);

            /* Return to supervisor mode */
            NU_SUPERVISOR_MODE();

#if (defined(NU_SUPERV_USER_MODE)) && (NU_SUPERV_USER_MODE > 0)
            task->tc_su_mode = savedMode;   /* Restore original nesting count */
#endif
        }

        /* Protect against simultaneous access again.  */
        TCT_Protect(&TCD_System_Protect);
    }

    /* At this point, signals have been exhausted and protection is in
       force.  */

    /* Clear the signal in process flag.  */
    task -> tc_signal_active =  NU_FALSE;

    /* Determine how the signal handler was called.  Either in a solicited or
       an unsolicited manner.  */
    if (task -> tc_saved_stack_ptr)
    {

        /* Determine if the saved status still indicates that the task should
           be suspended.  */
        if (task -> tc_saved_status != NU_READY)
        {

            /* Suspend the task.  */
            task -> tc_status =  task -> tc_saved_status;

            /* Remove the task from the ready list.  */

            /* Determine if the task is the only one on the list.  */
            if (task -> tc_ready_next == task)
            {

                /* Only task on the list.  Clear the task's pointers and
                   clear the entry in the priority table.  */
                task -> tc_ready_next =        NU_NULL;
                task -> tc_ready_previous =    NU_NULL;
                *(task -> tc_priority_head) =  NU_NULL;

                /* Clear the sub-priority group.  */
                *(task -> tc_sub_priority_ptr) =
                 (*(task -> tc_sub_priority_ptr)) & ~(task -> tc_sub_priority);

                /* Determine if the main priority group needs to be cleared.
                   This is only true if there are no other bits set in this
                   sub-priority.  */
                if (*(task -> tc_sub_priority_ptr) == 0)

                /* Clear the main priority group bit.  */
                TCD_Priority_Groups =
                    TCD_Priority_Groups & ~(task -> tc_priority_group);

                /* Determine if this priority group was the highest in the
                   system.  */
                if (task -> tc_priority == (DATA_ELEMENT) TCD_Highest_Priority)
                {

                    /* Determine the highest priority task in the system.  */
                    if (TCD_Priority_Groups == 0)
                    {

                        /* Re-initialize the highest priority variable and
                           clear the current task pointer.  */
                        TCD_Highest_Priority =  TC_PRIORITIES;
                    }
                    else
                    {

                        /* Find the next highest priority task.  */
                        if (TCD_Priority_Groups & TC_HIGHEST_MASK)

                            /* Base of sub-group is 0.  */
                            index =  0;

                        else if (TCD_Priority_Groups & TC_NEXT_HIGHEST_MASK)

                            /* Base of sub-group is 8.  */
                            index =  8;

                        else if (TCD_Priority_Groups & TC_NEXT_LOWEST_MASK)

                            /* Base of sub-group is 16.  */
                            index =  16;
                        else

                            /* Base of sub-group is 24.  */
                            index =  24;

                        /* Calculate the highest available priority.  */
                        index =  index + TCD_Lowest_Set_Bit[(INT)
                           ((TCD_Priority_Groups >> index) & TC_HIGHEST_MASK)];

                        /* Get the mask of the priority within the group of
                           8 priorities.  */
                        temp =  TCD_Sub_Priority_Groups[index];

                        /* Calculate the actual priority.  */
                        TCD_Highest_Priority =
                            (index << 3) + TCD_Lowest_Set_Bit[temp];
                    }
                }
            }
            else
            {

                /* Not the only task ready at the same priority level.  */

                /* Remove from the linked-list.  */
                (task -> tc_ready_previous) -> tc_ready_next =
                                                 task -> tc_ready_next;
                (task -> tc_ready_next) -> tc_ready_previous =
                                                 task -> tc_ready_previous;

                /* See if the task being suspended is the current.  */
                if (*(task -> tc_priority_head) == task)

                    /* Update the head of this priority list.  */
                    *(task -> tc_priority_head) =  task -> tc_ready_next;

                /* Clear the task's pointers.  */
                task -> tc_ready_next =        NU_NULL;
                task -> tc_ready_previous =    NU_NULL;
            }

            /* Determine the next task to execute.  */
            if (TCD_Highest_Priority < TC_PRIORITIES)

                /* Put the next task to execute in TCD_Execute_Task.  */
                TCT_Set_Execute_Task(TCD_Priority_List[TCD_Highest_Priority]);
            else

                /* No other task is ready for execution.  */
                TCT_Set_Execute_Task(NU_NULL);
        }

        /* At this point, just exit back to the system.  Note that the
           signal exit routine clears the scheduling protection.  */
        TCT_Signal_Exit();
    }

    /* A signal handler was called from the current task.  Nothing needs
       to be done except to release protection.  */
    TCT_Unprotect();
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Dispatch_LISR                                                */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function dispatches the LISR associated with the specified  */
/*      interrupt vector.  Note that this function is called during      */
/*      the interrupt thread.  This routine must be called from          */
/*      Supervisor mode in a Supervisor/User mode switching kernel.      */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      INT_Interrupt_Shell                 Shell of interrupt routine   */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      application LISR                                                 */
/*      ERC_System_Error                    Unhandled interrupt error    */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      vector                              Vector number of interrupt   */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      None                                                             */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*        DATE                    REMARKS                                */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      11-01-1993      Added logic to save unhandled                    */
/*                      interrupt vector number in                       */
/*                      a global variable, resulting                     */
/*                      in version 1.0e                                  */
/*      11-01-1993      Verified version 1.0e                            */
/*                                                                       */
/*************************************************************************/
VOID  TCC_Dispatch_LISR(INT vector)
{

INT             index;                      /* Working index variable    */


    /* Determine if the specified vector has an LISR registered to it.  */
    index =  (INT)  TCD_Registered_LISRs[vector];
    if (index <= NU_MAX_LISRS)
    {
#ifdef INCLUDE_PROVIEW
        _RTProf_Dispatch_LISR_No_INT_Lock(vector);
#endif /*INCLUDE_PROVIEW*/

        /* Yes, an LISR is associated with this vector.  Call the actual
           registered LISR routine.  */
        (*(TCD_LISR_Pointers[index])) (vector);
    }
    else
    {

        /* Save interrupt vector number in TCD_Unhandled_Interrupt.  */
        TCD_Unhandled_Interrupt =  vector;

        /* System error, unhandled interrupt.  */
        ERC_System_Error(NU_UNHANDLED_INTERRUPT);
    }
}


/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      TCC_Register_LISR                                                */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*      This function registers the supplied LISR with the supplied      */
/*      vector number.  If the supplied LISR is NU_NULL, the supplied    */
/*      vector is de-registered.  The previously registered LISR is      */
/*      returned to the caller, along with the completion status.  This  */
/*      routine must be called from Supervisor mode in a Supervisor/     */
/*      User mode switching kernel.                                      */
/*                                                                       */
/* CALLED BY                                                             */
/*                                                                       */
/*      Application                                                      */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      [HIC_Make_History_Entry]            Make entry in history log    */
/*      INT_Retrieve_Shell                  Retrieve vector shell pointer*/
/*      INT_Setup_Vector                    Setup the actual vector      */
/*      INT_Vectors_Loaded                  Determine if interrupt shell */
/*                                            routines are loaded        */
/*      [TCT_Check_Stack]                   Stack checking function      */
/*      TCT_Protect                         Protect LISR registration    */
/*      TCT_Unprotect                       Release LISR protection      */
/*                                                                       */
/* INPUTS                                                                */
/*                                                                       */
/*      vector                              Vector number of interrupt   */
/*      new_lisr                            New LISR function            */
/*      old_lisr                            Previous LISR function ptr   */
/*                                                                       */
/* OUTPUTS                                                               */
/*                                                                       */
/*      NU_SUCCESS                          Successful registration      */
/*      NU_INVALID_VECTOR                   Invalid interrupt vector     */
/*      NU_NO_MORE_LISRS                    LISR registration table is   */
/*                                            full                       */
/*      NU_NOT_REGISTERED                   LISR was not registered      */
/*                                                                       */
/* HISTORY                                                               */
/*                                                                       */
/*        DATE                    REMARKS                                */
/*                                                                       */
/*      03-01-1993      Created initial version 1.0                      */
/*      04-19-1993      Verified version 1.0                             */
/*      03-01-1994      Added appropriate casting,                       */
/*                      resulting in version 1.1                         */
/*                                                                       */
/*      03-18-1994      Verified version 1.1                             */
/*                                                                       */
/*************************************************************************/
STATUS  TCC_Register_LISR(INT vector, VOID (*new_lisr)(INT),
                                        VOID (**old_lisr)(INT))
{

INT             index;                      /* Working index variable    */
STATUS          status;                     /* Completion status         */


#ifdef  NU_ENABLE_STACK_CHECK

    /* Call stack checking function to check for an overflow condition.  */
    TCT_Check_Stack();

#endif

#ifdef  NU_ENABLE_HISTORY

    /* Make an entry that corresponds to this function in the system history
       log.  */
    HIC_Make_History_Entry(NU_REGISTER_LISR_ID, (UNSIGNED) vector,
                                (UNSIGNED) new_lisr, (UNSIGNED) old_lisr);

#endif

    /* Determine if the vector is legal. */
    if (vector > NU_MAX_VECTORS)
        return(NU_INVALID_VECTOR);

    /* Initialize the completion status to successful.  */
    status =  NU_SUCCESS;

    /* Protect against LISR registration list access.  */
    TCT_Protect(&TCD_LISR_Protect);

    /* Determine if a registration or deregistration is requested.  This is
       determined by the value of new_lisr.  A NULL value indicates
       deregistration.  */
    if (new_lisr)
    {

        /* Register the new LISR.  */

        /* Determine if the vector already has a registration.  */
        if (TCD_Registered_LISRs[vector])
        {

            /* Yes, a registration exists.  */

            /* Pickup the index into the LISR pointer list.  */
            index =  (INT) TCD_Registered_LISRs[vector];

            /* Temporarily indicate that the LISR is not registered.  */
            TCD_Registered_LISRs[vector] =  0;

            /* Copy the currently registered LISR into the old_lisr return
               area.  */
            *old_lisr =  TCD_LISR_Pointers[index];

            /* Place the new LISR into the list. */
            TCD_LISR_Pointers[index] =  new_lisr;

            /* Indicate the LISR is registered again.  */
            TCD_Registered_LISRs[vector] =  (UNSIGNED_CHAR) index;
        }
        else
        {

            /* An empty slot needs to be found in the LISR pointers list.  */

            index =  0;
            while ((index <= NU_MAX_LISRS) && 
                   (TCD_LISR_Pointers[index] != NU_NULL))
                      index++;

            /* Determine if an empty slot was found.  */
            if (index <= NU_MAX_LISRS)
            {

                /* Yes, an empty slot was found.  */

                /* Place the new LISR in the LISR pointers list.  */
                TCD_LISR_Pointers[index] =  new_lisr;

                /* Associate the index into the pointers list to the actual
                   vector.  */
                TCD_Registered_LISRs[vector] =  (UNSIGNED_CHAR) index;

                /* Indicate that there was no previous LISR registered.  */
                *old_lisr =  NU_NULL;

                /* Determine if the actual vector needs to be stolen.  */
                if (!INT_Vectors_Loaded())

                    /* Actual vector needs to be replaced with the
                       appropriate ISR shell.  */
                    INT_Setup_Vector(vector, INT_Retrieve_Shell(vector));
            }
            else

                /* Return the completion status that indicates that there
                   is no more room in the LISR pointers list.  */
                status =  NU_NO_MORE_LISRS;
        }
    }
    else
    {

        /* De-register the specified vector.  */

        /* Determine if the vector has a registration current.  */
        if (TCD_Registered_LISRs[vector])
        {

            /* Pickup the index into the LISR pointer list.  */
            index =  (INT) TCD_Registered_LISRs[vector];

            /* Clear the registration table.  */
            TCD_Registered_LISRs[vector] =  0;

            /* Return the previously registered LISR.  */
            *old_lisr =  TCD_LISR_Pointers[index];

            /* Clear the LISR pointer list entry.  */
            TCD_LISR_Pointers[index] =  NU_NULL;
        }
        else

            /* The vector is not registered.  Return an error completion
               status.  */
            status =  NU_NOT_REGISTERED;
    }

#ifdef INCLUDE_PROVIEW
    _RTProf_RegisterLisr(vector);
#endif /*INCLUDE_PROVIEW*/

    /* Release protection on the LISR registration list.  */
    TCT_Unprotect();

    /* Return the completion status.  */
    return(status);
}