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