diff src/nucleus/tcs.c @ 0:92470e5d0b9e

src: partial import from FC Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 15 May 2020 01:28:16 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/nucleus/tcs.c	Fri May 15 01:28:16 2020 +0000
@@ -0,0 +1,1154 @@
+/*************************************************************************/
+/*                                                                       */
+/*               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       */
+/*                                                                       */
+/*      tcs.c                                          Nucleus PLUS 1.14 */
+/*                                                                       */
+/* COMPONENT                                                             */
+/*                                                                       */
+/*      TC - Thread Control                                              */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This file contains supplemental routines for the Thread Control  */
+/*      component.                                                       */
+/*                                                                       */
+/* DATA STRUCTURES                                                       */
+/*                                                                       */
+/*      None                                                             */
+/*                                                                       */
+/* FUNCTIONS                                                             */
+/*                                                                       */
+/*      TCS_Change_Priority                 Change task's priority       */
+/*      TCS_Change_Preemption               Change task's preemption     */
+/*      TCS_Change_Time_Slice               Change task's time-slice     */
+/*      TCS_Control_Signals                 Control signals              */
+/*      TCS_Receive_Signals                 Receive signals              */
+/*      TCS_Register_Signal_Handler         Register signal handler      */
+/*      TCS_Send_Signals                    Send signals to a task       */
+/*                                                                       */
+/*                                                                       */
+/* 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-1994      Created initial version 1.1 from                 */
+/*                      previous version of TCC.C                        */
+/*                                                                       */
+/*      03-18-1994      Verified version 1.1                             */
+/*      04-04-1996      Modified TCS_Send_Signals,                       */
+/*                      resulting in version 1.1+                        */
+/*                      (spr 107)                                        */
+/*      04-17-1996      updated to version 1.2                           */
+/*      03-24-1998      Released version 1.3.                            */
+/*      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        "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"                /* ProView interface         */
+
+
+/* Define external inner-component global data references.  */
+
+extern CS_NODE         *TCD_Created_Tasks_List;
+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 TC_PROTECT       TCD_System_Protect;
+extern INT              TMD_Time_Slice_State;
+
+
+
+/* Define external inner-component function calls that are not available to
+   other components.  */
+
+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);
+
+
+/*************************************************************************/
+/*                                                                       */
+/* FUNCTION                                                              */
+/*                                                                       */
+/*      TCS_Change_Priority                                              */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This function changes the priority of the specified task.  The   */
+/*      priority of a suspended or a ready task can be changed.  If the  */
+/*      new priority necessitates a context switch, control is           */
+/*      transferred back to the system.                                  */
+/*                                                                       */
+/* CALLED BY                                                             */
+/*                                                                       */
+/*      Application                                                      */
+/*      TCSE_Change_Priority                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 scheduling data      */
+/*      TCT_Set_Execute_Task                Set TCD_Execute_Task pointer */
+/*      TCT_Unprotect                       Release protection of data   */
+/*                                                                       */
+/* INPUTS                                                                */
+/*                                                                       */
+/*      task_ptr                            Task control block pointer   */
+/*      new_priority                        New priority for task        */
+/*                                                                       */
+/* OUTPUTS                                                               */
+/*                                                                       */
+/*      old_priority                        Original task priority       */
+/*                                                                       */
+/* 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,                    */
+/*                      modified protection logic,                       */
+/*                      resulting in version 1.1                         */
+/*                                                                       */
+/*      03-18-1994      Verified version 1.1                             */
+/*                                                                       */
+/*      10-4-1999       Bug fixes - return if new                        */
+/*                      priority equals old priority                     */
+/*                      and don't move the head pointer                  */
+/*                      unless the head node is changing                 */
+/*************************************************************************/
+OPTION   TCS_Change_Priority(NU_TASK *task_ptr, OPTION new_priority)
+{
+
+R1 TC_TCB      *task;                       /* Task control block ptr    */
+R2 TC_TCB      *head;                       /* Head list pointer         */
+R3 INT          index;                      /* Working index variable    */
+OPTION          old_priority;               /* Previous priority of task */
+DATA_ELEMENT    temp;                       /* Temporary variable        */
+NU_SUPERV_USER_VARIABLES
+
+    /* Switch to supervisor mode */
+    NU_SUPERVISOR_MODE();
+
+    /* 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
+
+#ifdef  NU_ENABLE_HISTORY
+
+    /* Make an entry that corresponds to this function in the system history
+       log.  */
+    HIC_Make_History_Entry(NU_CHANGE_PRIORITY_ID, (UNSIGNED) task,
+                                        (UNSIGNED) new_priority, (UNSIGNED) 0);
+
+#endif
+
+    /* Protect against multiple access to the scheduling list.  */
+    TCT_Protect(&TCD_System_Protect);
+
+    /* Save the old priority of the task.  */
+    old_priority =  task -> tc_priority;
+
+
+    /* BUG FIX  this should probably go into an error checking routine instead of here  */
+    if (!(task -> tc_priority == new_priority))
+    {
+
+
+       /* Check to see if the task is currently ready.  */
+       if (task -> tc_status == NU_READY)
+       {
+
+           /* 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);
+           }
+           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;
+
+
+
+               /* Update the head pointer.  */
+               /* BUG FIX - update head if head is changing priority - leave
+                  it alone otherwise! */
+               if(*(task -> tc_priority_head) ==  task )
+               *(task -> tc_priority_head) =  task -> tc_ready_next;
+
+               /* Clear the next and previous pointers.  */
+               task -> tc_ready_next =        NU_NULL;
+               task -> tc_ready_previous =    NU_NULL;
+           }
+
+           /* Now add in the task at the new priority.  */
+           task -> tc_priority =  new_priority;
+
+           /* Build the other priority information.  */
+           task -> tc_priority =      new_priority;
+           task -> tc_priority_head = &(TCD_Priority_List[new_priority]);
+           task -> tc_sub_priority =  (DATA_ELEMENT) (1 << (new_priority & 7));
+           task -> tc_priority_group =   ((UNSIGNED) 1) << (new_priority >> 3);
+           task -> tc_sub_priority_ptr =
+                   &(TCD_Sub_Priority_Groups[(new_priority >> 3)]);
+
+#ifdef INCLUDE_PROVIEW
+        _RTProf_DumpTask(task,RT_PROF_CHANGE_PRIORITY);
+#endif
+           /* Link the task into the new priority list.  */
+           head =  *(task -> tc_priority_head);
+
+           /* Determine if the list is non-empty.  */
+           if (head)
+           {
+
+               /* Add the 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 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 the highest priority task in the system.  */
+           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];
+
+           /* Check for preemption.  */
+           if ((TCD_Highest_Priority <= ((INT) TCD_Execute_Task -> tc_priority))
+               && (TCD_Execute_Task -> tc_preemption))
+           {
+
+               /* Update the current task pointer.  */
+               TCT_Set_Execute_Task(TCD_Priority_List[TCD_Highest_Priority]);
+
+               /* 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))
+
+                   /* Transfer control to the system.  */
+                   TCT_Control_To_System();
+           }
+       }
+       else
+       {
+
+           /* Just modify the priority.  */
+           task -> tc_priority =  new_priority;
+
+           /* Build the other priority information.  */
+           task -> tc_priority =      new_priority;
+           task -> tc_priority_head = &(TCD_Priority_List[new_priority]);
+           task -> tc_sub_priority =  (DATA_ELEMENT) (1 << (new_priority & 7));
+           task -> tc_priority_group =   ((UNSIGNED) 1) << (new_priority >> 3);
+           task -> tc_sub_priority_ptr =
+                   &(TCD_Sub_Priority_Groups[(new_priority >> 3)]);
+       }
+#ifdef INCLUDE_PROVIEW
+        _RTProf_DumpTask(task,RT_PROF_CHANGE_PRIORITY);
+#endif
+    }
+
+    /* Release the protection of the scheduling list.  */
+    TCT_Unprotect();
+
+    /* Return to user mode */
+    NU_USER_MODE();
+
+    /* Return the old priority.  */
+    return(old_priority);
+}
+
+
+/*************************************************************************/
+/*                                                                       */
+/* FUNCTION                                                              */
+/*                                                                       */
+/*      TCS_Change_Preemption                                            */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This function changes the preemption posture of the calling      */
+/*      task.  Preemption for a task may be enabled or disabled.  If     */
+/*      it is disabled, the task runs until it suspends or relinquishes. */
+/*      If a preemption is pending, a call to this function to enable    */
+/*      preemption causes a context switch.                              */
+/*                                                                       */
+/* CALLED BY                                                             */
+/*                                                                       */
+/*      Application                                                      */
+/*      TCSE_Change_Preemption              Error checking function      */
+/*                                                                       */
+/* 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 scheduling info      */
+/*      TCT_Set_Execute_Task                Set TCD_Execute_Task pointer */
+/*      TCT_Unprotect                       Release protection of info   */
+/*                                                                       */
+/* INPUTS                                                                */
+/*                                                                       */
+/*      preempt                             Preempt selection parameter  */
+/*                                                                       */
+/* OUTPUTS                                                               */
+/*                                                                       */
+/*      old_preempt                         Original preempt value       */
+/*                                                                       */
+/* 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                             */
+/*                                                                       */
+/*************************************************************************/
+OPTION   TCS_Change_Preemption(OPTION preempt)
+{
+
+TC_TCB         *task;                       /* Pointer to task           */
+OPTION          old_preempt;
+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_CHANGE_PREEMPTION_ID, (UNSIGNED) preempt,
+                                        (UNSIGNED) 0, (UNSIGNED) 0);
+
+#endif
+
+    /* Protect the scheduling information.  */
+    TCT_Protect(&TCD_System_Protect);
+
+    /* Pickup the current thread and place it in the task pointer.  */
+    task =  (TC_TCB *) TCD_Current_Thread;
+
+    /* Save the old preempt value.  */
+    if (task -> tc_preemption)
+
+        /* Previously enabled.  */
+        old_preempt =  NU_PREEMPT;
+    else
+
+        /* Previously disabled.  */
+        old_preempt =  NU_NO_PREEMPT;
+
+    /* Process the new value.  */
+    if (preempt == NU_NO_PREEMPT)
+
+        /* Disable preemption.  */
+        TCD_Execute_Task -> tc_preemption =  NU_FALSE;
+    else
+    {
+
+        /* Enable preemption.  */
+        task -> tc_preemption =  NU_TRUE;
+
+        /* Check for a preemption condition.  */
+        if ((task == TCD_Execute_Task) &&
+            (TCD_Highest_Priority < ((INT) TCD_Execute_Task -> tc_priority)))
+        {
+
+            /* Preempt the current task.  */
+            TCT_Set_Execute_Task(TCD_Priority_List[TCD_Highest_Priority]);
+
+            /* Transfer control to the system.  */
+            TCT_Control_To_System();
+        }
+    }
+
+#ifdef INCLUDE_PROVIEW
+    _RTProf_DumpTask(task,RT_PROF_CHANGE_PREEMPTION);
+#endif
+
+    /* Release protection of information.  */
+    TCT_Unprotect();
+
+    /* Return to user mode */
+    NU_USER_MODE();
+
+    /* Return the previous preemption posture.  */
+    return(old_preempt);
+}
+
+
+/*************************************************************************/
+/*                                                                       */
+/* FUNCTION                                                              */
+/*                                                                       */
+/*      TCS_Change_Time_Slice                                            */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This function changes the time slice of the specified task.  A   */
+/*      time slice value of 0 disables time slicing.                     */
+/*                                                                       */
+/* CALLED BY                                                             */
+/*                                                                       */
+/*      Application                                                      */
+/*      TCES_Change_Preemption              Error checking function      */
+/*                                                                       */
+/* CALLS                                                                 */
+/*                                                                       */
+/*      [HIC_Make_History_Entry]            Make entry in history log    */
+/*      [TCT_Check_Stack]                   Stack checking function      */
+/*      TCT_Protect                         Protect scheduling info      */
+/*      TCT_Unprotect                       Release protection of info   */
+/*                                                                       */
+/* INPUTS                                                                */
+/*                                                                       */
+/*      task_ptr                            Task control block pointer   */
+/*      time_slice                          New time slice value         */
+/*                                                                       */
+/* OUTPUTS                                                               */
+/*                                                                       */
+/*      old_time_slice                      Original time slice value    */
+/*                                                                       */
+/* 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,                    */
+/*                      modified protection logic,                       */
+/*                      resulting in version 1.1                         */
+/*                                                                       */
+/*      03-18-1994      Verified version 1.1                             */
+/*                                                                       */
+/*************************************************************************/
+UNSIGNED   TCS_Change_Time_Slice(NU_TASK *task_ptr, UNSIGNED time_slice)
+{
+
+TC_TCB         *task;                       /* Task control block ptr    */
+UNSIGNED        old_time_slice;             /* Old time slice value      */
+NU_SUPERV_USER_VARIABLES
+
+    /* Switch to supervisor mode */
+    NU_SUPERVISOR_MODE();
+
+    /* 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
+
+#ifdef  NU_ENABLE_HISTORY
+
+    /* Make an entry that corresponds to this function in the system history
+       log.  */
+    HIC_Make_History_Entry(NU_CHANGE_TIME_SLICE_ID, (UNSIGNED) task,
+                                        (UNSIGNED) time_slice, (UNSIGNED) 0);
+
+#endif
+
+    /* Protect the scheduling information.  */
+    TCT_Protect(&TCD_System_Protect);
+
+    /* Save the old time slice value.  */
+    old_time_slice =  task -> tc_time_slice;
+
+    /* Store the new time slice value.  */
+    task -> tc_time_slice =      time_slice;
+    task -> tc_cur_time_slice =  time_slice;
+
+    /* Bug fix. Let the system know we have started a new time slice */
+    TMD_Time_Slice_State = TM_ACTIVE;
+
+#ifdef INCLUDE_PROVIEW
+    _RTProf_DumpTask(task,RT_PROF_CHANGE_TIME_SLICE);
+#endif
+    /* Release protection of information.  */
+    TCT_Unprotect();
+
+    /* Return to user mode */
+    NU_USER_MODE();
+
+    /* Return the previous time slice value.  */
+    return(old_time_slice);
+}
+
+
+/*************************************************************************/
+/*                                                                       */
+/* FUNCTION                                                              */
+/*                                                                       */
+/*      TCS_Control_Signals                                              */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This function enables the specified signals and returns the      */
+/*      previous enable signal value back to the caller.  If a newly     */
+/*      enabled signal is present and a signal handler is registered,    */
+/*      signal handling is started.                                      */
+/*                                                                       */
+/* CALLED BY                                                             */
+/*                                                                       */
+/*      Application                                                      */
+/*      TCSE_Control_Signals                Error checking shell         */
+/*                                                                       */
+/* CALLS                                                                 */
+/*                                                                       */
+/*      [HIC_Make_History_Entry]            Make entry in history log    */
+/*      TCC_Signal_Shell                    Task signal execution        */
+/*      [TCT_Check_Stack]                   Stack checking function      */
+/*      TCT_Protect                         Protect against other access */
+/*      TCT_Unprotect                       Release protection           */
+/*                                                                       */
+/* INPUTS                                                                */
+/*                                                                       */
+/*      enable_signal_mask                  Enable signal mask           */
+/*                                                                       */
+/* OUTPUTS                                                               */
+/*                                                                       */
+/*      Previous signal enable mask                                      */
+/*                                                                       */
+/* HISTORY                                                               */
+/*                                                                       */
+/*         DATE                    REMARKS                               */
+/*                                                                       */
+/*      03-01-1993      Created initial version 1.0                      */
+/*      04-19-1993      Verified version 1.0                             */
+/*      05-15-1993      Corrected problem with a comment                 */
+/*      05-15-1993      Verified comment repair                          */
+/*      03-01-1994      Added register optimizations,                    */
+/*                      modified protection logic,                       */
+/*                      resulting in version 1.1                         */
+/*                                                                       */
+/*      03-18-1994      Verified version 1.1                             */
+/*                                                                       */
+/*************************************************************************/
+UNSIGNED  TCS_Control_Signals(UNSIGNED enable_signal_mask)
+{
+
+R1 TC_TCB      *task;                      /* Task pointer              */
+UNSIGNED        old_enable_mask;            /* Old enable signal mask    */
+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_CONTROL_SIGNALS_ID,(UNSIGNED) enable_signal_mask,
+                                        (UNSIGNED) 0, (UNSIGNED) 0);
+
+#endif
+
+    /* Pickup the task pointer.  */
+    task =  (TC_TCB *) TCD_Current_Thread;
+
+    /* Protect against simultaneous access.  */
+    TCT_Protect(&TCD_System_Protect);
+
+    /* Pickup the old signal mask.  */
+    old_enable_mask =  task -> tc_enabled_signals;
+
+    /* Put the new mask in.  */
+    task -> tc_enabled_signals =  enable_signal_mask;
+
+    /* Now, determine if the signal handler needs to be invoked.  */
+    if ((enable_signal_mask & task -> tc_signals) &&
+        (!task -> tc_signal_active) &&
+        (task -> tc_signal_handler))
+    {
+
+        /* Signal processing is required.  */
+
+        /* Indicate that signal processing is in progress.  */
+        task -> tc_signal_active =  NU_TRUE;
+
+        /* Clear the saved stack pointer to indicate that this is an
+           in line signal handler call.  */
+        task -> tc_saved_stack_ptr =  NU_NULL;
+
+#ifdef INCLUDE_PROVIEW
+    _RTProf_DumpTask(task,RT_PROF_CONTROL_SIGNALS);
+#endif
+
+        /* Release protection from multiple access.  */
+        TCT_Unprotect();
+
+        /* Call the signal handling shell. */
+        TCC_Signal_Shell();
+    }
+    else
+    {
+
+#ifdef INCLUDE_PROVIEW
+    _RTProf_DumpTask(task,RT_PROF_CONTROL_SIGNALS);
+#endif
+
+        /* Release protection.  */
+        TCT_Unprotect();
+    }
+
+    /* Return to user mode */
+    NU_USER_MODE();
+
+    /* Return the old enable mask.  */
+    return(old_enable_mask);
+}
+
+
+/*************************************************************************/
+/*                                                                       */
+/* FUNCTION                                                              */
+/*                                                                       */
+/*      TCS_Receive_Signals                                              */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This function returns the current signals back to the caller.    */
+/*      Note that the signals are cleared automatically.                 */
+/*                                                                       */
+/* CALLED BY                                                             */
+/*                                                                       */
+/*      Application                                                      */
+/*      TCSE_Receive_Signals                Error checking shell         */
+/*                                                                       */
+/* CALLS                                                                 */
+/*                                                                       */
+/*      [HIC_Make_History_Entry]            Make entry in history log    */
+/*      [TCT_Check_Stack]                   Stack checking function      */
+/*      TCT_Protect                         Protect against other access */
+/*      TCT_Unprotect                       Release protection           */
+/*                                                                       */
+/* INPUTS                                                                */
+/*                                                                       */
+/*      None                                                             */
+/*                                                                       */
+/* OUTPUTS                                                               */
+/*                                                                       */
+/*      Current signals                                                  */
+/*                                                                       */
+/* 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                             */
+/*                                                                       */
+/*************************************************************************/
+UNSIGNED  TCS_Receive_Signals(VOID)
+{
+
+TC_TCB          *task;                      /* Task pointer              */
+UNSIGNED        signals;                    /* Current signals           */
+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_RECEIVE_SIGNALS_ID, (UNSIGNED) 0,
+                                        (UNSIGNED) 0, (UNSIGNED) 0);
+
+#endif
+
+    /* Pickup the task pointer.  */
+    task =  (TC_TCB *) TCD_Current_Thread;
+
+    /* Protect against simultaneous access.  */
+    TCT_Protect(&TCD_System_Protect);
+
+    /* Pickup the current events.  */
+    signals =  task -> tc_signals;
+
+    /* Clear the current signals.  */
+    task -> tc_signals =  0;
+
+#ifdef INCLUDE_PROVIEW
+    _RTProf_DumpTask(task,RT_PROF_RECEIVE_SIGNALS);
+#endif
+
+    /* Release protection.  */
+    TCT_Unprotect();
+
+    /* Return to user mode */
+    NU_USER_MODE();
+
+    /* Return the signals to the caller.  */
+    return(signals);
+}
+
+
+/*************************************************************************/
+/*                                                                       */
+/* FUNCTION                                                              */
+/*                                                                       */
+/*      TCS_Register_Signal_Handler                                      */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This function registers a signal handler for the calling task.   */
+/*      Note that if an enabled signal is present and this is the first  */
+/*      registered signal handler call, the signal is processed          */
+/*      immediately.                                                     */
+/*                                                                       */
+/* CALLED BY                                                             */
+/*                                                                       */
+/*      Application                                                      */
+/*      TCSE_Register_Signal_Handler        Error checking shell         */
+/*                                                                       */
+/* CALLS                                                                 */
+/*                                                                       */
+/*      [HIC_Make_History_Entry]            Make entry in history log    */
+/*      TCC_Signal_Shell                    Signal execution shell       */
+/*      [TCT_Check_Stack]                   Stack checking function      */
+/*      TCT_Protect                         Protect against other access */
+/*      TCT_Unprotect                       Release protection           */
+/*                                                                       */
+/* INPUTS                                                                */
+/*                                                                       */
+/*      signal_handler                      Signal execution shell       */
+/*                                                                       */
+/* OUTPUTS                                                               */
+/*                                                                       */
+/*      NU_SUCCESS                                                       */
+/*                                                                       */
+/* HISTORY                                                               */
+/*                                                                       */
+/*         DATE                    REMARKS                               */
+/*                                                                       */
+/*      03-01-1993      Created initial version 1.0                      */
+/*      04-19-1993      Verified version 1.0                             */
+/*      05-15-1993      Corrected problem with a comment                 */
+/*      05-15-1993      Verified comment repair                          */
+/*      03-01-1994      Added register optimizations,                    */
+/*                      modified protection logic,                       */
+/*                      resulting in version 1.1                         */
+/*                                                                       */
+/*      03-18-1994      Verified version 1.1                             */
+/*                                                                       */
+/*************************************************************************/
+STATUS  TCS_Register_Signal_Handler(VOID (*signal_handler)(UNSIGNED))
+{
+
+R1 TC_TCB      *task;                       /* Task pointer              */
+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_REGISTER_SIGNAL_HANDLER_ID,
+                        (UNSIGNED) signal_handler, (UNSIGNED) 0, (UNSIGNED) 0);
+
+#endif
+
+    /* Pickup the task pointer.  */
+    task =  (TC_TCB *) TCD_Current_Thread;
+
+    /* Protect against simultaneous access.  */
+    TCT_Protect(&TCD_System_Protect);
+
+    /* Put the new signal handler in.  */
+    task -> tc_signal_handler =  signal_handler;
+
+    /* Now, determine if the signal handler needs to be invoked.  */
+    if ((task -> tc_enabled_signals & task -> tc_signals) &&
+        (!task -> tc_signal_active) &&
+        (task -> tc_signal_handler))
+    {
+
+        /* Signal processing is required.  */
+
+        /* Indicate that signal processing is in progress.  */
+        task -> tc_signal_active =  NU_TRUE;
+
+        /* Clear the saved stack pointer to indicate that this is an
+           in line signal handler call.  */
+        task -> tc_saved_stack_ptr =  NU_NULL;
+
+        /* Release protection from multiple access.  */
+        TCT_Unprotect();
+
+        /* Call the signal handling shell. */
+        TCC_Signal_Shell();
+    }
+    else
+
+        /* Release protection.  */
+        TCT_Unprotect();
+
+    /* Return to user mode */
+    NU_USER_MODE();
+
+    /* Return success.  */
+    return(NU_SUCCESS);
+}
+
+
+/*************************************************************************/
+/*                                                                       */
+/* FUNCTION                                                              */
+/*                                                                       */
+/*      TCS_Send_Signals                                                 */
+/*                                                                       */
+/* DESCRIPTION                                                           */
+/*                                                                       */
+/*      This function sends the specified task the specified signals.    */
+/*      If enabled, the specified task is setup in order to process the  */
+/*      signals.                                                         */
+/*                                                                       */
+/* CALLED BY                                                             */
+/*                                                                       */
+/*      Application                                                      */
+/*      TCSE_Send_Signals                   Error checking shell         */
+/*                                                                       */
+/* CALLS                                                                 */
+/*                                                                       */
+/*      [HIC_Make_History_Entry]            Make entry in history log    */
+/*      TCC_Resume_Task                     Resume task that is suspended*/
+/*      TCC_Signal_Shell                    Signal execution shell       */
+/*      TCT_Build_Signal_Frame              Build a signal frame         */
+/*      [TCT_Check_Stack]                   Stack checking function      */
+/*      TCT_Control_To_System               Control to system            */
+/*      TCT_Protect                         Protect against other access */
+/*      TCT_Unprotect                       Release protection           */
+/*                                                                       */
+/* INPUTS                                                                */
+/*                                                                       */
+/*      task_ptr                            Task pointer                 */
+/*      signals                             Signals to send to the task  */
+/*                                                                       */
+/* 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,                    */
+/*                      modified protection logic,                       */
+/*                      resulting in version 1.1                         */
+/*                                                                       */
+/*      03-18-1994      Verified version 1.1                             */
+/*      04-04-1996      On line 995, changed tc_signals                  */
+/*                      to tc_enabled_signals,                           */
+/*                      resulting in version 1.1+                        */
+/*                      (spr 107)                                        */
+/*                                                                       */
+/*************************************************************************/
+STATUS  TCS_Send_Signals(NU_TASK *task_ptr, UNSIGNED signals)
+{
+
+R1 TC_TCB      *task;                       /* Task control block ptr    */
+NU_SUPERV_USER_VARIABLES
+
+    /* Switch to supervisor mode */
+    NU_SUPERVISOR_MODE();
+
+    /* 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
+
+#ifdef  NU_ENABLE_HISTORY
+
+    /* Make an entry that corresponds to this function in the system history
+       log.  */
+    HIC_Make_History_Entry(NU_SEND_SIGNALS_ID, (UNSIGNED) signals,
+                                        (UNSIGNED) 0, (UNSIGNED) 0);
+
+#endif
+
+    /* Protect against simultaneous access.  */
+    TCT_Protect(&TCD_System_Protect);
+
+    /* Or the new signals into the current signals.  */
+    task -> tc_signals =  task -> tc_signals | signals;
+
+#ifdef INCLUDE_PROVIEW
+    _RTProf_DumpTask(task,RT_PROF_SEND_SIGNALS);
+#endif
+    /* Now, determine if the signal handler needs to be invoked.  */
+    if ((task -> tc_signals & task -> tc_enabled_signals) &&
+        (!task -> tc_signal_active) &&
+        (task -> tc_status != NU_TERMINATED) &&
+        (task -> tc_status != NU_FINISHED) &&
+        (task -> tc_signal_handler))
+    {
+
+        /* Indicate that signal processing is in progress.  */
+        task -> tc_signal_active =  NU_TRUE;
+
+        /* Signal processing is required.  Determine if the task is sending
+           signals to itself or if the calling thread is not the current
+           task.  */
+        if (task == (TC_TCB *) TCD_Current_Thread)
+        {
+
+            /* Task sending signals to itself.  */
+
+            /* Clear the saved stack pointer to indicate that this is an
+               in line signal handler call.  */
+            task -> tc_saved_stack_ptr =  NU_NULL;
+
+            /* Release protection from multiple access.  */
+            TCT_Unprotect();
+
+            /* Call the signal handling shell. */
+            TCC_Signal_Shell();
+        }
+        else
+        {
+
+            /* Target task must be prepared to receive the signals.  */
+
+            /* First, insure that the target task is not in a protected
+               area.  */
+            do
+            {
+
+                /* Check for protection.  Remember that protection is still
+                   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 on the scheduling structures.  */
+                    TCT_Protect(&TCD_System_Protect);
+                }
+            } while (task -> tc_current_protect);
+
+            /* Copy the current status and stack pointer to the signal save
+               areas.  */
+            task -> tc_saved_status =           task -> tc_status;
+            task -> tc_saved_stack_ptr =        task -> tc_stack_pointer;
+
+            /* Build a stack frame for the signal handling shell function. */
+            TCT_Build_Signal_Frame(task);
+
+            /* Determine if the target task is currently suspended.  If it is
+               suspended for any other reason than a pure suspend, resume
+               it.  */
+            if ((task -> tc_status != NU_READY) &&
+                (task -> tc_status != NU_PURE_SUSPEND))
+            {
+
+                /* Resume the target task and check for preemption.  */
+                if (TCC_Resume_Task(task_ptr, task -> tc_status))
+
+                    /* Preemption needs to take place.  */
+                    TCT_Control_To_System();
+            }
+        }
+    }
+
+    /* Release protection, no signals are currently enabled.  */
+    TCT_Unprotect();
+
+    /* Return to user mode */
+    NU_USER_MODE();
+
+    /* Return a successful status.  */
+    return(NU_SUCCESS);
+}
+
+
+
+