1    /* 
     2     * Copyright (c) 2009
     3     * Texas Instruments
     4     *
     5     *  All rights reserved.  Property of Texas Instruments
     6     *  Restricted rights to use, duplicate or disclose this code are
     7     *  granted through contract.
     8     * 
     9     * */
    10    /*
    11     *  ======== Task.xdc ========
    12     *
    13     */
    14    
    15    package ti.sysbios.knl;
    16    
    17    import xdc.rov.ViewInfo;
    18    
    19    import xdc.runtime.Error;
    20    import xdc.runtime.Assert;
    21    import xdc.runtime.Diags;
    22    import xdc.runtime.Log;
    23    import xdc.runtime.IHeap;
    24    
    25    import ti.sysbios.misc.Queue;
    26    
    27    /*!
    28     *  ======== Task ========
    29     *  Task Manager.
    30     *
    31     *  The Task module makes available a set of functions that manipulate task
    32     *  objects accessed through pointers of type {@link #Handle}. Tasks represent
    33     *  independent threads of control that conceptually execute functions in
    34     *  parallel within a single C program; in reality, concurrency is achieved
    35     *  by switching the processor from one task to another.
    36     *
    37     *  When you create a task, it is provided with its own run-time stack,
    38     *  used for storing local variables as well as for further nesting of
    39     *  function calls. Each stack must be large enough to handle normal
    40     *  subroutine calls and one task preemption context.
    41     *  A task preemption context is the context that gets saved when one task
    42     *  preempts another as a result of an interrupt thread readying
    43     *  a higher-priority task.
    44     *
    45     *  All tasks executing within a single program share a common set of
    46     *  global variables, accessed according to the standard rules of scope
    47     *  defined for C functions.
    48     *
    49     *  Each task is in one of five modes of execution at any point in time:
    50     *  running, ready, blocked, terminated, or inactive. By design, there is 
    51     *  always one
    52     *  (and only one) task currently running, even if it is only the idle task
    53     *  managed internally by Task. The current task can be suspended from
    54     *  execution by calling certain Task functions, as well as functions
    55     *  provided by other modules like the Semaphore or Event Modules. 
    56     *  The current task
    57     *  can also terminate its own execution. In either case, the processor
    58     *  is switched to the highest priority task that is ready to run.
    59     *
    60     *  You can assign numeric priorities to tasks. Tasks are
    61     *  readied for execution in strict priority order; tasks of the same
    62     *  priority are scheduled on a first-come, first-served basis. 
    63     *  The priority of the currently running task is never lower
    64     *  than the priority of any ready task. Conversely, the running task
    65     *  is preempted and re-scheduled for execution whenever there exists
    66     *  some ready task of higher priority.
    67     *
    68     *  Stack alignment
    69     *  
    70     *  Stack size parameters for both static and dynamic tasks are rounded
    71     *  up to the nearest integer multiple of a target specific alignment
    72     *  requirement.
    73     *  
    74     *  In the case of Task's which are created with a user-provided stack,
    75     *  both the base address and the stackSize are aligned. The base address
    76     *  is increased to the nearest aligned address. The stack size is decreased
    77     *  accordingly and then rounded down to the nearest integer multiple of the 
    78     *  target-specific required alignment.
    79     *
    80     *  Hook Functions
    81     *
    82     *  Sets of hook functions can be specified for the Task module.  Each
    83     *  set constains these hook functions:
    84     *  @p(blist)
    85     *  -Register:  A function called before any statically created tasks
    86     *      are initialized at runtime.  The register hook is called at boot time
    87     *      before main() and before interrupts are enabled.
    88     *  -Create:    A function that is called when a task is created. 
    89     *      This includes tasks that are created statically and those
    90     *      created dynamically using {@link #create} or {@link #construct}.
    91     *      The create hook is called outside of a Task_disable/enable block and
    92     *      before the task has been added to the ready list.
    93     *  -Ready:     A function that is called when a task becomes ready to run.
    94     *      The ready hook is called from within a Task_disable/enable block with
    95     *      interrupts enabled.
    96     *  -Switch:    A function that is called just before a task switch
    97     *      occurs. The 'prev' and 'next' task handles are passed to the Switch
    98     *      hook.  'prev' is set to NULL for the initial task switch that occurs
    99     *      during BIOS startup.  The Switch hook is called from within a
   100     *      Task_disable/enable block with interrupts enabled.
   101     *  -Exit:      A function that is called when a task exits using
   102     *      {@link #exit}.  The exit hook is passed the handle of the exiting
   103     *      task.  The exit hook is called outside of a Task_disable/enable block
   104     *      and before the task has been removed from the kernel lists.
   105     *  -Delete:    A function that is called when any task is deleted at
   106     *      run-time with {@link #delete}.  The delete hook is called outside
   107     *      of a Task_disable/enable block.
   108     *  @p
   109     *  Hook functions can only be configured statically.
   110     *
   111     *  Register Function
   112     *
   113     *  The Register function is provided to allow a hook set to store its
   114     *  hookset ID.  This id can be passed to {@link #setHookContext} and 
   115     *  {@link #getHookContext} to set or get hookset-specific context.  The
   116     *  Register function must be specified if the hook implementation
   117     *  needs to use {@link #setHookContext} or {@link #getHookContext}.
   118     *  The registerFxn hook function is called during system initialization
   119     *  before interrupts have been enabled. 
   120     *
   121     *  @p(code)
   122     *  Void myRegisterFxn(Int id);
   123     *  @p
   124     *
   125     *  Create and Delete Functions
   126     *
   127     *  The create and delete functions are called whenever a Task is created
   128     *  or deleted.  They are called with interrupts enabled (unless called 
   129     *  at boot time or from main()).
   130     *
   131     *  @p(code)
   132     *  Void myCreateFxn(Task_Handle task, Error_Block *eb);
   133     *  @p
   134     *
   135     *  @p(code)
   136     *  Void myDeleteFxn(Task_Handle task);
   137     *  @p
   138     *
   139     *  Switch Function
   140     *
   141     *  If a switch function is specified, it is invoked just before the new task
   142     *  is switched to.  The switch function is called with interrupts enabled.
   143     *
   144     *  This function can be used to save/restore additional task context (for
   145     *  example, external hardware registers), to check for task stack overflow,
   146     *  to monitor the time used by each task, etc.
   147     *
   148     *  @p(code)
   149     *  Void mySwitchFxn(Task_Handle prev, Task_Handle next);
   150     *  @p
   151     *
   152     *  Ready Function
   153     *
   154     *  If a ready function is specified, it is invoked whenever a task is made
   155     *  ready to run.   The ready function is called  with interrupts enabled
   156     *  (unless called at boot time or from main()).
   157     *
   158     *  @p(code)
   159     *  Void myReadyFxn(Task_Handle task);
   160     *  @p
   161     * 
   162     *  Exit Function
   163     *
   164     *  If an exit function is specified, it is invoked when a task exits (via
   165     *  call to Task_exit() or when a task returns from its' main function).
   166     *  The Exit Function is called with interrupts enabled. 
   167     *
   168     *  @p(code)
   169     *  Void myExitFxn(Task_Handle task);
   170     *  @p
   171     *
   172     *  @p(html)
   173     *  <h3> Calling Context </h3>
   174     *  <table border="1" cellpadding="3">
   175     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
   176     *    
   177     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th><th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
   178     *    <!--                                                                                                                 -->
   179     *    <tr><td> {@link #create}          </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   180     *    <tr><td> {@link #disable}         </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   181     *    <tr><td> {@link #exit}            </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   182     *    <tr><td> {@link #getIdleTask}     </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   183     *    <tr><td> {@link #Params_init}     </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   184     *    <tr><td> {@link #restore}         </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   185     *    <tr><td> {@link #self}            </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   186     *    <tr><td> {@link #sleep}           </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   187     *    <tr><td> {@link #yield}           </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   188     *    
   189     *    <tr><td> {@link #construct}       </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   190     *    <tr><td> {@link #delete}          </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   191     *    <tr><td> {@link #destruct}        </td><td>   N    </td><td>   N    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   192     *    <tr><td> {@link #getEnv}          </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   193     *    <tr><td> {@link #getHookContext}  </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   194     *    <tr><td> {@link #getMode}         </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   195     *    <tr><td> {@link #getPri}          </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   196     *    <tr><td> {@link #setEnv}          </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   197     *    <tr><td> {@link #setHookContext}  </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   198     *    <tr><td> {@link #setPri}          </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   199     *    <tr><td> {@link #stat}            </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   200     *    <tr><td colspan="6"> Definitions: <br />
   201     *       <ul>
   202     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   203     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   204     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   205     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   206     *           <ul>
   207     *             <li> In your module startup after this module is started (e.g. Task_Module_startupDone() returns TRUE). </li>
   208     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   209     *             <li> During main().</li>
   210     *             <li> During BIOS.startupFxns.</li>
   211     *           </ul>
   212     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   213     *           <ul>
   214     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   215     *             <li> In your module startup before this module is started (e.g. Task_Module_startupDone() returns FALSE).</li>
   216     *           </ul>
   217     *       </ul>
   218     *    </td></tr>
   219     *  
   220     *  </table>
   221     *  @p
   222     */
   223    
   224    @ModuleStartup      /* generate a call to Task_Module_startup at startup */
   225    @InstanceFinalize   /* generate call to Task_Instance_finalize on delete */
   226    @InstanceInitError  /* instance init can fail */
   227    
   228    module Task
   229    {
   230    
   231        // -------- Module Constants --------
   232    
   233        // -------- Module Types --------
   234    
   235        /*! Task function type definition. */
   236        typedef Void (*FuncPtr)(UArg, UArg);
   237    
   238        /*! 
   239         *  Task execution modes. 
   240         *
   241         *  These enumerations are the range of modes or states that 
   242         *  a task can be in. A task's current mode can be gotten using
   243         *  {@link #stat}.
   244         */
   245        enum Mode {
   246            Mode_RUNNING,           /*! Task is currently executing. */
   247            Mode_READY,             /*! Task is scheduled for execution. */
   248            Mode_BLOCKED,           /*! Task is suspended from execution. */
   249            Mode_TERMINATED,        /*! Task is terminated from execution. */
   250            Mode_INACTIVE           /*! Task is on inactive task list */
   251        };
   252    
   253        /*! 
   254         *  Task Status Buffer. 
   255         *
   256         *  Passed to and filled in by {@link #stat};
   257         */
   258        struct Stat {
   259            Int     priority;       /*! Task priority. */
   260            Ptr     stack;          /*! Task stack. */
   261            SizeT   stackSize;      /*! Task stack size. */
   262            IHeap.Handle stackHeap; /*! Heap used to alloc stack. */
   263            Ptr     env;            /*! Global environment struct. */
   264            Mode    mode;           /*! Task's current mode. */
   265            Ptr     sp;             /*! Task's current stack pointer. */
   266            SizeT   used;           /*! max # of words used on stack. */
   267        };
   268    
   269        /*! Task hook set type definition. */
   270        struct HookSet {
   271            Void (*registerFxn)(Int);
   272            Void (*createFxn)(Handle, Error.Block *);       
   273            Void (*readyFxn)(Handle);
   274            Void (*switchFxn)(Handle, Handle);
   275            Void (*exitFxn)(Handle);
   276            Void (*deleteFxn)(Handle);
   277        };
   278    
   279        metaonly struct BasicView {
   280            String      label;
   281            Int         priority;
   282            String      mode;
   283            String      fxn[]; 
   284            UArg        arg0; 
   285            UArg        arg1; 
   286            SizeT       stackSize;
   287            Ptr         stackBase; 
   288        }
   289        
   290        metaonly struct DetailedView {
   291            String      label;
   292            Int         priority;
   293            String      mode;
   294            String      fxn[]; 
   295            UArg        arg0; 
   296            UArg        arg1; 
   297            SizeT       stackPeak;
   298            SizeT       stackSize;
   299            Ptr         stackBase; 
   300            String      blockedOn;
   301        }
   302    
   303        metaonly struct ModuleView {
   304            String      schedulerState;
   305            String      readyQMask;
   306            Bool        workPending;
   307            UInt        numVitalTasks;
   308            Ptr         currentTask;
   309            SizeT       hwiStackPeak;
   310            SizeT       hwiStackSize;
   311            Ptr         hwiStackBase;
   312        }
   313           
   314        /*! @_nodoc */
   315        @Facet
   316        metaonly config ViewInfo.Instance rovViewInfo = 
   317            ViewInfo.create({
   318                viewMap: [
   319                    ['Basic',    {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic',    structName: 'BasicView'}],
   320                    ['Detailed', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitDetailed', structName: 'DetailedView'}],
   321                    ['Module',   {type: ViewInfo.MODULE,   viewInitFxn: 'viewInitModule',   structName: 'ModuleView'}],
   322                ]
   323            });
   324    
   325        // -------- Module Parameters --------
   326    
   327        // Logs
   328        
   329        /*! Logged on every task switch */
   330        config Log.Event LM_switch = {
   331            mask: Diags.USER1 | Diags.USER2,
   332            msg: "LM_switch: oldtsk: 0x%x, oldfunc: 0x%x, newtsk: 0x%x, newfunc: 0x%x"
   333        };
   334    
   335        /*! Logged on calls to Task_sleep */
   336        config Log.Event LM_sleep = {
   337            mask: Diags.USER1 | Diags.USER2,
   338            msg: "LM_sleep: tsk: 0x%x, func: 0x%x, timeout: %d"
   339        };
   340    
   341        /*! Logged when a task is made ready to run (ie Semaphore_post()) */
   342        config Log.Event LD_ready = {
   343            mask: Diags.USER2,
   344            msg: "LD_ready: tsk: 0x%x, func: 0x%x, pri: %d"
   345        };
   346    
   347        /*! Logged when a task is blocked (ie Semaphore_pend()) */
   348        config Log.Event LD_block = {
   349            mask: Diags.USER2,
   350            msg: "LD_block: tsk: 0x%x, func: 0x%x"
   351        };
   352    
   353        /*! Logged on calls to Task_yield */
   354        config Log.Event LM_yield = {
   355            mask: Diags.USER1 | Diags.USER2,
   356            msg: "LM_yield: tsk: 0x%x, func: 0x%x, currThread: %d"
   357        };
   358    
   359        /*! Logged on calls to Task_setPri */
   360        config Log.Event LM_setPri = {
   361            mask: Diags.USER1 | Diags.USER2,
   362            msg: "LM_setPri: tsk: 0x%x, func: 0x%x, oldPri: %d, newPri %d"
   363        };
   364    
   365        /*! 
   366         *  Logged when Task functions fall thru the bottom 
   367         *  or when Task_exit() is explicitly called.
   368         */
   369        config Log.Event LD_exit = {
   370            mask: Diags.USER2,
   371            msg: "LD_exit: tsk: 0x%x, func: 0x%x"
   372        };
   373    
   374        // Errors
   375    
   376        /*! 
   377         *  Error raised when a stack overflow (or corruption) is detected.
   378         *
   379         *  This error is raised by kernel's stack checking function.  This
   380         *  function checks the stacks before every task switch to make sure
   381         *  that reserved word at top of stack has not been modified.
   382         *
   383         *  The stack checking logic is enabled by the {@link #initStackFlag} and
   384         *  {@link #checkStackFlag} configuration parameters.  If both of these
   385         *  flags are set to true, the kernel will validate the stacks.
   386         */
   387        config Error.Id E_stackOverflow  = {
   388            msg: "E_stackOverflow: Task '%s' stack overflow."
   389        };
   390    
   391        // Asserts
   392    
   393        /*! 
   394         *  Assert if all tasks are blocked.  
   395         *
   396         *  This can only happen if the 
   397         *  idle task blocks (via I/O call, call to Semaphore_pend(), etc.). 
   398         *  This should never happen since the idle task should never block.
   399         */
   400        config Assert.Id A_allBlocked  = {
   401            msg: "A_allBlocked: All tasks blocked."
   402        };
   403    
   404        /*! Asserted in Task_create and Task_delete */
   405        config Assert.Id A_badThreadType = {
   406            msg: "A_badThreadType: Cannot create/delete a task from Hwi or Swi thread."
   407        };
   408    
   409        /*! Asserted in Task_delete */
   410        config Assert.Id A_badTaskState = {
   411            msg: "A_badTaskState: Can't delete a task in BLOCKED or RUNNING state."
   412        };
   413    
   414        /*! Asserted in Task_create */
   415        config Assert.Id A_taskDisabled = {
   416            msg: "A_taskDisabled: Cannot create a task when tasking is disabled."
   417        };
   418    
   419        /*! Asserted in Task_create */
   420        config Assert.Id A_badPriority = {
   421            msg: "A_badPriority: An invalid task priority was used."
   422        };
   423    
   424        /*! Asserted in Task_sleep */
   425        config Assert.Id A_badTimeout = {
   426            msg: "A_badTimeout: Can't sleep FOREVER."
   427        };
   428    
   429        /*! 
   430         *  Number of Task priorities supported. Default is 16.
   431         *
   432         *  The maximum number of priorities supported is
   433         *  target specific and depends on the number of 
   434         *  bits in a UInt data type. For 6x and Arm devices
   435         *  the maximum number of priorities is therefore 32.
   436         *  For 28x and 55x devices, the maximum number of
   437         *  priorities is 16.
   438         */
   439        config UInt numPriorities = 16;
   440    
   441        /*!
   442         *  Default stack size (in MAUs) used for all tasks.
   443         *
   444         *  Default is obtained from the target-specific Task_Support module.
   445         */
   446        config SizeT defaultStackSize;
   447    
   448        /*!
   449         *  Default memory section used for all statically created task stacks.
   450         *
   451         *  The default stack section name is ".taskStackSection" which gets placed 
   452         *  into the platform's stackMemory (ie Program.platform.stackMemory).
   453         *
   454         *  To place all task stacks into a different memory segment, 
   455         *  add the following to your config script:
   456         *
   457         *  @p(code)
   458         *  Program.sectMap[Task.defaultStackSection] = new Program.SectionSpec();
   459         *  Program.sectMap[Task.defaultStackSection].loadSegment = "yourMemorySegment";
   460         *  @p
   461         *
   462         *  To place all task stacks into a different section AND memory segment, 
   463         *  add the following to your config script:
   464         *
   465         *  @p(code)
   466         *  Task.defaultStackSection = ".yourSectionName";
   467         *  Program.sectMap[Task.defaultStackSection] = new Program.SectionSpec();
   468         *  Program.sectMap[Task.defaultStackSection].loadSegment = "yourMemorySegment";
   469         *  @p
   470         *
   471         *  Where "yourSectionName" can be just about anything, and "yourMemorySegment" 
   472         *  must be a memory segment defined within the 
   473         *  {@link xdc.cfg.Program#platform Program.platform} 
   474         *  the application is being built for.
   475         */
   476        metaonly config String defaultStackSection = ".taskStackSection";
   477    
   478        /*!
   479         *  Default Mem heap used for all dynamically created task stacks.
   480         *
   481         *  Default is null.
   482         */
   483        config IHeap.Handle defaultStackHeap;
   484    
   485        /*! 
   486         *  Idle task stack size in MAUs. 
   487         *
   488         *  Default is inherited from module config defaultStackSize.
   489         */
   490        metaonly config SizeT idleTaskStackSize;
   491    
   492        /*! 
   493         *  Idle task stack section
   494         *
   495         *  Default is inherited from module config defaultStackSection;
   496         */
   497        metaonly config String idleTaskStackSection;
   498    
   499        /*! 
   500         *  Idle task's vitalTaskFlag.
   501         *  (see {@link #vitalTaskFlag}).
   502         *
   503         *  Default is true.
   504         */
   505        metaonly config Bool idleTaskVitalTaskFlag = true;
   506    
   507        /*! 
   508         *  Initialize stack with known value for stack checking at runtime
   509         *  (see {@link #checkStackFlag}).
   510         *
   511         *  This is also useful for inspection of stack in debugger or core
   512         *  dump utilities.
   513         *  Default is true.
   514         */
   515        config Bool initStackFlag = true;
   516    
   517        /*! 
   518         *  Check 'from' and 'to' task stacks before task context switch.
   519         *
   520         *  The check consists of testing the top of stack value against
   521         *  its initial value (see {@link #initStackFlag}). If it is no
   522         *  longer at this value, the assumption is that the task has
   523         *  overrun its stack. If the test fails, then the 
   524         *  {@link #E_stackOverflow} error is raised.
   525         *
   526         *  Runtime stack checking is only performed if {@link #initStackFlag} is
   527         *  also true.
   528         *
   529         *  Default is true.
   530         */
   531        metaonly config Bool checkStackFlag = true;
   532    
   533        /*!
   534         *  const array that holds the HookSet objects.
   535         */
   536        config HookSet hooks[length] = [];
   537    
   538        // -------- Module Functions --------
   539    
   540        /*!
   541         *  ======== addHookSet ========
   542         *  addHookSet is used in a config file to add a hook set (defined
   543         *  by struct HookSet).
   544         *
   545         *  HookSet structure elements may be omitted, in which case those
   546         *  elements will not exist.
   547         *
   548         *  @param(hook)    structure of type HookSet
   549         */
   550        metaonly Void addHookSet(HookSet hook);
   551    
   552        /*!
   553         *  @_nodoc
   554         *  ======== Task_startup ========
   555         *  Start the task scheduler.
   556         *
   557         *  Task_startup signals the end of boot operations, enables
   558         *  the Task scheduler and schedules the highest priority ready
   559         *  task for execution.
   560         *
   561         *  Task_startup is called by BIOS_start() after Hwi_enable() 
   562         *  and Swi_enable(). There is no return from this function as the 
   563         *  execution thread is handed to the highest priority ready task.
   564         */
   565        Void startup();
   566    
   567        /*!
   568         *  ======== Task_disable ========
   569         *  Disable the task scheduler.
   570         *
   571         *  {@link #disable} and {@link #restore} control Task scheduling.
   572         *  {@link #disable} disables all other Tasks from running until
   573         *  {@link #restore} is called. Hardware and Software interrupts
   574         *  can still run.
   575         *
   576         *  {@link #disable} and {@link #restore} allow you to ensure that 
   577         *  statements
   578         *  that must be performed together during critical processing are not
   579         *  preempted by other Tasks.
   580         *
   581         *  The value of the key returned is opaque to applications and is meant
   582         *  to be passed to Task_restore().
   583         *
   584         *  In the following example, the critical section is
   585         *  not preempted by any Tasks.
   586         *
   587         *  @p(code)
   588         *  key = Task_disable();
   589         *      `critical section`
   590         *  Task_restore(key);
   591         *  @p
   592         *
   593         *  You can also use {@link #disable} and {@link #restore} to 
   594         *  create several Tasks and allow them to be invoked in 
   595         *  priority order.
   596         *
   597         *  {@link #disable} calls can be nested.
   598         *
   599         *  @b(returns)     key for use with {@link #restore}
   600         *
   601         *  @a(constraints)
   602         *  Do not call any function that can cause the current task to block 
   603         *  within a {@link #disable}/{@link #restore} block. For example, 
   604         *  {@link ti.sysbios.ipc.Semaphore#pend Semaphore_pend} 
   605         *  (if timeout is non-zero), 
   606         *  {@link #sleep}, {@link #yield}, and Memory_alloc can all
   607         *  cause blocking. 
   608         */
   609        UInt disable();
   610    
   611        /*!
   612         *  @_nodoc
   613         *  ======== enable ========
   614         *  Enable the task scheduler.
   615         *
   616         *  {@link #enable} unconditionally enables the Task scheduler and
   617         *  schedules the highest priority ready task for execution.
   618         *
   619         *  This function is called by {@link #startup} (which is called by
   620         *  {@link ti.sysbios.BIOS#start BIOS_start}) to begin multi-tasking
   621         *  operations.
   622         */
   623        Void enable();
   624    
   625        /*!
   626         *  ======== restore ========
   627         *  Restore Task scheduling state.
   628         *
   629         *  {@link #disable} and {@link #restore} control Task scheduling
   630         *  {@link #disable} disables all other Tasks from running until
   631         *  {@link #restore} is called. Hardware and Software interrupts
   632         *  can still run.
   633         *
   634         *  {@link #disable} and {@link #restore} allow you to ensure that statements
   635         *  that must be performed together during critical processing are not
   636         *  preempted.
   637    
   638         *  In the following example, the critical section is not preempted
   639         *  by any Tasks.
   640         *
   641         *  @p(code)
   642         *  key = Task_disable();
   643         *      `critical section`
   644         *  Task_restore(key);
   645         *  @p
   646         *
   647         *  You can also use {@link #disable} and {@link #restore} to create 
   648         *  several Tasks and allow them to be performed in priority order.
   649         *
   650         *  {@link #disable} calls can be nested.
   651         *
   652         *  {@link #restore} returns with interrupts enabled if the key unlocks
   653         *  the scheduler
   654         *
   655         *  @param(key)     key to restore previous Task scheduler state
   656         *
   657         *  @a(constraints)
   658         *  Do not call any function that can cause the current task to block 
   659         *  within a {@link #disable}/{@link #restore} block. For example, 
   660         *  {@link ti.sysbios.ipc.Semaphore#pend Semaphore_pend()} 
   661         *  (if timeout is non-zero), 
   662         *  {@link #sleep}, {@link #yield}, and Memory_alloc can all
   663         *  cause blocking. 
   664         *
   665         *  {@link #restore} internally calls Hwi_enable() if the key passed
   666         *  to it results in the unlocking of the Task scheduler (ie if this
   667         *  is root Task_disable/Task_restore pair).
   668         */
   669        Void restore(UInt key);
   670    
   671        /*!
   672         *  @_nodoc
   673         *  ======== restoreHwi ========
   674         *  Restore Task scheduling state.
   675         *  Used by dispatcher. Does not re-enable Ints.
   676         */
   677        Void restoreHwi(UInt key);
   678    
   679        /*!
   680         *  ======== self ========
   681         *  Returns a handle to the currently executing Task object.
   682         *
   683         *  Task_self returns the object handle for the currently executing task. 
   684         *  This function is useful when inspecting the object or when the current 
   685         *  task changes its own priority through {@link #setPri}.
   686         *  
   687         *  No task switch occurs when calling Task_self.
   688         *  
   689         *  Task_self will return NULL until Tasking is initiated at the end of 
   690         *  BIOS_start().
   691         *
   692         *  @b(returns)     address of currently executing task object
   693         */
   694        Handle self();
   695    
   696        /*!
   697         *  @_nodoc
   698         *  ======== checkStacks ========
   699         *  Check for stack overflow.
   700         *
   701         *  This function is usually called by the {@link #HookSet} switchFxn to 
   702         *  make sure task stacks are valid before performing the context 
   703         *  switch.
   704         *
   705         *  If a stack overflow is detected on either the oldTask or the
   706         *  newTask, a {@link #E_stackOverflow} Error is raised and the system 
   707         *  exited.
   708         *
   709         *  In order to work properly, {@link #checkStacks} requires that the
   710         *  {@link #initStackFlag} set to true, which it is by default.
   711         *
   712         *  You can call {@link #checkStacks} directly from your application. 
   713         *  For example, you can check the current task's stack integrity 
   714         *  at any time with a call like the following:
   715         *
   716         *  @p(code)
   717         *  Task_checkStacks(Task_self(), Task_self());
   718         *  @p
   719         *
   720         *  @param(oldTask)  leaving Task Object Ptr
   721         *  @param(newTask)  entering Task Object Ptr
   722         */
   723        Void checkStacks(Handle oldTask, Handle newTask);
   724    
   725        /*!
   726         *  ======== exit ========
   727         *  Terminate execution of the current task.
   728         *
   729         *  Task_exit terminates execution of the current task, changing its mode
   730         *  from {@link #Mode_RUNNING} to {@link #Mode_TERMINATED}. If all tasks 
   731         *  have been terminated, or if all remaining tasks have their 
   732         *  vitalTaskFlag attribute set to FALSE, then DSP/BIOS terminates the 
   733         *  program as a whole by calling the function System_exit with a status 
   734         *  code of 0.
   735         * 
   736         *  Task_exit is automatically called whenever a task returns from its 
   737         *  toplevel function.
   738         * 
   739         *  Exit Hooks (see exitFxn in {@link #HookSet}) can be used to provide 
   740         *  functions that run whenever a task is terminated. The exitFxn Hooks 
   741         *  are called before the task has been blocked and marked 
   742         *  {@link #Mode_TERMINATED}.
   743         *
   744         *  Any DSP/BIOS function can be called from an Exit Hook function. 
   745         *
   746         *  Calling {@link #self} within an Exit function returns the task
   747         *  being exited. Your Exit function declaration should be similar to 
   748         *  the following:
   749         *  @p(code)
   750         *  Void myExitFxn(Void);
   751         *  @p
   752         * 
   753         *  A task switch occurs when calling Task_exit unless the program as a
   754         *  whole is terminated
   755         *
   756         *  @a(constraints)
   757         *  Task_exit cannot be called from a Swi or Hwi.
   758         *
   759         *  Task_exit cannot be called from the program's main() function.
   760         */
   761        Void exit();
   762    
   763        /*!
   764         *  ======== sleep ========
   765         *  Delay execution of the current task.
   766         *
   767         *  Task_sleep changes the current task's mode from {@link #Mode_RUNNING} 
   768         *  to {@link #Mode_BLOCKED}, and delays its execution for nticks 
   769         *  increments of the system clock. The actual time delayed can be up to 
   770         *  1 system clock tick less than nticks due to granularity in system 
   771         *  timekeeping.
   772         *  
   773         *  After the specified period of time has elapsed, the task reverts to 
   774         *  the {@link #Mode_READY} mode and is scheduled for execution.
   775         *  
   776         *  A task switch always occurs when calling Task_sleep if nticks > 0.
   777         *
   778         *  @param(nticks)  number of system clock ticks to sleep
   779         *
   780         *  @a(constraints)
   781         *  Task_sleep cannot be called from a Swi or Hwi, or within a
   782         *  {@link #disable} / {@link #restore} block.
   783         *
   784         *  Task_sleep cannot be called from the program's main() function.
   785         *
   786         *  Task_sleep should not be called from within an Idle function. Doing 
   787         *  so prevents analysis tools from gathering run-time information.
   788         *
   789         *  nticks cannot be {@link ti.sysbios.BIOS#WAIT_FOREVER BIOS_WAIT_FOREVER}.
   790         */
   791        Void sleep(UInt nticks);
   792    
   793        /*!
   794         *  ======== yield ========
   795         *  Yield processor to equal priority task.
   796         *
   797         *  Task_yield yields the processor to another task of equal priority.
   798         *  
   799         *  A task switch occurs when you call Task_yield if there is an equal 
   800         *  priority task ready to run.
   801         *  
   802         *  Tasks of higher priority preempt the currently running task without 
   803         *  the need for a call to Task_yield. If only lower-priority tasks are 
   804         *  ready to run when you call Task_yield, the current task continues to 
   805         *  run. Control does not pass to a lower-priority task.
   806         *
   807         *  @a(constraints)
   808         *  When called within an Hwi, the code sequence calling Task_yield
   809         *  must be invoked by the Hwi dispatcher.
   810         *
   811         *  Task_yield cannot be called from the program's main() function.
   812         */
   813        Void yield();
   814    
   815        /*!
   816         *  ======== getIdleTask ========
   817         *  returns a handle to idle task object
   818         */
   819        Handle getIdleTask();
   820        
   821        /*!
   822         *  ======== getNickName ========
   823         *  
   824         */
   825        metaonly String getNickName(Any tskView);
   826    
   827    instance:
   828    
   829        /*!
   830         *  ======== create ========
   831         *  Create a Task.
   832         *
   833         *  Task_create creates a new task object. If successful, Task_create
   834         *  returns the handle of the new task object. If unsuccessful, 
   835         *  Task_create returns NULL unless it aborts.
   836         *
   837         *  The fxn parameter uses the {@link #FuncPtr} type to pass a pointer to 
   838         *  the function the Task object should run. For example, if myFxn is a 
   839         *  function in your program, you can create a Task object to call that 
   840         *  function as follows: 
   841         *  @p(code)
   842         *  task = Task_create((Task_FuncPtr)myFxn, NULL, NULL);
   843         *  @p
   844         *  You can specify application-wide Create functions in your config 
   845         *  file that run whenever a task is created. This includes tasks that 
   846         *  are created statically and those created dynamically using 
   847         *  Task_create.
   848         *
   849         *  For Task objects created statically, Create functions are called
   850         *  during the Task module initialization phase of the program startup 
   851         *  process prior to main().
   852         *
   853         *  For Task objects created dynamically, Create functions 
   854         *  are called after the task handle has been initialized but before the 
   855         *  task has been placed on its ready queue.
   856         *
   857         *  Any DSP/BIOS function can be called from Create functions.
   858         *  DSP/BIOS passes the task handle of the task being created to each of 
   859         *  the Create functions. 
   860         *
   861         *  All Create function declarations should be similar to this:
   862         *  @p(code)
   863         *  Void myCreateFxn(Task_Handle task);
   864         *  @p
   865         *
   866         *  The newly created task is placed in {@link #Mode_READY} mode, and is 
   867         *  scheduled to begin concurrent execution of the following function 
   868         *  call:
   869         *  @p(code)
   870         *  (*fxn)(arg1, arg2);
   871         *  @p
   872         *  As a result of being made ready to run, the task runs any
   873         *  application-wide Ready functions that have been specified.
   874         *
   875         *  Task_exit is automatically called if and when the task returns 
   876         *  from fxn. 
   877         *
   878         *  If params is NULL, the new task is assigned a default 
   879         *  set of configuration parameters as described below.
   880         *  
   881         *  @param(fxn)     Task Function
   882         *  
   883         *  @a(constraints)
   884         *  The fxn parameter and the name attribute cannot be NULL.
   885         *
   886         *  The priority attribute must be less than or equal to 
   887         *  ({@link #numPriorities} - 1) and greater than or equal to one (1)
   888         *  (priority 0 is owned by the Idle task). 
   889         *
   890         *  The priority can be less than zero (0) for tasks that should not 
   891         *  execute.
   892         *
   893         *  The stackHeap attribute must identify a valid memory Heap.
   894         */
   895        create(FuncPtr fxn);
   896    
   897        // -------- Handle Parameters --------
   898    
   899        /*! Task function argument. Default is 0 */
   900        config UArg arg0 = 0;
   901    
   902        /*! Task function argument. Default is 0 */
   903        config UArg arg1 = 0;
   904    
   905        /*!
   906         *  Task priority (0 to numPriorities-1 or -1).
   907         *  Default is 1.
   908         */
   909        config Int priority = 1;
   910    
   911        /*!
   912         *  Task stack pointer. Default = null.
   913         *  null indicates that the stack is to be allocated by create().
   914         *
   915         *  Example: To statically initialize "tsk0"'s stack to a literal
   916         *  address, use the following syntax:
   917         *
   918         *  @p(code)
   919         *      Program.global.tsk0.stack = $addr(literal);
   920         *  @p
   921         *
   922         */
   923        config Ptr stack = null;
   924    
   925        /*! 
   926         *  Task stack size in MAUs. 
   927         *  The default value of 0 means that the module config 
   928         *  {@link #defaultStackSize} is used.
   929         */
   930        config SizeT stackSize = 0;
   931    
   932        /*!
   933         *  Mem section used for statically created task stacks.
   934         *  Default is inherited from module config defaultStackSection
   935         */
   936        metaonly config String stackSection;
   937    
   938        /*!
   939         *  Mem heap used for dynamically created task stack.
   940         *  The default value of NULL means that the module config 
   941         *  {@link #defaultStackHeap} is used.
   942         */
   943        config IHeap.Handle stackHeap = null;
   944    
   945        /*! Environment data struct. */
   946        config Ptr env = null;
   947    
   948        /*!
   949         *  Exit system immediately when the last task with this
   950         *  flag set to TRUE has terminated. Default is true.
   951         */
   952        config Bool vitalTaskFlag = true;
   953    
   954        // -------- Handle Functions --------
   955    
   956        /*!
   957         *  @_nodoc
   958         *  ======== getArg0 ========
   959         *  Returns arg0 passed via params to create.
   960         *
   961         *  @b(returns)     task's arg0
   962         */
   963        UArg getArg0();
   964    
   965        /*!
   966         *  @_nodoc
   967         *  ======== getArg1 ========
   968         *  Returns arg1 passed via params to create.
   969         *
   970         *  @b(returns)     task's arg1
   971         */
   972        UArg getArg1();
   973    
   974        /*!
   975         *  ======== getEnv ========
   976         *  Get task environment pointer.
   977         *
   978         *  Task_getEnv returns the environment pointer of the specified task. The
   979         *  environment pointer references an arbitrary application-defined data 
   980         *  structure.
   981         *  
   982         *  If your program uses multiple hook sets, {@link #getHookContext} 
   983         *  allows you to get environment pointers you have set for a particular 
   984         *  hook set and Task object combination.
   985         *
   986         *  @b(returns)     task environment pointer
   987         */
   988        Ptr getEnv();
   989    
   990        /*!
   991         *  ======== getHookContext ========
   992         *  Get hook set's context for a task.
   993         *
   994         *  @param(id)      hook set ID
   995         *  @b(returns)     hook set context for task
   996         */
   997        Ptr getHookContext(Int id);
   998    
   999        /*!
  1000         *  ======== getPri ========
  1001         *  Get task priority.
  1002         *
  1003         *  Task_getPri returns the priority of the referenced task.
  1004         *
  1005         *  @b(returns)     task priority
  1006         */
  1007        Int getPri();
  1008    
  1009        /*!
  1010         *  @_nodoc
  1011         *  ======== setArg0 ========
  1012         *  Set arg0 (used primarily for legacy support)
  1013         */
  1014        Void setArg0(UArg arg);
  1015    
  1016        /*!
  1017         *  @_nodoc
  1018         *  ======== setArg1 ========
  1019         *  Set arg1 (used primarily for legacy support)
  1020         */
  1021        Void setArg1(UArg arg);
  1022    
  1023        /*!
  1024         *  ======== setEnv ========
  1025         *  Set task environment.
  1026         *
  1027         *  Task_setEnv sets the task environment pointer to env. The
  1028         *  environment pointer references an arbitrary application-defined
  1029         *  data structure.
  1030         *
  1031         *  If your program uses multiple hook sets, {@link #setHookContext} 
  1032         *  allows you to set environment pointers for any
  1033         *  hook set and Task object combination.
  1034         *
  1035         *  @param(env)     task environment pointer
  1036         */
  1037        Void setEnv(Ptr env);
  1038    
  1039        /*!
  1040         *  ======== setHookContext ========
  1041         *  Set hook instance's context for a task.
  1042         *
  1043         *  @param(id)              hook set ID
  1044         *  @param(hookContext)     value to write to context
  1045         */
  1046        Void setHookContext(Int id, Ptr hookContext);
  1047    
  1048        /*!
  1049         *  ======== setPri ========
  1050         *  Set a task's priority
  1051         *
  1052         *  Task_setpri sets the execution priority of task to newpri, and returns
  1053         *  that task's old priority value. Raising or lowering a task's priority
  1054         *  does not necessarily force preemption and re-scheduling of the caller:
  1055         *  tasks in the {@link #Mode_BLOCKED} mode remain suspended despite a
  1056         *  change in priority; and tasks in the {@link #Mode_READY} mode gain
  1057         *  control only if their new priority is greater than that of the
  1058         *  currently executing task.
  1059         *  
  1060         *  The maximum value of newpri is ({@link #numPriorities} - 1). 
  1061         *  The minimum value of newpri is one (1) (The Idle task owns priority 0).
  1062         *  If newpri is less than 0, the task is barred from further execution 
  1063         *  until its priority is raised at a later time by another task; if newpri
  1064         *  equals ({@link #numPriorities} - 1), execution of the task effectively
  1065         *  locks out all other program activity, except for the handling of 
  1066         *  interrupts.
  1067         *  
  1068         *  The current task can change its own priority (and possibly preempt its
  1069         *  execution) by passing the output of {@link #self} as the value of the 
  1070         *  task parameter.
  1071         *  
  1072         *  A context switch occurs when calling Task_setpri if a currently 
  1073         *  running task priority is set lower than the priority of another 
  1074         *  currently ready task, or if another ready task is made to have a
  1075         *  higher priority than the currently running task.
  1076         *
  1077         *  Task_setpri can be used for mutual exclusion.
  1078         *
  1079         *  If a task's new priority is different than its previous priority, 
  1080         *  then it's relative placement in it's new ready task priority 
  1081         *  queue can be different than the one it was removed from. This can 
  1082         *  effect the relative order in which it becomes the running task.
  1083         *
  1084         *  The effected task is placed at the head of its new priority queue
  1085         *  if it is the currently running task. Otherwise it is placed at
  1086         *  at the end of its new task priority queue.
  1087         *
  1088         *  @param(newpri) task's new priority
  1089         *  @b(returns)     task's old priority
  1090         *
  1091         *  @a(constraints)
  1092         *  newpri must be less than or equal to ({@link #numPriorities} - 1).
  1093         *
  1094         *  The task cannot be in the {@link #Mode_TERMINATED} mode.
  1095         *
  1096         *  The new priority should not be zero (0). This priority level is 
  1097         *  reserved for the Idle task.
  1098         */
  1099        UInt setPri(Int newpri);
  1100    
  1101        /*!
  1102         *  ======== stat ========
  1103         *  Retrieve the status of a task.
  1104         *
  1105         *  Task_stat retrieves attribute values and status information about a 
  1106         *  task.
  1107         *  
  1108         *  Status information is returned through statbuf, which references a
  1109         *  structure of type {@link #Stat}.
  1110         *  
  1111         *  When a task is preempted by a software or hardware interrupt, the task
  1112         *  execution mode returned for that task by Task_stat is still 
  1113         *  {@link #Mode_RUNNING}  because the task runs when the preemption ends.
  1114         *
  1115         *  The current task can inquire about itself by passing the output of
  1116         *  {@link #self} as the first argument to Task_stat. However, the task 
  1117         *  stack pointer (sp) in the {@link #Stat} structure is the value from 
  1118         *  the previous context switch.
  1119         *
  1120         *  Task_stat has a non-deterministic execution time. As such, it is not
  1121         *  recommended to call this API from Swis or Hwis.
  1122         *
  1123         *  @param(statbuf) pointer to task status structure
  1124         *
  1125         *  @a(constraints)
  1126         *  statbuf cannot be NULL;
  1127         */
  1128        Void stat(Stat *statbuf);
  1129    
  1130        /*!
  1131         *  ======== getMode ========
  1132         *  Retrieve the {@link #Mode} of a task.
  1133         */
  1134        Mode getMode();
  1135    
  1136        /*!
  1137         *  @_nodoc
  1138         *  ======== block ========
  1139         *  Block a task.
  1140         *
  1141         *  Remove a task from its ready list.
  1142         *  The effect of this API is manifest the next time the internal
  1143         *  Task scheduler is invoked. 
  1144         *  This can be done directly by embedding the call within a 
  1145         *  {@link #disable}/{@link #restore} block.
  1146         *  Otherwise, the effect will be manifest as a result of processing
  1147         *  the next dispatched interrupt, or by posting a Swi, or by falling
  1148         *  through the task function.
  1149         *
  1150         *  @a(constraints)
  1151         *  If called from within a Hwi or a Swi, or main(), there is no need 
  1152         *  to embed the call within a {@link #disable}/{@link #restore} block.
  1153         */
  1154        Void block();
  1155    
  1156        /*!
  1157         *  @_nodoc
  1158         *  ======== unblock ========
  1159         *  Unblock a task.
  1160         *
  1161         *  Place task in its ready list.
  1162         *  The effect of this API is manifest the next time the internal
  1163         *  Task scheduler is invoked. 
  1164         *  This can be done directly by embedding the call within a 
  1165         *  {@link #disable}/{@link #restore} block.
  1166         *  Otherwise, the effect will be manifest as a result of processing
  1167         *  the next dispatched interrupt, or by posting a Swi, or by falling
  1168         *  through the task function.
  1169         *
  1170         *  @a(constraints)
  1171         *  If called from within a Hwi or a Swi, or main(), there is no need 
  1172         *  to embed the call within a {@link #disable}/{@link #restore} block.
  1173         */
  1174        Void unblock();
  1175    
  1176        /*!
  1177         *  @_nodoc
  1178         *  ======== blockI ========
  1179         *  Block a task.
  1180         *
  1181         *  Remove a task from its ready list.
  1182         *  Must be called within Task_disable/Task_restore block
  1183         *  with interrupts disabled.
  1184         *  This API is meant to be used internally.
  1185         */
  1186        Void blockI();
  1187    
  1188        /*!
  1189         *  @_nodoc
  1190         *  ======== unblockI ========
  1191         *  Unblock a task.
  1192         *
  1193         *  Place task in its ready list.
  1194         *  Must be called within Task_disable/Task_restore block
  1195         *  with interrupts disabled.
  1196         *  This API is meant to be used internally.
  1197         *
  1198         *  @param(hwiKey) key returned from Hwi_disable()
  1199         */
  1200        Void unblockI(UInt hwiKey);
  1201    
  1202    
  1203    internal:   /* not for client use */
  1204    
  1205        /*! Target specific support functions. */
  1206        proxy SupportProxy inherits ti.sysbios.interfaces.ITaskSupport;
  1207    
  1208        /*
  1209         *  ======== schedule ========
  1210         *  Find highest priority ready task and invoke it.
  1211         *
  1212         *  Must be called with interrupts disabled.
  1213         */
  1214        Void schedule();
  1215    
  1216        /*
  1217         *  ======== enter ========
  1218         *  Task's initial entry point before entering task function.
  1219         */
  1220        Void enter();
  1221    
  1222        /*
  1223         *  ======== sleepTimeout ========
  1224         *  This function is the clock event handler for sleep.
  1225         */
  1226        Void sleepTimeout(UArg arg);
  1227    
  1228        /*
  1229         *  ======== postInit ========
  1230         *  finish initing static and dynamic Tasks
  1231         */
  1232        Int postInit(Object *swi, Error.Block *eb);
  1233    
  1234        /*
  1235         *  Number of statically constructed Task objects.
  1236         *  Shouldn't be set directly by the user's
  1237         *  config (it gets set by instance$static$init).
  1238         */
  1239        config UInt numConstructedTasks = 0;
  1240    
  1241        /* Task_sleep() Element */
  1242        struct PendElem {
  1243            Queue.Elem              qElem;
  1244            Task.Handle             task;
  1245            Clock.Handle            clock;
  1246        };
  1247    
  1248        struct Instance_State {
  1249            Queue.Elem      qElem;      // Task's readyQ element
  1250            volatile Int    priority;   // Task priority
  1251            UInt            mask;       // curSet mask = 1 << priority
  1252            Ptr             context;    // ptr to Task's saved context
  1253                                        // while not in RUNNING mode.
  1254            Mode            mode;       // READY, BLOCKED, RUNNING, etc
  1255            Ptr             pendElem;   // ptr to Task/Semaphore/Event PendElem
  1256            SizeT           stackSize;  // Task's stack buffer size
  1257            Char            stack[];    // buffer used for Task's stack
  1258            IHeap.Handle    stackHeap;  // Heap to allocate stack from
  1259            FuncPtr         fxn;        // Task function
  1260            UArg            arg0;       // Task function 1st arg
  1261            UArg            arg1;       // Task function 2nd arg
  1262            Ptr             env;        // Task environment pointer
  1263            Ptr             hookEnv[];  // ptr to Task's hook env array
  1264            Bool            vitalTaskFlag; // TRUE = shutdown system if
  1265                                        // last task like this exits
  1266            Queue.Handle    readyQ;     // This Task's readyQ
  1267        };
  1268    
  1269        struct Module_State {
  1270            Bool            locked;     // Task scheduler locked flag
  1271            UInt            curSet;     // Bitmask reflects readyQ states
  1272            Bool            workFlag;   // Scheduler work is pending.
  1273                                        // Optimization. Must be set
  1274                                        // whenever readyQs are modified.
  1275            UInt            vitalTasks; // number of tasks with
  1276                                        // vitalTaskFlag = true
  1277            Handle          curTask;    // current Task instance
  1278            Queue.Handle    curQ;       // current Task's readyQ
  1279            Queue.Object    readyQ[];   // Task ready queues
  1280            Queue.Object    inactiveQ;  // Task's with -1 priority
  1281            Handle          idleTask;   // Idle Task
  1282            Handle          constructedTasks[]; // array of statically 
  1283                                        // constructed Tasks
  1284        };
  1285    }
  1286    
  1287    /*
  1288     *  @(#) ti.sysbios.knl; 2, 0, 0, 0,322; 8-25-2009 22:47:15; /db/vtree/library/trees/avala/avala-l10x/src/
  1289     */
  1290