view src/nucleus/tcc.c @ 301:4bb5772a05a3

AT%SPVER: new command for setting custom speech version lists The speech version list in the Bearer Capability IE tells the network which speech codecs are supported by the MS, and in which order of preference. The standard behaviour is to list all codecs that are supported by the hw+fw platform, and the standard preference order is newer over older, FR over HR. But sometimes it is desirable (for network testing) to artificially restrict which codecs the test MS will declare as supported, and/or to list them in some peculiar non-standard order of preference. Add a new private AT command, AT%SPVER, allowing the user to set and clear custom speech version lists for the Bearer Capability IE composer in CC.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 21 May 2023 21:43:10 +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);
}