1    /*
     2     * Copyright (c) 2014, Texas Instruments Incorporated
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     */
    32    /*
    33     *  ======== Task.xdc ========
    34     *
    35     */
    36    
    37    package ti.sysbios.knl;
    38    
    39    import xdc.rov.ViewInfo;
    40    
    41    import xdc.runtime.Error;
    42    import xdc.runtime.Assert;
    43    import xdc.runtime.Diags;
    44    import xdc.runtime.Log;
    45    import xdc.runtime.IHeap;
    46    
    47    import ti.sysbios.knl.Queue;
    48    
    49    /*!
    50     *  ======== Task ========
    51     *  Task Manager.
    52     *
    53     *  The Task module makes available a set of functions that manipulate task
    54     *  objects accessed through pointers of type {@link #Handle}. Tasks represent
    55     *  independent threads of control that conceptually execute functions in
    56     *  parallel within a single C program; in reality, concurrency is achieved
    57     *  by switching the processor from one task to another.
    58     *
    59     *  When you create a task, it is provided with its own run-time stack,
    60     *  used for storing local variables as well as for further nesting of
    61     *  function calls. Each stack must be large enough to handle normal
    62     *  subroutine calls and one task preemption context.
    63     *  A task preemption context is the context that gets saved when one task
    64     *  preempts another as a result of an interrupt thread readying
    65     *  a higher-priority task.
    66     *
    67     *  All tasks executing within a single program share a common set of
    68     *  global variables, accessed according to the standard rules of scope
    69     *  defined for C functions.
    70     *
    71     *  Each task is in one of five modes of execution at any point in time:
    72     *  running, ready, blocked, terminated, or inactive. By design, there is
    73     *  always one
    74     *  (and only one) task currently running, even if it is only the idle task
    75     *  managed internally by Task. The current task can be suspended from
    76     *  execution by calling certain Task functions, as well as functions
    77     *  provided by other modules like the Semaphore or Event Modules.
    78     *  The current task
    79     *  can also terminate its own execution. In either case, the processor
    80     *  is switched to the highest priority task that is ready to run.
    81     *
    82     *  You can assign numeric priorities to tasks. Tasks are
    83     *  readied for execution in strict priority order; tasks of the same
    84     *  priority are scheduled on a first-come, first-served basis.
    85     *  The priority of the currently running task is never lower
    86     *  than the priority of any ready task. Conversely, the running task
    87     *  is preempted and re-scheduled for execution whenever there exists
    88     *  some ready task of higher priority.
    89     *
    90     *  @a(Task Deletion)
    91     *
    92     *  Any dynamically created task that is not in the Task_Mode_RUNNING
    93     *  state (ie not the currently running task) can be deleted using the
    94     *  {@link #delete} API.
    95     *
    96     *  Task_delete() removes the task from all internal queues and calls
    97     *  Memory_free() is used to free the task object and its stack.
    98     *  Memory_free() must acquire a lock to the memory before proceeding.
    99     *  If another task already holds a lock to the memory, then the thread
   100     *  performing the delete will be blocked until the memory is unlocked.
   101     *
   102     *  Note:
   103     *  Task_delete() should be called with extreme care.
   104     *  As mentioned above, the scope of Task_delete() is limited to
   105     *  freeing the Task object itself, freeing the task's stack memory
   106     *  if it was allocated at create time, and removing the task from
   107     *  any SYS/BIOS-internal state structures.
   108     *
   109     *  SYS/BIOS does not keep track of any resources the task may have
   110     *  acquired or used during its lifetime.
   111     *
   112     *  It is the application's responsibility to guarantee the integrity
   113     *  of a task's partnerships prior to deleting that task.
   114     *
   115     *  For example, if a task has obtained exclusive access to a resource,
   116     *  deleting that task will make the resource forever unavailable.
   117     *
   118     *  Task_delete() sets the referenced task handle to NULL. Any subsequent
   119     *  call to a Task instance API using that null task handle will behave
   120     *  unpredictably and will usually result in an application crash.
   121     *
   122     *  Assuming a task completely cleans up after itself prior to calling
   123     *  Task_exit() (or falling through the the bottom of the task
   124     *  function), it is then safest to use Task_delete() only when a task
   125     *  is in the 'Task_Mode_TERMINATED' state.
   126     *
   127     *  Delete hooks:
   128     *  You can specify application-wide Delete hook functions that
   129     *  run whenever a task is deleted. See the discussion of Hook Functions
   130     *  below for details.
   131     *
   132     *  Task_delete() constraints:
   133     *  @p(blist)
   134     *  -The task cannot be the currently executing task (Task_self()).
   135     *  -Task_delete cannot be called from a Swi or Hwi.
   136     *  -No check is performed to prevent Task_delete from being used on a
   137     *  statically-created object. If a program attempts to delete a task object
   138     *  that was created statically, the Memory_free() call will result in an
   139     *  assertion failure in its corresponding Heap manager, causing the
   140     *  application to exit.
   141     *  @p
   142     *
   143     *  @a(Stack Alignment)
   144     *
   145     *  Stack size parameters for both static and dynamic tasks are rounded
   146     *  up to the nearest integer multiple of a target-specific alignment
   147     *  requirement.
   148     *
   149     *  In the case of Task's which are created with a user-provided stack,
   150     *  both the base address and the stackSize are aligned. The base address
   151     *  is increased to the nearest aligned address. The stack size is decreased
   152     *  accordingly and then rounded down to the nearest integer multiple of the
   153     *  target-specific required alignment.
   154     *
   155     *  @p(html)
   156     *  <a name="hookfunc"></a>
   157     *  @p
   158     *
   159     *  @a(Hook Functions)
   160     *
   161     *  Sets of hook functions can be specified for the Task module.  Each
   162     *  set can contains these hook functions:
   163     *  @p(blist)
   164     *  -Register: A function called before any statically created tasks
   165     *      are initialized at runtime.  The register hook is called at boot time
   166     *      before main() and before interrupts are enabled.
   167     *  -Create: A function that is called when a task is created.
   168     *      This includes tasks that are created statically and those
   169     *      created dynamically using {@link #create} or {@link #construct}.
   170     *      The create hook is called outside of a Task_disable/enable block and
   171     *   before the task has been added to the ready list.
   172     *  -Ready: A function that is called when a task becomes ready to run.
   173     *   The ready hook is called from within a Task_disable/enable block with
   174     *   interrupts enabled.
   175     *  -Switch: A function that is called just before a task switch
   176     *      occurs. The 'prev' and 'next' task handles are passed to the Switch
   177     *      hook. 'prev' is set to NULL for the initial task switch that occurs
   178     *      during SYS/BIOS startup.  The Switch hook is called from within a
   179     *      Task_disable/enable block with interrupts enabled.
   180     *  -Exit:      A function that is called when a task exits using
   181     *      {@link #exit}.  The exit hook is passed the handle of the exiting
   182     *      task.  The exit hook is called outside of a Task_disable/enable block
   183     *      and before the task has been removed from the kernel lists.
   184     *  -Delete: A function that is called when any task is deleted at
   185     *      run-time with {@link #delete}.  The delete hook is called outside
   186     *      of a Task_disable/enable block.
   187     *  @p
   188     *  Hook functions can only be configured statically.
   189     *
   190     *  If you define more than one set of hook functions, all the functions
   191     *  of a particular type will be run when a Swi triggers that type of
   192     *  hook.
   193     *
   194     *  @p(html)
   195     *  <B>Register Function</B>
   196     *  @p
   197     *
   198     *  The Register function is provided to allow a hook set to store its
   199     *  hookset ID.  This id can be passed to {@link #setHookContext} and
   200     *  {@link #getHookContext} to set or get hookset-specific context.  The
   201     *  Register function must be specified if the hook implementation
   202     *  needs to use {@link #setHookContext} or {@link #getHookContext}.
   203     *  The registerFxn hook function is called during system initialization
   204     *  before interrupts have been enabled.
   205     *
   206     *  @p(code)
   207     *  Void myRegisterFxn(Int id);
   208     *  @p
   209     *
   210     *  @p(html)
   211     *  <B>Create and Delete Functions</B>
   212     *  @p
   213     *
   214     *  The create and delete functions are called whenever a Task is created
   215     *  or deleted.  They are called with interrupts enabled (unless called
   216     *  at boot time or from main()).
   217     *
   218     *  @p(code)
   219     *  Void myCreateFxn(Task_Handle task, Error_Block *eb);
   220     *  @p
   221     *
   222     *  @p(code)
   223     *  Void myDeleteFxn(Task_Handle task);
   224     *  @p
   225     *
   226     *  @p(html)
   227     *  <B>Switch Function</B>
   228     *  @p
   229     *
   230     *  If a switch function is specified, it is invoked just before the new task
   231     *  is switched to.  The switch function is called with interrupts enabled.
   232     *
   233     *  This function can be used to save/restore additional task context (for
   234     *  example, external hardware registers), to check for task stack overflow,
   235     *  to monitor the time used by each task, etc.
   236     *
   237     *  @p(code)
   238     *  Void mySwitchFxn(Task_Handle prev, Task_Handle next);
   239     *  @p
   240     *
   241     *  To properly handle the switch to the first task your switchFxn should
   242     *  check for "prev == NULL" before using prev:
   243     *
   244     *  @p(code)
   245     *  Void mySwitchFxn(Task_Handle prev, Task_Handle next)
   246     *  {
   247     *      if (prev != NULL) {
   248     *          ...
   249     *      }
   250     *      ...
   251     *  }
   252     *  @p
   253     *
   254     *  @p(html)
   255     *  <B>Ready Function</B>
   256     *  @p
   257     *
   258     *  If a ready function is specified, it is invoked whenever a task is made
   259     *  ready to run.   The ready function is called  with interrupts enabled
   260     *  (unless called at boot time or from main()).
   261     *
   262     *  @p(code)
   263     *  Void myReadyFxn(Task_Handle task);
   264     *  @p
   265     *
   266     *  @p(html)
   267     *  <B>Exit Function</B>
   268     *  @p
   269     *
   270     *  If an exit function is specified, it is invoked when a task exits (via
   271     *  call to Task_exit() or when a task returns from its' main function).
   272     *  The Exit Function is called with interrupts enabled.
   273     *
   274     *  @p(code)
   275     *  Void myExitFxn(Task_Handle task);
   276     *  @p
   277     *
   278     *  @p(html)
   279     *  <h3> Calling Context </h3>
   280     *  <table border="1" cellpadding="3">
   281     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
   282     *  </colgroup>
   283     *
   284     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th>
   285     *  <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
   286     *    <!--                                                       -->
   287     *    <tr><td> {@link #create}          </td><td>   N    </td><td>   N    </td>
   288     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   289     *    <tr><td> {@link #disable}         </td><td>   Y    </td><td>   Y    </td>
   290     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   291     *    <tr><td> {@link #exit}            </td><td>   N    </td><td>   N    </td>
   292     *  <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   293     *    <tr><td> {@link #getIdleTask}     </td><td>   Y    </td><td>   Y    </td>
   294     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   295     *    <tr><td> {@link #Params_init}     </td><td>   Y    </td><td>   Y    </td>
   296     *  <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
   297     *    <tr><td> {@link #restore}         </td><td>   Y    </td><td>   Y    </td>
   298     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   299     *    <tr><td> {@link #self}            </td><td>   Y    </td><td>   Y    </td>
   300     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   301     *    <tr><td> {@link #sleep}           </td><td>   N    </td><td>   N    </td>
   302     *  <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   303     *    <tr><td> {@link #yield}           </td><td>   Y    </td><td>   Y    </td>
   304     *  <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   305     *    <tr><td> {@link #construct}       </td><td>   N    </td><td>   N    </td>
   306     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   307     *    <tr><td> {@link #delete}          </td><td>   N    </td><td>   N    </td>
   308     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   309     *    <tr><td> {@link #destruct}        </td><td>   N    </td><td>   N    </td>
   310     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   311     *    <tr><td> {@link #getEnv}          </td><td>   Y    </td><td>   Y    </td>
   312     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   313     *    <tr><td> {@link #getHookContext}  </td><td>   Y    </td><td>   Y    </td>
   314     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   315     *    <tr><td> {@link #getMode}         </td><td>   Y    </td><td>   Y    </td>
   316     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   317     *    <tr><td> {@link #getPri}          </td><td>   Y    </td><td>   Y    </td>
   318     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   319     *    <tr><td> {@link #getFunc}         </td><td>   Y    </td><td>   Y    </td>
   320     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   321     *    <tr><td> {@link #setEnv}          </td><td>   Y    </td><td>   Y    </td>
   322     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   323     *    <tr><td> {@link #setHookContext}  </td><td>   Y    </td><td>   Y    </td>
   324     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   325     *    <tr><td> {@link #setPri}          </td><td>   Y    </td><td>   Y    </td>
   326     *  <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   327     *    <tr><td> {@link #stat}            </td><td>   Y    </td><td>   Y    </td>
   328     *  <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   329     *    <tr><td colspan="6"> Definitions: <br />
   330     *       <ul>
   331     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   332     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   333     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   334     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   335     *           <ul>
   336     *             <li> In your module startup after this module is started
   337     *  (e.g. Task_Module_startupDone() returns TRUE). </li>
   338     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   339     *             <li> During main().</li>
   340     *             <li> During BIOS.startupFxns.</li>
   341     *           </ul>
   342     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   343     *           <ul>
   344     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   345     *             <li> In your module startup before this module is started
   346     *  (e.g. Task_Module_startupDone() returns FALSE).</li>
   347     *           </ul>
   348     *       </ul>
   349     *    </td></tr>
   350     *
   351     *  </table>
   352     *  @p
   353     */
   354    
   355    @ModuleStartup      /* generate a call to Task_Module_startup at startup */
   356    @InstanceFinalize   /* generate call to Task_Instance_finalize on delete */
   357    @InstanceInitError  /* instance init can fail */
   358    
   359    module Task
   360    {
   361    
   362        // -------- Module Constants --------
   363    
   364        // -------- Module Types --------
   365    
   366        /*! Task function type definition. */
   367        typedef Void (*FuncPtr)(UArg, UArg);
   368    
   369        /*! "All Task Blocked" function type definition. */
   370        typedef Void (*AllBlockedFuncPtr)(Void);
   371    
   372        /*!
   373         *  Task execution modes.
   374         *
   375         *  These enumerations are the range of modes or states that
   376         *  a task can be in. A task's current mode can be gotten using
   377         *  {@link #stat}.
   378         */
   379        enum Mode {
   380            Mode_RUNNING,           /*! Task is currently executing. */
   381            Mode_READY,             /*! Task is scheduled for execution. */
   382            Mode_BLOCKED,           /*! Task is suspended from execution. */
   383            Mode_TERMINATED,        /*! Task is terminated from execution. */
   384            Mode_INACTIVE           /*! Task is on inactive task list */
   385        };
   386    
   387        /*!
   388         *  Task Status Buffer.
   389         *
   390         *  Passed to and filled in by {@link #stat};
   391         */
   392        struct Stat {
   393            Int     priority;       /*! Task priority. */
   394            Ptr     stack;          /*! Task stack. */
   395            SizeT   stackSize;      /*! Task stack size. */
   396            IHeap.Handle stackHeap; /*! Heap used to alloc stack. */
   397            Ptr     env;            /*! Global environment struct. */
   398            Mode    mode;           /*! Task's current mode. */
   399            Ptr     sp;             /*! Task's current stack pointer. */
   400            SizeT   used;           /*! max # of words used on stack. */
   401        };
   402    
   403        /*!
   404         *  Task hook set type definition.
   405         *
   406         *  Sets of hook functions can be specified for the Task module.
   407         *  See {@link #hookfunc Hook Functions} for details.
   408         */
   409        struct HookSet {
   410            Void (*registerFxn)(Int);
   411            Void (*createFxn)(Handle, Error.Block *);
   412            Void (*readyFxn)(Handle);
   413            Void (*switchFxn)(Handle, Handle);
   414            Void (*exitFxn)(Handle);
   415            Void (*deleteFxn)(Handle);
   416        };
   417    
   418        /*! "Don't care" task affinity */
   419        const UInt AFFINITY_NONE = ~(0);
   420    
   421        /*!  @_nodoc */
   422        metaonly struct BasicView {
   423            String      label;
   424            Int         priority;
   425            String      mode;
   426            String      fxn[];
   427            UArg        arg0;
   428            UArg        arg1;
   429            SizeT       stackSize;
   430            Ptr         stackBase;
   431            String      curCoreId;
   432            String      affinity;
   433        }
   434    
   435        /*!  @_nodoc */
   436        metaonly struct DetailedView {
   437            String      label;
   438            Int         priority;
   439            String      mode;
   440            String      fxn[];
   441            UArg        arg0;
   442            UArg        arg1;
   443            String      stackPeak;
   444            SizeT       stackSize;
   445            Ptr         stackBase;
   446            String      curCoreId;
   447            String      affinity;
   448            String      blockedOn;
   449        }
   450    
   451        /*!  @_nodoc */
   452        metaonly struct ModuleView {
   453            String      schedulerState;
   454            String      readyQMask[];
   455            Bool        workPending;
   456            UInt        numVitalTasks;
   457            Ptr         currentTask[];
   458            String      hwiStackPeak;
   459            SizeT       hwiStackSize;
   460            Ptr         hwiStackBase;
   461        }
   462    
   463        /*!  @_nodoc (not used by view) */
   464        metaonly struct CallStackView {
   465            Int         depth;
   466            String      decode;
   467        }
   468    
   469        /*!  @_nodoc */
   470        metaonly struct ReadyQView {
   471            Ptr         task;
   472            Ptr         next;
   473            Ptr         prev;
   474            Ptr         readyQ;
   475            String      label;
   476            Int         priority;
   477            String      mode;
   478            String      fxn[];
   479            String      curCoreId;
   480            String      affinity;
   481        }
   482    
   483        /*! @_nodoc */
   484        @Facet
   485        metaonly config ViewInfo.Instance rovViewInfo =
   486            ViewInfo.create({
   487                viewMap: [
   488                    ['Basic',    {type: ViewInfo.INSTANCE,     viewInitFxn: 'viewInitBasic',    structName: 'BasicView'}],
   489                    ['Detailed', {type: ViewInfo.INSTANCE,     viewInitFxn: 'viewInitDetailed', structName: 'DetailedView'}],
   490                    ['CallStacks',  {type: ViewInfo.TREE,         viewInitFxn: 'viewInitCallStack', structName: 'CallStackView'}],
   491                    ['ReadyQs',     {type: ViewInfo.TREE_TABLE,   viewInitFxn: 'viewInitReadyQs',   structName: 'ReadyQView'}],
   492                    ['Module',      {type: ViewInfo.MODULE,       viewInitFxn: 'viewInitModule',    structName: 'ModuleView'}],
   493                ]
   494            });
   495    
   496        // -------- Module Parameters --------
   497    
   498        // Logs
   499    
   500        /*! Logged on every task switch */
   501        config Log.Event LM_switch = {
   502            mask: Diags.USER1 | Diags.USER2,
   503            msg: "LM_switch: oldtsk: 0x%x, oldfunc: 0x%x, newtsk: 0x%x, newfunc: 0x%x"
   504        };
   505    
   506        /*! Logged on calls to Task_sleep */
   507        config Log.Event LM_sleep = {
   508            mask: Diags.USER1 | Diags.USER2,
   509            msg: "LM_sleep: tsk: 0x%x, func: 0x%x, timeout: %d"
   510        };
   511    
   512        /*! Logged when a task is made ready to run (ie Semaphore_post()) */
   513        config Log.Event LD_ready = {
   514            mask: Diags.USER2,
   515            msg: "LD_ready: tsk: 0x%x, func: 0x%x, pri: %d"
   516        };
   517    
   518        /*! Logged when a task is blocked (ie Semaphore_pend()) */
   519        config Log.Event LD_block = {
   520            mask: Diags.USER2,
   521            msg: "LD_block: tsk: 0x%x, func: 0x%x"
   522        };
   523    
   524        /*! Logged on calls to Task_yield */
   525        config Log.Event LM_yield = {
   526            mask: Diags.USER1 | Diags.USER2,
   527            msg: "LM_yield: tsk: 0x%x, func: 0x%x, currThread: %d"
   528        };
   529    
   530        /*! Logged on calls to Task_setPri */
   531        config Log.Event LM_setPri = {
   532            mask: Diags.USER1 | Diags.USER2,
   533            msg: "LM_setPri: tsk: 0x%x, func: 0x%x, oldPri: %d, newPri %d"
   534        };
   535    
   536        /*!
   537         *  Logged when Task functions fall thru the bottom
   538         *  or when Task_exit() is explicitly called.
   539         */
   540        config Log.Event LD_exit = {
   541            mask: Diags.USER2,
   542            msg: "LD_exit: tsk: 0x%x, func: 0x%x"
   543        };
   544    
   545        /*! Logged on calls to Task_setAffinity */
   546        config Log.Event LM_setAffinity = {
   547            mask: Diags.USER1 | Diags.USER2,
   548            msg: "LM_setAffinity: tsk: 0x%x, func: 0x%x, oldCore: %d, oldAffinity %d, newAffinity %d"
   549        };
   550    
   551        /*! Logged on every task schedule entry */
   552        config Log.Event LM_schedule = {
   553            mask: Diags.USER3,
   554            msg: "LD_schedule: coreId: %d, workFlag: %d, curSetLocal: %d, curSetX: %d, curMaskLocal: %d"
   555        };
   556    
   557        /*! Logged when no scheduling work was found */
   558        config Log.Event LM_noWork = {
   559            mask: Diags.USER3,
   560            msg: "LD_noWork: coreId: %d, curSetLocal: %d, curSetX: %d, curMaskLocal: %d"
   561        };
   562    
   563        // Errors
   564    
   565        /*!
   566         *  Error raised when a stack overflow (or corruption) is detected.
   567         *
   568         *  This error is raised by kernel's stack checking function.  This
   569         *  function checks the stacks before every task switch to make sure
   570         *  that reserved word at top of stack has not been modified.
   571         *
   572         *  The stack checking logic is enabled by the {@link #initStackFlag} and
   573         *  {@link #checkStackFlag} configuration parameters.  If both of these
   574         *  flags are set to true, the kernel will validate the stacks.
   575         */
   576        config Error.Id E_stackOverflow  = {
   577            msg: "E_stackOverflow: Task 0x%x stack overflow."
   578        };
   579    
   580        /*!
   581         *  Error raised when a task's stack pointer (SP) does not point
   582         *  somewhere within the task's stack.
   583         *
   584         *  This error is raised by kernel's stack checking function.  This
   585         *  function checks the SPs before every task switch to make sure
   586         *  they point within the task's stack.
   587         *
   588         *  The stack checking logic is enabled by the {@link #initStackFlag} and
   589         *  {@link #checkStackFlag} configuration parameters.  If both of these
   590         *  flags are set to true, the kernel will validate the stack pointers.
   591         */
   592        config Error.Id E_spOutOfBounds  = {
   593            msg: "E_spOutOfBounds: Task 0x%x stack error, SP = 0x%x."
   594        };
   595    
   596        config Error.Id E_deleteNotAllowed = {
   597            msg: "E_deleteNotAllowed: Task 0x%x."
   598        };
   599    
   600        // Asserts
   601    
   602        /*! Asserted in Task_create and Task_delete */
   603        config Assert.Id A_badThreadType = {
   604            msg: "A_badThreadType: Cannot create/delete a task from Hwi or Swi thread."
   605        };
   606    
   607        /*! Asserted in Task_delete */
   608        config Assert.Id A_badTaskState = {
   609            msg: "A_badTaskState: Can't delete a task in RUNNING state."
   610        };
   611    
   612        /*! Asserted in Task_delete */
   613        config Assert.Id A_noPendElem = {
   614            msg: "A_noPendElem: Not enough info to delete BLOCKED task."
   615        };
   616    
   617        /*! Asserted in Task_create */
   618        config Assert.Id A_taskDisabled = {
   619            msg: "A_taskDisabled: Cannot create a task when tasking is disabled."
   620        };
   621    
   622        /*! Asserted in Task_create */
   623        config Assert.Id A_badPriority = {
   624            msg: "A_badPriority: An invalid task priority was used."
   625        };
   626    
   627        /*! Asserted in Task_sleep */
   628        config Assert.Id A_badTimeout = {
   629            msg: "A_badTimeout: Can't sleep FOREVER."
   630        };
   631    
   632        /*! Asserted in Task_setAffinity */
   633        config Assert.Id A_badAffinity = {
   634            msg: "A_badAffinity: Invalid affinity."
   635        };
   636    
   637        /*! Asserted in Task_sleep */
   638        config Assert.Id A_sleepTaskDisabled = {
   639            msg: "A_sleepTaskDisabled: Cannot call Task_sleep() while the Task scheduler is disabled."
   640        };
   641    
   642        /*!
   643         *  Number of Task priorities supported. Default is 16.
   644         *
   645         *  The maximum number of priorities supported is
   646         *  target specific and depends on the number of
   647         *  bits in a UInt data type. For 6x and ARM devices
   648         *  the maximum number of priorities is therefore 32.
   649         *  For 28x, 55x, and MSP430 devices, the maximum number of
   650         *  priorities is 16.
   651         */
   652        config UInt numPriorities = 16;
   653    
   654        /*!
   655         *  Default stack size (in MAUs) used for all tasks.
   656         *
   657         *  Default is obtained from the family-specific TaskSupport module
   658          *  (e.g. {@link ti.sysbios.family.arm.m3.TaskSupport},
   659          *  {@link ti.sysbios.family.c62.TaskSupport}).
   660         */
   661        config SizeT defaultStackSize;
   662    
   663        /*!
   664         *  Default memory section used for all statically created task stacks.
   665         *
   666         *  The default stack section name is target/device specific.
   667         *  For C6x targets it is ".far:taskStackSection".
   668         *  For C28x targets it is ".taskStackSection".
   669         *  For all other targets it is ".bss:taskStackSection".
   670         *
   671         *  By default, all statically created task stacks are grouped together
   672         *  into the defaultStackSection and placed where ever
   673         *  the target specific defaultStackSection base section name
   674         *  (ie .bss, .far, .ebss) is placed.
   675         *
   676         *  To place all task stacks into a different memory segment,
   677         *  add the following to your config script:
   678         *
   679         *  @p(code)
   680         *  Program.sectMap[Task.defaultStackSection] = new Program.SectionSpec();
   681         *  Program.sectMap[Task.defaultStackSection].loadSegment =
   682         *                   "yourMemorySegment";
   683         *  @p
   684         *
   685         *  To group all task stacks into a different section AND place that
   686         *  section into a specific memory segment, add the following to your
   687         *  config script:
   688         *
   689         *  @p(code)
   690         *  Task.defaultStackSection = ".yourSectionName";
   691         *  Program.sectMap[Task.defaultStackSection] = new Program.SectionSpec();
   692         *  Program.sectMap[Task.defaultStackSection].loadSegment =
   693         *                   "yourMemorySegment";
   694         *  @p
   695         *
   696         *  Where "yourSectionName" can be just about anything, and
   697         *                   "yourMemorySegment"
   698         *  must be a memory segment defined for your board.
   699         */
   700        metaonly config String defaultStackSection;
   701    
   702        /*!
   703         *  Default Mem heap used for all dynamically created task stacks.
   704         *
   705         *  Default is null.
   706         */
   707        config IHeap.Handle defaultStackHeap;
   708    
   709        /*!
   710         *  Default core affinity for newly created tasks.
   711         *
   712         *  Default is Task_AFFINITY_NONE, meaning don't care.
   713         */
   714        metaonly config UInt defaultAffinity = AFFINITY_NONE;
   715    
   716        /*!
   717         *  Create a task (of priority 0) to run the Idle functions in.
   718         *
   719         *  When set to true, a task is created that continuously calls the
   720         *  {@link Idle#run Idle_run()} function, which, in turn calls each of
   721         *  the configured Idle functions.
   722         *
   723         *  When set to false, no Idle Task is created and it is up to the
   724         *  user to call the Idle_run() function if the configured Idle
   725         *  functions need to be run. Or, by adding the following lines to
   726         *  the config script, the Idle functions will run whenever all
   727         *  tasks are blocked ({@link #allBlockedFunc Task.allBlockedFunc}):
   728         *
   729         *  @p(code)
   730         *  Task.enableIdleTask = false;
   731         *  Task.allBlockedFunc = Idle.run;
   732         *  @p
   733         *
   734         *  Default is true.
   735         *
   736         *  @see #idleTaskStackSize
   737         *  @see #idleTaskStackSection
   738         *  @see #idleTaskVitalTaskFlag
   739         *  @see #allBlockedFunc
   740         */
   741        metaonly config Bool enableIdleTask = true;
   742    
   743        /*!
   744         *  Idle task stack size in MAUs.
   745         *
   746         *  Default is inherited from module config defaultStackSize.
   747         */
   748        metaonly config SizeT idleTaskStackSize;
   749    
   750        /*!
   751         *  Idle task stack section
   752         *
   753         *  Default is inherited from module config defaultStackSection;
   754         */
   755        metaonly config String idleTaskStackSection;
   756    
   757        /*!
   758         *  Idle task's vitalTaskFlag.
   759         *  (see {@link #vitalTaskFlag}).
   760         *
   761         *  Default is true.
   762         */
   763        metaonly config Bool idleTaskVitalTaskFlag = true;
   764    
   765        /*!
   766         *  Function to call while all tasks are blocked.
   767         *
   768         *  This function will be called repeatedly while no tasks are
   769         *  ready to run.
   770         *
   771         *  Ordinarily (in applications that have tasks ready to run at startup),
   772         *  the function will run in the context of the last task to block.
   773         *
   774         *  In an application where there are no tasks ready to run
   775         *  when BIOS_start() is called, the allBlockedFunc function is
   776         *  called within the BIOS_start() thread which runs on the system/ISR
   777         *  stack.
   778         *
   779         *  By default, allBlockedFunc is initialized to point to an internal
   780         *  function that simply returns.
   781         *
   782         *  By adding the following lines to the config script, the Idle
   783         *  functions will run whenever all tasks are blocked:
   784         *
   785         *  @p(code)
   786         *  Task.enableIdleTask = false;
   787         *  Task.allBlockedFunc = Idle.run;
   788         *  @p
   789         *
   790         *  @see #enableIdleTask
   791         *
   792         *  @a(constraints)
   793         *  The configured allBlockedFunc is designed to be called repeatedly.
   794         *  It must return in order for the task scheduler to check if all
   795         *  tasks are STILL blocked and if not, run the highest priority task
   796         *  currently ready to run.
   797         *
   798         *  The configured allBlockedFunc function is called with interrupts
   799         *  disabled. If your function must run with interrupts enabled,
   800         *  surround the body of your code with  Hwi_enable()/Hwi_restore()
   801         *  function calls per the following example:
   802         *
   803         *  @p(code)
   804         *  Void yourFunc() {
   805         *      UInt hwiKey;
   806         *
   807         *      hwiKey = Hwi_enable();
   808         *
   809         *      ...         // your code here
   810         *
   811         *      Hwi_restore(hwiKey);
   812         *  }
   813         *  @p
   814         */
   815        config AllBlockedFuncPtr allBlockedFunc = null;
   816    
   817        /*!
   818         *  Initialize stack with known value for stack checking at runtime
   819         *  (see {@link #checkStackFlag}).
   820         *
   821         *  This is also useful for inspection of stack in debugger or core
   822         *  dump utilities.
   823         *  Default is true.
   824         */
   825        config Bool initStackFlag = true;
   826    
   827        /*!
   828         *  Check 'from' and 'to' task stacks before task context switch.
   829         *
   830         *  The check consists of testing the top of stack value against
   831         *  its initial value (see {@link #initStackFlag}). If it is no
   832         *  longer at this value, the assumption is that the task has
   833         *  overrun its stack. If the test fails, then the
   834         *  {@link #E_stackOverflow} error is raised.
   835         *
   836         *  Runtime stack checking is only performed if {@link #initStackFlag} is
   837         *  also true.
   838         *
   839         *  Default is true.
   840         *
   841         *  To enable or disable full stack checking, you should set both this
   842         *  flag and the {@link ti.sysbios.hal.Hwi#checkStackFlag}.
   843         */
   844        metaonly config Bool checkStackFlag = true;
   845    
   846        /*!
   847         *  Automatically delete terminated tasks.
   848         *
   849         *  If this feature is enabled, an Idle function is installed that
   850         *  deletes dynamically created Tasks that have terminated either
   851         *  by falling through their task function or by explicitly calling
   852         *  Task_exit().
   853         *
   854         *  A list of terminated Tasks that were created dynmically is
   855         *  maintained internally. Each invocation of the installed Idle function
   856         *  deletes the first Task on this list. This one-at-a-time process
   857         *  continues until the list is empty.
   858         *
   859         *  @a(Note)
   860         *  This feature is disabled by default.
   861         *
   862         *  @a(WARNING)
   863         *  When this feature is enabled, an error will be raised if the user's
   864         *  application attempts to delete a terminated task. If a terminated task
   865         *  has already been automatically deleted and THEN the user's application
   866         *  attempts to delete it (ie: using a stale Task handle), the results are
   867         *  undefined and probably catastrophic!
   868         *
   869         */
   870        config Bool deleteTerminatedTasks = false;
   871    
   872        /*!
   873         *  Const array that holds the HookSet objects.
   874         *
   875         *  See {@link #hookfunc Hook Functions} for details about HookSets.
   876         */
   877        config HookSet hooks[length] = [];
   878    
   879        // -------- Module Functions --------
   880    
   881        /*!
   882         *  ======== addHookSet ========
   883         *  addHookSet is used in a config file to add a hook set.
   884         *
   885         *  Configures a set of hook functions for the
   886         *  Task module. Each set contains these hook functions:
   887         *
   888         *  @p(blist)
   889         *  -Register: A function called before any statically created tasks
   890         *  are initialized at runtime.  The register hook is called at boot time
   891         *  before main() and before interrupts are enabled.
   892         *  -Create: A function that is called when a task is created.
   893         *  This includes tasks that are created statically and those
   894         *  created dynamically using {@link #create} or {@link #construct}.
   895         *  The create hook is called outside of a Task_disable/enable block and
   896         *   before the task has been added to the ready list.
   897         *  -Ready: A function that is called when a task becomes ready to run.
   898         *   The ready hook is called from within a Task_disable/enable block with
   899         *   interrupts enabled.
   900         *  -Switch: A function that is called just before a task switch
   901         *  occurs. The 'prev' and 'next' task handles are passed to the Switch
   902         *  hook. 'prev' is set to NULL for the initial task switch that occurs
   903         *  during SYS/BIOS startup.  The Switch hook is called from within a
   904         *  Task_disable/enable block with interrupts enabled.
   905         *  -Exit:  A function that is called when a task exits using
   906         *  {@link #exit}.  The exit hook is passed the handle of the exiting
   907         *  task.  The exit hook is called outside of a Task_disable/enable block
   908         *  and before the task has been removed from the kernel lists.
   909         *  -Delete: A function that is called when any task is deleted at
   910         *  run-time with {@link #delete}.  The delete hook is called outside
   911         *  of a Task_disable/enable block.
   912         *  @p
   913         *  Hook functions can only be configured statically.
   914         *
   915         *  See {@link #hookfunc Hook Functions} for more details.
   916         *
   917         *  HookSet structure elements may be omitted, in which case those
   918         *  elements will not exist.
   919         *
   920         *  For example, the following configuration code defines a HookSet:
   921         *
   922         *  @p(code)
   923         *  // Hook Set 1
   924         *  Task.addHookSet({
   925         *     registerFxn: '&myRegister1',
   926         *     createFxn:   '&myCreate1',
   927         *     readyFxn:    '&myReady1',
   928         *     switchFxn:   '&mySwitch1',
   929         *     exitFxn:     '&myExit1',
   930         *     deleteFxn:   '&myDelete1'
   931         *  });
   932         *  @p
   933         *
   934         *  @param(hook)    structure of type HookSet
   935         */
   936        metaonly Void addHookSet(HookSet hook);
   937    
   938        /*!
   939         *  @_nodoc
   940         *  ======== Task_startup ========
   941         *  Start the task scheduler.
   942         *
   943         *  Task_startup signals the end of boot operations, enables
   944         *  the Task scheduler and schedules the highest priority ready
   945         *  task for execution.
   946         *
   947         *  Task_startup is called by BIOS_start() after Hwi_enable()
   948         *  and Swi_enable(). There is no return from this function as the
   949         *  execution thread is handed to the highest priority ready task.
   950         */
   951        @DirectCall
   952        Void startup();
   953    
   954        /*!
   955         *  ======== Task_enabled ========
   956         *  Returns TRUE if the Task scheduler is enabled
   957         *
   958         *  @_nodoc
   959         */
   960        @DirectCall
   961        Bool enabled();
   962    
   963        /*!
   964         *  @_nodoc
   965         *  ======== unlockSched ========
   966         *  Force a Task scheduler unlock. Used by Core_atExit() & Core_hwiFunc()
   967         *  to unlock Task scheduler before exiting.
   968         *
   969         *  This function should only be called after a Hwi_disable() has entered
   970         *  the Inter-core gate and disabled interrupts locally.
   971         */
   972        @DirectCall
   973        Void unlockSched();
   974    
   975        /*!
   976         *  ======== Task_disable ========
   977         *  Disable the task scheduler.
   978         *
   979         *  {@link #disable} and {@link #restore} control Task scheduling.
   980         *  {@link #disable} disables all other Tasks from running until
   981         *  {@link #restore} is called. Hardware and Software interrupts
   982         *  can still run.
   983         *
   984         *  {@link #disable} and {@link #restore} allow you to ensure that
   985         *  statements
   986         *  that must be performed together during critical processing are not
   987         *  preempted by other Tasks.
   988         *
   989         *  The value of the key returned is opaque to applications and is meant
   990         *  to be passed to Task_restore().
   991         *
   992         *  In the following example, the critical section is
   993         *  not preempted by any Tasks.
   994         *
   995         *  @p(code)
   996         *  key = Task_disable();
   997         *      `critical section`
   998         *  Task_restore(key);
   999         *  @p
  1000         *
  1001         *  You can also use {@link #disable} and {@link #restore} to
  1002         *  create several Tasks and allow them to be invoked in
  1003         *  priority order.
  1004         *
  1005         *  {@link #disable} calls can be nested.
  1006         *
  1007         *  @b(returns)     key for use with {@link #restore}
  1008         *
  1009         *  @a(constraints)
  1010         *  Do not call any function that can cause the current task to block
  1011         *  within a {@link #disable}/{@link #restore} block. For example,
  1012         *  {@link ti.sysbios.knl.Semaphore#pend Semaphore_pend}
  1013         *  (if timeout is non-zero),
  1014         *  {@link #sleep}, {@link #yield}, and Memory_alloc can all
  1015         *  cause blocking.
  1016         */
  1017        @DirectCall
  1018        UInt disable();
  1019    
  1020        /*!
  1021         *  @_nodoc
  1022         *  ======== enable ========
  1023         *  Enable the task scheduler.
  1024         *
  1025         *  {@link #enable} unconditionally enables the Task scheduler and
  1026         *  schedules the highest priority ready task for execution.
  1027         *
  1028         *  This function is called by {@link #startup} (which is called by
  1029         *  {@link ti.sysbios.BIOS#start BIOS_start}) to begin multi-tasking
  1030         *  operations.
  1031         */
  1032        @DirectCall
  1033        Void enable();
  1034    
  1035        /*!
  1036         *  ======== restore ========
  1037         *  Restore Task scheduling state.
  1038         *
  1039         *  {@link #disable} and {@link #restore} control Task scheduling
  1040         *  {@link #disable} disables all other Tasks from running until
  1041         *  {@link #restore} is called. Hardware and Software interrupts
  1042         *  can still run.
  1043         *
  1044         *  {@link #disable} and {@link #restore} allow you to ensure that
  1045         *  statements
  1046         *  that must be performed together during critical processing are not
  1047         *  preempted.
  1048    
  1049         *  In the following example, the critical section is not preempted
  1050         *  by any Tasks.
  1051         *
  1052         *  @p(code)
  1053         *  key = Task_disable();
  1054         *      `critical section`
  1055         *  Task_restore(key);
  1056         *  @p
  1057         *
  1058         *  You can also use {@link #disable} and {@link #restore} to create
  1059         *  several Tasks and allow them to be performed in priority order.
  1060         *
  1061         *  {@link #disable} calls can be nested.
  1062         *
  1063         *  {@link #restore} returns with interrupts enabled if the key unlocks
  1064         *  the scheduler
  1065         *
  1066         *  @param(key)     key to restore previous Task scheduler state
  1067         *
  1068         *  @a(constraints)
  1069         *  Do not call any function that can cause the current task to block
  1070         *  within a {@link #disable}/{@link #restore} block. For example,
  1071         *  {@link ti.sysbios.knl.Semaphore#pend Semaphore_pend()}
  1072         *  (if timeout is non-zero),
  1073         *  {@link #sleep}, {@link #yield}, and Memory_alloc can all
  1074         *  cause blocking.
  1075         *
  1076         *  {@link #restore} internally calls Hwi_enable() if the key passed
  1077         *  to it results in the unlocking of the Task scheduler (ie if this
  1078         *  is root Task_disable/Task_restore pair).
  1079         */
  1080        @DirectCall
  1081        Void restore(UInt key);
  1082    
  1083        /*!
  1084         *  @_nodoc
  1085         *  ======== restoreHwi ========
  1086         *  Restore Task scheduling state.
  1087         *  Used by dispatcher. Does not re-enable Ints.
  1088         */
  1089        @DirectCall
  1090        Void restoreHwi(UInt key);
  1091    
  1092        /*!
  1093         *  ======== self ========
  1094         *  Returns a handle to the currently executing Task object.
  1095         *
  1096         *  Task_self returns the object handle for the currently executing task.
  1097         *  This function is useful when inspecting the object or when the current
  1098         *  task changes its own priority through {@link #setPri}.
  1099         *
  1100         *  No task switch occurs when calling Task_self.
  1101         *
  1102         *  Task_self will return NULL until Tasking is initiated at the end of
  1103         *  BIOS_start().
  1104         *
  1105         *  @b(returns)     address of currently executing task object
  1106         */
  1107        @DirectCall
  1108        Handle self();
  1109    
  1110        /*!
  1111         *  ======== selfMacro ========
  1112         *  Returns a handle to the currently executing Task object.
  1113         *
  1114         *  Task_selfMacro is identical to {@link #self} but is implemented as
  1115         *  and inline macro.
  1116         *
  1117         *  @b(returns)     address of currently executing task object
  1118         */
  1119        @Macro
  1120        Handle selfMacro();
  1121    
  1122        /*!
  1123         *  @_nodoc
  1124         *  ======== checkStacks ========
  1125         *  Check for stack overflow.
  1126         *
  1127         *  This function is usually called by the {@link #HookSet} switchFxn to
  1128         *  make sure task stacks are valid before performing the context
  1129         *  switch.
  1130         *
  1131         *  If a stack overflow is detected on either the oldTask or the
  1132         *  newTask, a {@link #E_stackOverflow} Error is raised and the system
  1133         *  exited.
  1134         *
  1135         *  In order to work properly, {@link #checkStacks} requires that the
  1136         *  {@link #initStackFlag} set to true, which it is by default.
  1137         *
  1138         *  You can call {@link #checkStacks} directly from your application.
  1139         *  For example, you can check the current task's stack integrity
  1140         *  at any time with a call like the following:
  1141         *
  1142         *  @p(code)
  1143         *  Task_checkStacks(Task_self(), Task_self());
  1144         *  @p
  1145         *
  1146         *  @param(oldTask)  leaving Task Object Ptr
  1147         *  @param(newTask)  entering Task Object Ptr
  1148         */
  1149        @DirectCall
  1150        Void checkStacks(Handle oldTask, Handle newTask);
  1151    
  1152        /*!
  1153         *  ======== exit ========
  1154         *  Terminate execution of the current task.
  1155         *
  1156         *  Task_exit terminates execution of the current task, changing its mode
  1157         *  from {@link #Mode_RUNNING} to {@link #Mode_TERMINATED}. If all tasks
  1158         *  have been terminated, or if all remaining tasks have their
  1159         *  vitalTaskFlag attribute set to FALSE, then SYS/BIOS terminates the
  1160         *  program as a whole by calling the function System_exit with a status
  1161         *  code of 0.
  1162         *
  1163         *  Task_exit is automatically called whenever a task returns from its
  1164         *  top-level function.
  1165         *
  1166         *  Exit Hooks (see exitFxn in {@link #HookSet}) can be used to provide
  1167         *  functions that run whenever a task is terminated. The exitFxn Hooks
  1168         *  are called before the task has been blocked and marked
  1169         *  {@link #Mode_TERMINATED}.
  1170         *  See {@link #hookfunc Hook Functions} for more information.
  1171         *
  1172         *  Any SYS/BIOS function can be called from an Exit Hook function.
  1173         *
  1174         *  Calling {@link #self} within an Exit function returns the task
  1175         *  being exited. Your Exit function declaration should be similar to
  1176         *  the following:
  1177         *  @p(code)
  1178         *  Void myExitFxn(Void);
  1179         *  @p
  1180         *
  1181         *  A task switch occurs when calling Task_exit unless the program as a
  1182         *  whole is terminated
  1183         *
  1184         *  @a(constraints)
  1185         *  Task_exit cannot be called from a Swi or Hwi.
  1186         *
  1187         *  Task_exit cannot be called from the program's main() function.
  1188         */
  1189        @DirectCall
  1190        Void exit();
  1191    
  1192        /*!
  1193         *  ======== sleep ========
  1194         *  Delay execution of the current task.
  1195         *
  1196         *  Task_sleep changes the current task's mode from {@link #Mode_RUNNING}
  1197         *  to {@link #Mode_BLOCKED}, and delays its execution for nticks
  1198         *  increments of the {@link Clock system clock}. The actual time
  1199         *  delayed can be up to 1 system clock tick less than nticks due to
  1200         *  granularity in system timekeeping and the time elapsed per
  1201         *  tick is determined by {@link Clock#tickPeriod Clock_tickPeriod}.
  1202         *
  1203         *  After the specified period of time has elapsed, the task reverts to
  1204         *  the {@link #Mode_READY} mode and is scheduled for execution.
  1205         *
  1206         *  A task switch always occurs when calling Task_sleep if nticks > 0.
  1207         *
  1208         *  @param(nticks)  number of system clock ticks to sleep
  1209         *
  1210         *  @a(constraints)
  1211         *  Task_sleep cannot be called from a Swi or Hwi, or within a
  1212         *  {@link #disable} / {@link #restore} block.
  1213         *
  1214         *  Task_sleep cannot be called from the program's main() function.
  1215         *
  1216         *  Task_sleep should not be called from within an Idle function. Doing
  1217         *  so prevents analysis tools from gathering run-time information.
  1218         *
  1219         *  nticks cannot be {@link ti.sysbios.BIOS#WAIT_FOREVER BIOS_WAIT_FOREVER}.
  1220         */
  1221        @DirectCall
  1222        Void sleep(UInt nticks);
  1223    
  1224        /*!
  1225         *  ======== yield ========
  1226         *  Yield processor to equal priority task.
  1227         *
  1228         *  Task_yield yields the processor to another task of equal priority.
  1229         *
  1230         *  A task switch occurs when you call Task_yield if there is an equal
  1231         *  priority task ready to run.
  1232         *
  1233         *  Tasks of higher priority preempt the currently running task without
  1234         *  the need for a call to Task_yield. If only lower-priority tasks are
  1235         *  ready to run when you call Task_yield, the current task continues to
  1236         *  run. Control does not pass to a lower-priority task.
  1237         *
  1238         *  @a(constraints)
  1239         *  When called within an Hwi, the code sequence calling Task_yield
  1240         *  must be invoked by the Hwi dispatcher.
  1241         *
  1242         *  Task_yield cannot be called from the program's main() function.
  1243         */
  1244        @DirectCall
  1245        Void yield();
  1246    
  1247        /*!
  1248         *  @_nodoc
  1249         *  ======== getIdleTask ========
  1250         *  returns a handle to the idle task object (for core 0)
  1251         */
  1252        @DirectCall
  1253        Handle getIdleTask();
  1254    
  1255        /*!
  1256         *  @_nodoc
  1257         *  ======== getIdleTaskHandle ========
  1258         *  returns a handle to the idle task object for the specified coreId
  1259         */
  1260        @DirectCall
  1261        Handle getIdleTaskHandle(UInt coreId);
  1262    
  1263        /*
  1264         *  @_nodoc
  1265         *  ======== startCore ========
  1266         *  begin tasking on a core
  1267         */
  1268        @DirectCall
  1269        Void startCore(UInt coreId);
  1270    
  1271        /*!
  1272         *  ======== getNickName ========
  1273         *
  1274         */
  1275        metaonly String getNickName(Any tskView);
  1276    
  1277    instance:
  1278    
  1279        /*!
  1280         *  ======== create ========
  1281         *  Create a Task.
  1282         *
  1283         *  Task_create creates a new task object. If successful, Task_create
  1284         *  returns the handle of the new task object. If unsuccessful,
  1285         *  Task_create returns NULL unless it aborts.
  1286         *
  1287         *  The fxn parameter uses the {@link #FuncPtr} type to pass a pointer to
  1288         *  the function the Task object should run. For example, if myFxn is a
  1289         *  function in your program, your C code can create a Task object
  1290         *  to call that
  1291         *  function as follows:
  1292         *
  1293         *  @p(code)
  1294         *  Task_Params taskParams;
  1295         *
  1296         *  // Create task with priority 15
  1297         *  Task_Params_init(&taskParams);
  1298         *  taskParams.stackSize = 512;
  1299         *  taskParams.priority = 15;
  1300         *  Task_create((Task_FuncPtr)myFxn, &taskParams, &eb);
  1301         *  @p
  1302         *
  1303         *  The following statements statically create a task in the
  1304         *  configuration file:
  1305         *
  1306         *  @p(code)
  1307         *  var params = new Task.Params;
  1308         *  params.instance.name = "tsk0";
  1309         *  params.arg0 = 1;
  1310         *  params.arg1 = 2;
  1311         *  params.priority = 1;
  1312         *  Task.create('&tsk0_func', params);
  1313         *  @p
  1314         *
  1315         *  If NULL is passed instead of a pointer to an actual Task_Params
  1316         *  struct, a
  1317         *  default set of parameters is used. The "eb" is an error block that
  1318         *  you can use
  1319         *  to handle errors that may occur during Task object creation.
  1320         *
  1321         *  The newly created task is placed in {@link #Mode_READY} mode, and is
  1322         *  scheduled to begin concurrent execution of the following function
  1323         *  call:
  1324         *
  1325         *  @p(code)
  1326         *  (*fxn)(arg1, arg2);
  1327         *  @p
  1328         *
  1329         *  As a result of being made ready to run, the task runs any
  1330         *  application-wide Ready functions that have been specified.
  1331         *
  1332         *  Task_exit is automatically called if and when the task returns
  1333         *  from fxn.
  1334         *
  1335         *  @p(html)
  1336         *  <B>Create Hook Functions</B>
  1337         *  @p
  1338         *
  1339         *  You can specify application-wide Create hook functions in your config
  1340         *  file that run whenever a task is created. This includes tasks that
  1341         *  are created statically and those created dynamically using
  1342         *  Task_create.
  1343         *
  1344         *  For Task objects created statically, Create functions are called
  1345         *  during the Task module initialization phase of the program startup
  1346         *  process prior to main().
  1347         *
  1348         *  For Task objects created dynamically, Create functions
  1349         *  are called after the task handle has been initialized but before the
  1350         *  task has been placed on its ready queue.
  1351         *
  1352         *  Any SYS/BIOS function can be called from Create functions.
  1353         *  SYS/BIOS passes the task handle of the task being created to each of
  1354         *  the Create functions.
  1355         *
  1356         *  All Create function declarations should be similar to this:
  1357         *  @p(code)
  1358         *  Void myCreateFxn(Task_Handle task);
  1359         *  @p
  1360         *
  1361         *  @param(fxn)     Task Function
  1362         *
  1363         *  @a(constraints)
  1364         *  @p(blist)
  1365         *  - The fxn parameter and the name attribute cannot be NULL.
  1366         *  - The priority attribute must be less than or equal to
  1367         *  ({@link #numPriorities} - 1) and greater than or equal to one (1)
  1368         *  (priority 0 is owned by the Idle task).
  1369         *  - The priority can be set to -1 for tasks that will not execute
  1370         *  until another task changes the priority to a positive value.
  1371         *  - The stackHeap attribute must identify a valid memory Heap.
  1372         *  @p
  1373         */
  1374        @DirectCall
  1375        create(FuncPtr fxn);
  1376    
  1377        // -------- Handle Parameters --------
  1378    
  1379        /*! Task function argument. Default is 0 */
  1380        config UArg arg0 = 0;
  1381    
  1382        /*! Task function argument. Default is 0 */
  1383        config UArg arg1 = 0;
  1384    
  1385        /*!
  1386         *  Task priority (0 to Task.numPriorities-1, or -1).
  1387         *  Default is 1.
  1388         */
  1389        config Int priority = 1;
  1390    
  1391        /*!
  1392         *  Task stack pointer. Default = null.
  1393         *
  1394         *  Null indicates that the stack is to be allocated by create().
  1395         *
  1396         *  Example: To statically initialize "tsk0"'s stack to a literal
  1397         *  address, use the following syntax:
  1398         *
  1399         *  @p(code)
  1400         *      Program.global.tsk0.stack = $addr(literal);
  1401         *  @p
  1402         *
  1403         */
  1404        config Ptr stack = null;
  1405    
  1406        /*!
  1407         *  Task stack size in MAUs.
  1408         *
  1409         *  The default value of 0 means that the module config
  1410         *  {@link #defaultStackSize} is used.
  1411         */
  1412        config SizeT stackSize = 0;
  1413    
  1414        /*!
  1415         *  Mem section used for statically created task stacks.
  1416         *
  1417         *  Default is inherited from module config defaultStackSection.
  1418         */
  1419        metaonly config String stackSection;
  1420    
  1421        /*!
  1422         *  Mem heap used for dynamically created task stack.
  1423         *
  1424         *  The default value of NULL means that the module config
  1425         *  {@link #defaultStackHeap} is used.
  1426         */
  1427        config IHeap.Handle stackHeap = null;
  1428    
  1429        /*! Environment data struct. */
  1430        config Ptr env = null;
  1431    
  1432        /*!
  1433         *  Exit system immediately when the last task with this
  1434         *  flag set to TRUE has terminated.
  1435         *
  1436         *  Default is true.
  1437         */
  1438        config Bool vitalTaskFlag = true;
  1439    
  1440        /*!
  1441         *  The core which this task is to run on. Default is Task_AFFINITY_NONE
  1442         *
  1443         *  If there is a compelling reason for a task to be pinned to a
  1444         *  particular core, then setting 'affinity' to the corresponding core
  1445         *  id will force the task to only be run on that core.
  1446         *
  1447         *  The default affinity is inherited from {@link #defaultAffinity
  1448         *  Task.defaultAffinity}
  1449         *  which in turn defaults to {@link #AFFINITY_NONE Task_AFFINITY_NONE},
  1450         *  which means the task can be run on either core.
  1451         *
  1452         *  Furthermore,  Task_AFFINITY_NONE implies that the task can be moved
  1453         *  from core to core as deemed necessary by the Task scheduler in order
  1454         *  to keep the two highest priority ready tasks running simultaneously.
  1455         */
  1456        config UInt affinity;
  1457    
  1458        // -------- Handle Functions --------
  1459    
  1460        /*!
  1461         *  @_nodoc
  1462         *  ======== getArg0 ========
  1463         *  Returns arg0 passed via params to create.
  1464         *
  1465         *  @b(returns)     task's arg0
  1466         */
  1467        @DirectCall
  1468        UArg getArg0();
  1469    
  1470        /*!
  1471         *  @_nodoc
  1472         *  ======== getArg1 ========
  1473         *  Returns arg1 passed via params to create.
  1474         *
  1475         *  @b(returns)     task's arg1
  1476         */
  1477        @DirectCall
  1478        UArg getArg1();
  1479    
  1480        /*!
  1481         *  ======== getEnv ========
  1482         *  Get task environment pointer.
  1483         *
  1484         *  Task_getEnv returns the environment pointer of the specified task. The
  1485         *  environment pointer references an arbitrary application-defined data
  1486         *  structure.
  1487         *
  1488         *  If your program uses multiple hook sets, {@link #getHookContext}
  1489         *  allows you to get environment pointers you have set for a particular
  1490         *  hook set and Task object combination.
  1491         *
  1492         *  @b(returns)     task environment pointer
  1493         */
  1494        @DirectCall
  1495        Ptr getEnv();
  1496    
  1497        /*!
  1498         *  ======== getFunc ========
  1499         *  Get Task function and arguments
  1500         *
  1501         *  If either arg0 or arg1 is NULL, then the corresponding argument is not
  1502         *  returned.
  1503         *
  1504         *  @param(arg0)    pointer for returning Task's first function argument
  1505         *  @param(arg1)    pointer for returning Task's second function argument
  1506         *
  1507         *  @b(returns)     Task function
  1508         */
  1509        @DirectCall
  1510        FuncPtr getFunc(UArg *arg0, UArg *arg1);
  1511    
  1512        /*!
  1513         *  ======== getHookContext ========
  1514         *  Get hook set's context for a task.
  1515         *
  1516         *  For example, this C code gets the HookContext, prints it,
  1517         *  and sets a new value for the HookContext.
  1518         *
  1519         *  @p(code)
  1520         *  Ptr pEnv;
  1521         *  Task_Handle myTask;
  1522         *  Int myHookSetId1;
  1523         *
  1524         *  pEnv = Task_getHookContext(task, myHookSetId1);
  1525         *
  1526         *  System_printf("myEnd1: pEnv = 0x%lx, time = %ld\n",
  1527         *                (ULong)pEnv, (ULong)Timestamp_get32());
  1528         *
  1529         *  Task_setHookContext(task, myHookSetId1, (Ptr)0xc0de1);
  1530         *  @p
  1531         *
  1532         *  See {@link #hookfunc Hook Functions} for more details.
  1533         *
  1534         *  @param(id)      hook set ID
  1535         *  @b(returns)     hook set context for task
  1536         */
  1537        @DirectCall
  1538        Ptr getHookContext(Int id);
  1539    
  1540        /*!
  1541         *  ======== getPri ========
  1542         *  Get task priority.
  1543         *
  1544         *  Task_getPri returns the priority of the referenced task.
  1545         *
  1546         *  @b(returns)     task priority
  1547         */
  1548        @DirectCall
  1549        Int getPri();
  1550    
  1551        /*!
  1552         *  @_nodoc
  1553         *  ======== setArg0 ========
  1554         *  Set arg0 (used primarily for legacy support)
  1555         */
  1556        @DirectCall
  1557        Void setArg0(UArg arg);
  1558    
  1559        /*!
  1560         *  @_nodoc
  1561         *  ======== setArg1 ========
  1562         *  Set arg1 (used primarily for legacy support)
  1563         */
  1564        @DirectCall
  1565        Void setArg1(UArg arg);
  1566    
  1567        /*!
  1568         *  ======== setEnv ========
  1569         *  Set task environment.
  1570         *
  1571         *  Task_setEnv sets the task environment pointer to env. The
  1572         *  environment pointer references an arbitrary application-defined
  1573         *  data structure.
  1574         *
  1575         *  If your program uses multiple hook sets, {@link #setHookContext}
  1576         *  allows you to set environment pointers for any
  1577         *  hook set and Task object combination.
  1578         *
  1579         *  @param(env)     task environment pointer
  1580         */
  1581        @DirectCall
  1582        Void setEnv(Ptr env);
  1583    
  1584        /*!
  1585         *  ======== setHookContext ========
  1586         *  Set hook instance's context for a task.
  1587         *
  1588         *  For example, this C code gets the HookContext, prints it,
  1589         *  and sets a new value for the HookContext.
  1590         *
  1591         *  @p(code)
  1592         *  Ptr pEnv;
  1593         *  Task_Handle myTask;
  1594         *  Int myHookSetId1;
  1595         *
  1596         *  pEnv = Task_getHookContext(task, myHookSetId1);
  1597         *
  1598         *  System_printf("myEnd1: pEnv = 0x%lx, time = %ld\n",
  1599         *                (ULong)pEnv, (ULong)Timestamp_get32());
  1600         *
  1601         *  Task_setHookContext(task, myHookSetId1, (Ptr)0xc0de1);
  1602         *  @p
  1603         *
  1604         *  See {@link #hookfunc Hook Functions} for more details.
  1605         *
  1606         *  @param(id)              hook set ID
  1607         *  @param(hookContext)     value to write to context
  1608         */
  1609        @DirectCall
  1610        Void setHookContext(Int id, Ptr hookContext);
  1611    
  1612        /*!
  1613         *  ======== setPri ========
  1614         *  Set a task's priority
  1615         *
  1616         *  Task_setpri sets the execution priority of task to newpri, and returns
  1617         *  that task's old priority value. Raising or lowering a task's priority
  1618         *  does not necessarily force preemption and re-scheduling of the caller:
  1619         *  tasks in the {@link #Mode_BLOCKED} mode remain suspended despite a
  1620         *  change in priority; and tasks in the {@link #Mode_READY} mode gain
  1621         *  control only if their new priority is greater than that of the
  1622         *  currently executing task.
  1623         *
  1624         *  newpri should be set to a value greater than or equal to 1 and
  1625         *  less than or equal to ({@link #numPriorities} - 1).  newpri can also
  1626         *  be set to -1 which puts the the task into the INACTIVE state and the
  1627         *  task will not run until its priority is raised at a later time by
  1628         *  another task.  Priority 0 is reserved for the idle task.
  1629         *  If newpri equals ({@link #numPriorities} - 1), execution of the task
  1630         *  effectively locks out all other program activity, except for the
  1631         *  handling of interrupts.
  1632         *
  1633         *  The current task can change its own priority (and possibly preempt its
  1634         *  execution) by passing the output of {@link #self} as the value of the
  1635         *  task parameter.
  1636         *
  1637         *  A context switch occurs when calling Task_setpri if a currently
  1638         *  running task priority is set lower than the priority of another
  1639         *  currently ready task, or if another ready task is made to have a
  1640         *  higher priority than the currently running task.
  1641         *
  1642         *  Task_setpri can be used for mutual exclusion.
  1643         *
  1644         *  If a task's new priority is different than its previous priority,
  1645         *  then its relative placement in its new ready task priority
  1646         *  queue can be different than the one it was removed from. This can
  1647         *  effect the relative order in which it becomes the running task.
  1648         *
  1649         *  The effected task is placed at the head of its new priority queue
  1650         *  if it is the currently running task. Otherwise it is placed at
  1651         *  at the end of its new task priority queue.
  1652         *
  1653         *  @param(newpri) task's new priority
  1654         *  @b(returns)     task's old priority
  1655         *
  1656         *  @a(constraints)
  1657         *  newpri must be a value between 1 and ({@link #numPriorities} - 1) or -1.
  1658         *
  1659         *  The task cannot be in the {@link #Mode_TERMINATED} mode.
  1660         *
  1661         *  The new priority should not be zero (0). This priority level is
  1662         *  reserved for the Idle task.
  1663         */
  1664        @DirectCall
  1665        UInt setPri(Int newpri);
  1666    
  1667        /*!
  1668         *  ======== stat ========
  1669         *  Retrieve the status of a task.
  1670         *
  1671         *  Task_stat retrieves attribute values and status information about a
  1672         *  task.
  1673         *
  1674         *  Status information is returned through statbuf, which references a
  1675         *  structure of type {@link #Stat}.
  1676         *
  1677         *  When a task is preempted by a software or hardware interrupt, the task
  1678         *  execution mode returned for that task by Task_stat is still
  1679         *  {@link #Mode_RUNNING}  because the task runs when the preemption ends.
  1680         *
  1681         *  The current task can inquire about itself by passing the output of
  1682         *  {@link #self} as the first argument to Task_stat. However, the task
  1683         *  stack pointer (sp) in the {@link #Stat} structure is the value from
  1684         *  the previous context switch.
  1685         *
  1686         *  Task_stat has a non-deterministic execution time. As such, it is not
  1687         *  recommended to call this API from Swis or Hwis.
  1688         *
  1689         *  @param(statbuf) pointer to task status structure
  1690         *
  1691         *  @a(constraints)
  1692         *  statbuf cannot be NULL;
  1693         */
  1694        @DirectCall
  1695        Void stat(Stat *statbuf);
  1696    
  1697        /*!
  1698         *  ======== getMode ========
  1699         *  Retrieve the {@link #Mode} of a task.
  1700         */
  1701        @DirectCall
  1702        Mode getMode();
  1703    
  1704        /*!
  1705         *  ======== setAffinity ========
  1706         *  Set task's core affinity.
  1707         *
  1708         *  If the new core ID is different than the current core affinity
  1709         *  a reschedule will be performed immediately.
  1710         *
  1711         *  @a(constraints)
  1712         *  Must NOT be called with interrupts disabled
  1713         *  (ie within a Hwi_disable()/Hwi_restore() block).
  1714         *
  1715         *  Must NOT be called with tasking disabled
  1716         *  (ie within a Task_disable()/Task_restore() block).
  1717         *
  1718         *  @b(returns)     task's previous core affinity
  1719         */
  1720        @DirectCall
  1721        UInt setAffinity(UInt coreId);
  1722    
  1723        /*!
  1724         *  ======== getAffinity ========
  1725         *  Return task's core affinity.
  1726         *
  1727         *  @b(returns)     task's current core affinity
  1728         */
  1729        @DirectCall
  1730        UInt getAffinity();
  1731    
  1732        /*!
  1733         *  @_nodoc
  1734         *  ======== block ========
  1735         *  Block a task.
  1736         *
  1737         *  Remove a task from its ready list.
  1738         *  The effect of this API is manifest the next time the internal
  1739         *  Task scheduler is invoked.
  1740         *  This can be done directly by embedding the call within a
  1741         *  {@link #disable}/{@link #restore} block.
  1742         *  Otherwise, the effect will be manifest as a result of processing
  1743         *  the next dispatched interrupt, or by posting a Swi, or by falling
  1744         *  through the task function.
  1745         *
  1746         *  @a(constraints)
  1747         *  If called from within a Hwi or a Swi, or main(), there is no need
  1748         *  to embed the call within a {@link #disable}/{@link #restore} block.
  1749         */
  1750        @DirectCall
  1751        Void block();
  1752    
  1753        /*!
  1754         *  @_nodoc
  1755         *  ======== unblock ========
  1756         *  Unblock a task.
  1757         *
  1758         *  Place task in its ready list.
  1759         *  The effect of this API is manifest the next time the internal
  1760         *  Task scheduler is invoked.
  1761         *  This can be done directly by embedding the call within a
  1762         *  {@link #disable}/{@link #restore} block.
  1763         *  Otherwise, the effect will be manifest as a result of processing
  1764         *  the next dispatched interrupt, or by posting a Swi, or by falling
  1765         *  through the task function.
  1766         *
  1767         *  @a(constraints)
  1768         *  If called from within a Hwi or a Swi, or main(), there is no need
  1769         *  to embed the call within a {@link #disable}/{@link #restore} block.
  1770         */
  1771        @DirectCall
  1772        Void unblock();
  1773    
  1774        /*!
  1775         *  @_nodoc
  1776         *  ======== blockI ========
  1777         *  Block a task.
  1778         *
  1779         *  Remove a task from its ready list.
  1780         *  Must be called within Task_disable/Task_restore block
  1781         *  with interrupts disabled.
  1782         *  This API is meant to be used internally.
  1783         */
  1784        @DirectCall
  1785        Void blockI();
  1786    
  1787        /*!
  1788         *  @_nodoc
  1789         *  ======== unblockI ========
  1790         *  Unblock a task.
  1791         *
  1792         *  Place task in its ready list.
  1793         *  Must be called within Task_disable/Task_restore block
  1794         *  with interrupts disabled.
  1795         *  This API is meant to be used internally.
  1796         *
  1797         *  @param(hwiKey) key returned from Hwi_disable()
  1798         */
  1799        @DirectCall
  1800        Void unblockI(UInt hwiKey);
  1801    
  1802    internal:   /* not for client use */
  1803    
  1804        /*! Target-specific support functions. */
  1805        proxy SupportProxy inherits ti.sysbios.interfaces.ITaskSupport;
  1806    
  1807        /*
  1808         *  ======== schedule ========
  1809         *  Find highest priority ready task and invoke it.
  1810         *
  1811         *  Must be called with interrupts disabled.
  1812         */
  1813        Void schedule();
  1814    
  1815        /*
  1816         *  ======== enter ========
  1817         *  Task's initial entry point before entering task function.
  1818         */
  1819        Void enter();
  1820    
  1821        /*
  1822         *  ======== sleepTimeout ========
  1823         *  This function is the clock event handler for sleep.
  1824         */
  1825        Void sleepTimeout(UArg arg);
  1826    
  1827        /*
  1828         *  ======== postInit ========
  1829         *  finish initializing static and dynamic Tasks
  1830         */
  1831        Int postInit(Object *task, Error.Block *eb);
  1832    
  1833        /*
  1834         *  Number of statically constructed Task objects.
  1835         *  Shouldn't be set directly by the user's
  1836         *  config (it gets set by instance$static$init).
  1837         */
  1838        config UInt numConstructedTasks = 0;
  1839    
  1840        /*
  1841         *  ======== allBlockedFunction ========
  1842         *  default function to be called
  1843         */
  1844        Void allBlockedFunction();
  1845    
  1846        /*
  1847         *  ======== deleteTerminatedTasksFunc ========
  1848         *  Idle func that deletes the first terminated task it finds
  1849         *  in the queue of dynamically created tasks
  1850         */
  1851        Void deleteTerminatedTasksFunc();
  1852    
  1853        /*
  1854         *  ======== Task_processVitalTasks ========
  1855         *  Call BIOS_exit() when last vitalTask exits or is
  1856         *  deleted.
  1857         */
  1858        Void processVitalTaskFlag(Object *task);
  1859    
  1860        /*
  1861         *  ======== startupHookFunc ========
  1862         *  Called by core 0 just before switch to first task
  1863         */
  1864        config Void (*startupHookFunc)(Void) = null;
  1865    
  1866        /*
  1867         *  Common object used by all blocked tasks to enable Task_delete()
  1868         *  to remove a task from any pend Q it is placed on while blocked.
  1869         */
  1870        struct PendElem {
  1871            Queue.Elem      qElem;
  1872            Task.Handle     task;
  1873            Clock.Handle    clock;
  1874        };
  1875    
  1876        struct Instance_State {
  1877            Queue.Elem      qElem;          // Task's readyQ element
  1878            volatile Int    priority;       // Task priority
  1879            UInt            mask;           // curSet mask = 1 << priority
  1880            Ptr             context;        // ptr to Task's saved context
  1881                                            // while not in RUNNING mode.
  1882            Mode            mode;           // READY, BLOCKED, RUNNING, etc
  1883            PendElem        *pendElem;      // ptr to Task, Semaphore, Event,
  1884                                            // or GateMutexPri PendElem
  1885            SizeT           stackSize;      // Task's stack buffer size
  1886            Char            stack[];        // buffer used for Task's stack
  1887            IHeap.Handle    stackHeap;      // Heap to allocate stack from
  1888            FuncPtr         fxn;            // Task function
  1889            UArg            arg0;           // Task function 1st arg
  1890            UArg            arg1;           // Task function 2nd arg
  1891            Ptr             env;            // Task environment pointer
  1892            Ptr             hookEnv[];      // ptr to Task's hook env array
  1893            Bool            vitalTaskFlag;  // TRUE = shutdown system if
  1894                                            // last task like this exits
  1895            Queue.Handle    readyQ;         // This Task's readyQ
  1896            UInt            curCoreId;      // Core this task is currently running on.
  1897            UInt            affinity;       // Core this task must run on
  1898                                            // Task_AFFINITY_NONE = don't care
  1899        };
  1900    
  1901        struct Module_State {
  1902            volatile Bool   locked;         // Task scheduler locked flag
  1903            volatile UInt   curSet;         // Bitmask reflects readyQ states
  1904            Bool            workFlag;       // Scheduler work is pending.
  1905                                            // Optimization. Must be set
  1906                                            // whenever readyQs are modified.
  1907            UInt            vitalTasks;     // number of tasks with
  1908                                            // vitalTaskFlag = true
  1909            Handle          curTask;        // current Task instance
  1910            Queue.Handle    curQ;           // current Task's readyQ
  1911            Queue.Object    readyQ[];       // Task ready queues
  1912    
  1913            volatile UInt   smpCurSet[];    // Bitmask reflects readyQ states
  1914                                            // curSet[n] = core n
  1915                                            // curSet[Core.numCores] = don't care
  1916            volatile UInt   smpCurMask[];   // mask of currently running tasks
  1917            Handle          smpCurTask[];   // current Task instance ([0] = core 0, etc)
  1918            Queue.Handle    smpReadyQ[];    // core ready queues
  1919                                            // [0] = core0 readyQs
  1920                                            // [1] = core1 readyQs
  1921                                            // [numCores] = don't care readyQs
  1922            Queue.Object    inactiveQ;      // Task's with -1 priority
  1923            Queue.Object    terminatedQ;    // terminated dynamically created Tasks
  1924    
  1925            Handle          idleTask[];             // Idle Task handles
  1926            Handle          constructedTasks[];     // array of statically
  1927                                                    // constructed Tasks
  1928        };
  1929    }
  1930