1    /*
     2     * Copyright (c) 2013-2018, 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     *  ======== Load.xdc ========
    34     */
    35    
    36    package ti.sysbios.utils;
    37    
    38    import xdc.rov.ViewInfo;
    39    
    40    import ti.sysbios.knl.Queue;
    41    import ti.sysbios.knl.Task;
    42    import ti.sysbios.knl.Swi;
    43    import ti.sysbios.interfaces.IHwi;
    44    
    45    import xdc.rov.ViewInfo;
    46    import xdc.runtime.Diags;
    47    import xdc.runtime.Log;
    48    import xdc.runtime.Error;
    49    
    50    /*!
    51     *  ======== Load ========
    52     *  The Load module reports execution times and load information for threads
    53     *  in a system.
    54     *
    55     *  SYS/BIOS manages four distinct levels of execution threads: hardware
    56     *  interrupt service routines, software interrupt routines, tasks, and
    57     *  background idle functions. This module reports execution time and load on a
    58     *  per-task basis, and also provides information globally for hardware
    59     *  interrupt service routines, software interrupt routines and idle functions
    60     *  (in the form of the idle task). It can also report an estimate of the
    61     *  global CPU load.
    62     *
    63     *  Execution time is reported in units of
    64     *  {@link xdc.runtime.Timestamp Timestamp} counts, and load is reported
    65     *  in percentages.
    66     *
    67     *  By default, load data is gathered for Task threads.
    68     *  {@link #hwiEnabled hwiEnabled}, {@link #swiEnabled swiEnabled}
    69     *  and {@link #taskEnabled taskEnabled} can be used to select which
    70     *  type(s) of threads are monitored. These statistics are automatically
    71     *  recorded to the load module's logger instance. Users can also choose
    72     *  to call {@link #getTaskLoad}, {@link #getGlobalSwiLoad},
    73     *  {@link #getGlobalHwiLoad} and {@link #getCPULoad} at any time to obtain the
    74     *  statistics at runtime.
    75     *
    76     *  The module relies on {@link #update} to be called to compute load and
    77     *  execution times from the time when {@link #update} was last called. This
    78     *  is automatically done for every period specified by
    79     *  {@link #windowInMs windowInMs} in an {@link ti.sysbios.knl.Idle Idle}
    80     *  function when {@link #updateInIdle updateInIdle} is
    81     *  set to true. The time between two calls to {@link #update} is called the
    82     *  benchmark time window.
    83     *
    84     *  By passing in a function pointer of type
    85     *  Void(*{@link #postUpdate})(Void) through the
    86     *  {@link #postUpdate postUpdate} config parameter, one can specify a
    87     *  {@link #postUpdate postUpdate} function that is
    88     *  automatically called by {@link #update} immediately after the statistics
    89     *  have been computed at the end of a benchmark time window.  Setting this
    90     *  function allows the user to optionally post-process the thread statistics
    91     *  once and only once per benchmark window.
    92     *
    93     *  Advanced users could optionally omit calling {@link #update} in the idle
    94     *  loop by setting {@link #updateInIdle updateInIdle} to false. They can
    95     *  then call {@link #update} somewhere else (e.g. in a periodic higher
    96     *  priority Task) instead to ensure statistics are computed even when the
    97     *  system is never idle.
    98     *
    99     *  @a(CPU Load Calculation Methods)
   100     *
   101     *  The CPU load is computed in three different ways,
   102     *  depending on what threads are monitored, and whether or not Power
   103     *  management is used to idle the CPU when no threads are running.
   104     *
   105     *  @p(html)
   106     *  <B>Task Load Disabled and No Power Management</B>
   107     *  @p
   108     *
   109     *  The first method of calculating CPU load is used when
   110     *  Task load logging is disabled, ie, {@link #taskEnabled}
   111     *  is false, and Power management is not used. The CPU load is computed as
   112     *  the percentage of time in the benchmark window which was NOT spent in the
   113     *  idle loop. More specifically, the load is computed as follows:
   114     *
   115     *  global CPU load = 100 * (1 - (min. time for a trip around idle loop *
   116     *      # times in idle loop)/(benchmark time window) )
   117     *
   118     *  Any work done in the idle loop is included in the CPU load - in other
   119     *  words, any time spent in the loop beyond the shortest trip around the idle
   120     *  loop is counted as non-idle time.
   121     *
   122     *  This method works fairly well if the timestamp frequency is
   123     *  sufficiently high (for example, if it's equal to the CPU frequency).
   124     *  The CPU load accuracy can also be affected by caching and user idle functions.
   125     *
   126     *  @p(html)
   127     *  <B>Task Load Enabled and No Power Management</B>
   128     *  @p
   129     *
   130     *  The second method of calculating CPU load is used when Task load logging
   131     *  is enabled ({@link #taskEnabled} = true) and Power management is not used.
   132     *  In this case the CPU load is calculted as
   133     *
   134     *      global CPU load = 100 - (Idle task load)
   135     *
   136     *  This prevents any discrepancy between the calculated CPU load had we
   137     *  used the first method, and 100 - the Idle task load.  If Swi and
   138     *  Hwi load logging are not enabled, however, time spent in a Swi
   139     *  or Hwi will be charged to the task in which it ran.  This will
   140     *  affect the accuracy of the CPU (and Task) load, but the trade off
   141     *  is more overhead to do the Hwi and Swi load logging.
   142     *
   143     *  @p(html)
   144     *  <B>Power Management Enabled</B>
   145     *  @p
   146     *
   147     *  This method applies to targets that have a SYS/BIOS Power
   148     *  module.  It does not apply to targets
   149     *  where Power management is part of TI-RTOS (e.g., CC3200).
   150     *
   151     *  The third method of calculating CPU load is used when Power
   152     *  management is enabled.  In this case, the idle loop has a
   153     *  function brought in by the Power module that idles the CPU.
   154     *  The timestamp timer must continue to run during idle, in order
   155     *  to measure idle and non-idle time, however.  This method of
   156     *  calculating CPU load plugs a Hwi hook function which is run
   157     *  at the beginning of every Hwi. An idle function will call
   158     *  Timestamp_get32() to mark the beginning of idle time, and
   159     *  when the first Hwi causes the CPU to come out of idle, the
   160     *  Hwi hook function will call Timestamp_get32() to mark the end
   161     *  of idle time.  The idle function accumulates the idle time
   162     *  and total time elapsed, and the CPU load is calculated as:
   163     *
   164     *    global CPU load = 100 * (1 - idle time / time elapsed)
   165     *
   166     *  With this method of CPU load calculation, all idle functions are
   167     *  included in the CPU load.  When Power is enabled, Task, Swi, and
   168     *  Hwi load logging can be enabled, but you may find that the
   169     *  CPU load does not equal (100 - idle task load), since the CPU load
   170     *  is calculated as the percentage of time that the processor is not
   171     *  powered down, while the idle task load includes powered down time
   172     *  plus time executing idle functions.
   173     *
   174     *  @p(html)
   175     *  <B>Power Management Enabled outside of SYS/BIOS</B>
   176     *  @p
   177     *
   178     *  Some targets have Power management support outside of SYS/BIOS.  For
   179     *  example, CC3200 and CC26XX devices have Power management in TI-RTOS.
   180     *  In these cases, the best way to get CPU load is to make sure that
   181     *  {@link #taskEnabled} is set to true.  Then the CPU load will be
   182     *  calculated as 100 - the idle task load.  However, for BIOS in ROM builds,
   183     *  this method will not work, as Task hooks are not allowed.  So to
   184     *  use Load for any devices that support BIOS in ROM builds, make
   185     *  sure the ROM build is disabled.
   186     *
   187     *  @a(Examples)
   188     *  Configuration example: The following statements configure the Load module
   189     *  to obtain output in the CCS output window. This is useful for early
   190     *  development without RTA tools support in SYS/BIOS:
   191     *
   192     *  @p(code)
   193     *  var System = xdc.useModule('xdc.runtime.System');
   194     *  var SysStd = xdc.useModule('xdc.runtime.SysStd');
   195     *  System.SupportProxy = SysStd;
   196     *
   197     *  var Load = xdc.useModule('ti.sysbios.utils.Load');
   198     *  var LoggerSys = xdc.useModule('xdc.runtime.LoggerSys');
   199     *  var Defaults = xdc.useModule('xdc.runtime.Defaults');
   200     *  var Diags = xdc.useModule('xdc.runtime.Diags');
   201     *
   202     *  // Turn on statistics log messages for Load module
   203     *  Load.common$.diags_USER4 = Diags.ALWAYS_ON;
   204     *  // Define a program-wide logger to be the System Logger
   205     *  Defaults.common$.logger = LoggerSys.create();
   206     *  @p
   207     *
   208     *  Notes on above example:
   209     *  @p(blist)
   210     *  - When using the {@link xdc.runtime.LoggerSys System Logger},
   211     *  {@link xdc.runtime.System#printf System_printf} calls are made to produce
   212     *  the output in the output window. These calls are highly intrusive
   213     *  and are only suited for early development.
   214     *
   215     *  - Also make sure your task stack sizes are large enough when using the
   216     *  {@link xdc.runtime.LoggerSys System Logger} - particularly the idle task
   217     *  stack size since logging is done in the idle task by default.
   218     *  @p
   219     *
   220     *  @a(Caveats)
   221     *  @p(nlist)
   222     *  - For the module to return accurate load values, the {@link #update}
   223     *  function must be run at least once before the Timestamp count gets to
   224     *  wrap around. This means on a platform with a 32-bit
   225     *  {@link xdc.runtime.Timestamp Timestamp} frequency that runs at 200 MHz,
   226     *  the function must be called at least once every 21 sec. With faster
   227     *  {@link xdc.runtime.Timestamp Timestamp} frequencies it would have to be
   228     *  called even more frequently.
   229     *
   230     *  - If the {@link #updateInIdle updateInIdle} option is enabled, the
   231     *  module will call {@link #update} periodically according to
   232     *  {@link #windowInMs windowInMs}. The latter must be set to a time
   233     *  interval that is below
   234     *  (2^32) * 1000 / ({@link xdc.runtime.Timestamp Timestamp} Frequency)
   235     *  milliseconds
   236     *
   237     *  - If the {@link #updateInIdle updateInIdle} option is disabled, the user is
   238     *  then responsible for calling {@link #update} more often than the above
   239     *  time interval.
   240     *
   241     *  - Load values might not add up to 100%. Because the module minimizes
   242     *  its interrupt latency and avoids locking up the system to compute all
   243     *  thread loads at once, each thread's execution time is evaluated separately
   244     *  over its own time window, which could be slightly different to that of
   245     *  another thread.
   246     *
   247     *  - When disabling monitoring of a thread type of higher priority, the
   248     *  time spent in that thread type will be counted towards time spent in
   249     *  threads of lower priority. E.g. if {@link #hwiEnabled hwiEnabled} and
   250     *  {@link #swiEnabled swiEnabled} are both false, then time spent in Hwi's and
   251     *  Swi's will be counted towards the Tasks in which the interrupts happened.
   252     *  Thus, for better accuracy, it is best to leave monitoring on for threads of
   253     *  a higher priority relative to the thread type of interest.
   254     *
   255     *  - When Task load logging is not enabled and Power management is not used,
   256     *  the implementation of {@link #getCPULoad()} self-calibrates the shortest
   257     *  path through the idle loop. It does this by keeping track of the shortest
   258     *  time between invocations of an idle function automatically inserted by the
   259     *  Load module, and assumes that to be the time it takes for one iteration
   260     *  through the idle loop. Because of this, the CPU load value is only an
   261     *  estimate since the idle loop might occasionally take longer to run
   262     *  (e.g. due to caching effects, stalls). The reported CPU load tends to be
   263     *  slightly higher than reality, especially when the load is low.
   264     *
   265     *  - If {@link #taskEnabled taskEnabled} is set to true,
   266     *  task name support will be automatically turned on so that the Load module
   267     *  can print out the task names in its log output.
   268     *
   269     *  - Currently does not support {@link xdc.runtime.Timestamp Timestamp}
   270     *  frequencies over 4 GHz.
   271     *  @p
   272     *
   273     *  @p(html)
   274     *  <h3> Calling Context </h3>
   275     *  <table border="1" cellpadding="3">
   276     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
   277     *    </colgroup>
   278     *
   279     *    <tr><th> Function                 </th><th>  Hwi   </th><th>  Swi   </th>
   280     *    <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
   281     *    <!--                                                          -->
   282     *    <tr><td> {@link #getCPULoad}      </td><td>   Y    </td><td>   Y    </td>
   283     *    <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   284     *    <tr><td> {@link #getGlobalHwiLoad}</td><td>   Y    </td><td>   Y    </td>
   285     *    <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   286     *    <tr><td> {@link #getGlobalSwiLoad}</td><td>   Y    </td><td>   Y    </td>
   287     *    <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   288     *    <tr><td> {@link #getTaskLoad}     </td><td>   Y    </td><td>   Y    </td>
   289     *    <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   290     *    <tr><td> {@link #reset}           </td><td>   Y*   </td><td>   Y*   </td>
   291     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   292     *    <tr><td> {@link #update}          </td><td>   Y*   </td><td>   Y*   </td>
   293     *    <td>   Y    </td><td>   N    </td><td>   N    </td></tr>
   294     *    <tr><td colspan="6"> Definitions: <br />
   295     *       <ul>
   296     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   297     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   298     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   299     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   300     *           <ul>
   301     *             <li> In your module startup after this module is started
   302     *    (e.g. Load_Module_startupDone() returns TRUE). </li>
   303     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   304     *             <li> During main().</li>
   305     *             <li> During BIOS.startupFxns.</li>
   306     *           </ul>
   307     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   308     *           <ul>
   309     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   310     *             <li> In your module startup before this module is started
   311     *    (e.g. Load_Module_startupDone() returns FALSE).</li>
   312     *           </ul>
   313     *       <li> <b>*</b>: Indicates only when {@link #taskEnabled taskEnabled}
   314     *    is set to false. </li>
   315     *       </ul>
   316     *    </td></tr>
   317     *  </table>
   318     *  @p
   319     */
   320    
   321    @Template("./Load.xdt")
   322    @DirectCall
   323    module Load
   324    {
   325        /*!
   326         *  ======== ModuleView ========
   327         *  @_nodoc
   328         */
   329        metaonly struct ModuleView {
   330            String cpuLoad;     /* total cpu load, in percent */
   331            String swiLoad;     /* cpu load due to Swi's, in percent */
   332            String hwiLoad;     /* cpu load due to Hwi's, in percent */
   333            String idleError;   /* estimated measurement error in one pass of idle
   334                                 * loop, in percent
   335                                 */
   336        }
   337    
   338        /*!
   339         *  ======== rovViewInfo ========
   340         *  @_nodoc
   341         */
   342        @Facet
   343        metaonly config ViewInfo.Instance rovViewInfo =
   344            ViewInfo.create({
   345                viewMap: [
   346                [
   347                    'Module',
   348                    {
   349                        type: ViewInfo.MODULE,
   350                        viewInitFxn: 'viewInitModule',
   351                        structName: 'ModuleView'
   352                    }
   353                ],
   354                ]
   355            });
   356    
   357    
   358        /* -------- Module Types -------- */
   359    
   360        /*!
   361         *  ======== FuncPtr ========
   362         *  Callback function type
   363         */
   364        typedef Void (*FuncPtr)();
   365    
   366        /*!
   367         *  ======== Stat ========
   368         *  Load statistics info
   369         */
   370        struct Stat {
   371            UInt32 threadTime;
   372            UInt32 totalTime;
   373        };
   374    
   375    
   376        /* -------- Module Configuration Parameters -------- */
   377    
   378        /*!
   379         *  ======== LS_cpuLoad ========
   380         *  This event logs the global CPU load as a percentage
   381         *
   382         *  This event is logged whenever the Diags.USER4 level is enabled
   383         *  and the load is measured.
   384         *
   385         */
   386        config Log.Event LS_cpuLoad = {
   387            mask: Diags.USER4,
   388            msg: "LS_cpuLoad: %d%%"
   389        };
   390    
   391        /*!
   392         *  ======== LS_hwiLoad ========
   393         *  This event logs the Hwi load
   394         *
   395         *  This event is logged whenever the Diags.USER4 level is enabled
   396         *  {@link #hwiEnabled} is true, and the load is measured.
   397         *
   398         *  This event logs the Hwi load, with the form:
   399         *  <load time>,<measurement time>
   400         *
   401         *  Percentage load = <load time> / <measurement time> x 100%
   402         */
   403        config Log.Event LS_hwiLoad = {
   404            mask: Diags.USER4,
   405            msg: "LS_hwiLoad: %d,%d"
   406        };
   407    
   408        /*!
   409         *  ======== LS_swiLoad ========
   410         *  This event logs the Swi load
   411         *
   412         *  This event is logged whenever the Diags.USER4 level is enabled
   413         *  {@link #swiEnabled} is true, and the load is measured.
   414         *
   415         *  This event logs the Swi load, with the form:
   416         *  <load time>,<measurement time>
   417         *
   418         *  Percentage load = <load time> / <measurement time> x 100%
   419         */
   420        config Log.Event LS_swiLoad = {
   421            mask: Diags.USER4,
   422            msg: "LS_swiLoad: %d,%d"
   423        };
   424    
   425        /*!
   426         *  ======== LS_taskLoad ========
   427         *  This event logs Task thread loads
   428         *
   429         *  This event is logged whenever the Diags.USER4 level is enabled,
   430         *  {@link #taskEnabled} is true, and the load is measured.
   431         *
   432         *  This event logs Task thread loads, with the form:
   433         *  <Task handle>,<load time>,<measurement time>,<Task function pointer>
   434         *
   435         *  Percentage load = <load time> / <measurement time> x 100%
   436         */
   437        config Log.Event LS_taskLoad = {
   438            mask: Diags.USER4,
   439            msg: "LS_taskLoad: 0x%x,%d,%d,0x%x"
   440        };
   441    
   442        /*!
   443         *  ======== postUpdate ========
   444         *  User function called after each load update
   445         *
   446         *  If non-NULL, postUpdate is run immediately after each update.
   447         */
   448        config FuncPtr postUpdate = null;
   449    
   450        /*!
   451         *  ======== updateInIdle ========
   452         *  Automatically call {@link #update} in Idle loop
   453         *
   454         *  If this parameter is set to `true`, an {@link ti.sysbios.knl.Idle Idle}
   455         *  function, which computes and updates the CPU load, is added to the
   456         *  {@link ti.sysbios.knl.Idle#run Idle loop}.
   457         */
   458        config Bool updateInIdle = true;
   459    
   460        /*!
   461         *  ======== enableCPULoadCalc ========
   462         *  Automatically update the Load module's CPU load value in
   463         *  {@link #update}.
   464         *
   465         *  If this parameter is set to `true`, Load_update() will calculate
   466         *  the CPU load for the elapsed time.  In some cases, the user may
   467         *  prefer to use the statistics gathered by the Load module and do
   468         *  the CPU load calculation themself.  Set this parameter to false,
   469         *  to disable the Load module's CPU load calculations.  This can
   470         *  improve performance of the Load_update() call.
   471         */
   472        metaonly config Bool enableCPULoadCalc = true;
   473    
   474        /*!
   475         *  ======== minIdle ========
   476         *  Specifies the minimum time used to compute idle time
   477         *
   478         *  During CPU load measurement, the minimum time observed executing
   479         *  the idle loop together with the count of the number of times the idle
   480         *  loop runs id used to compute the total idle time.  However, since the
   481         *  _actual_ time spent in the idle loop will almost always be greater
   482         *  then the observed minimum, the idle time is almost always under
   483         *  estimated.
   484         *
   485         *  This configuration parameter can be used to compensate for this
   486         *  underestimate by placing a lower bound on the minimum time used in
   487         *  the CPU measurements.  The minimum idle time used to compute CPU
   488         *  load is guarenteed to be greater than or equal to `minIdle`.
   489         */
   490        metaonly config UInt32 minIdle = 0;
   491    
   492        /*!
   493         *  ======== windowInMs ========
   494         *  Load averaging period
   495         *
   496         *  When {@link #updateInIdle} is enabled, this period determines the
   497         *  minimum elapsed time between updates of the load statistics in the
   498         *  idle loop.
   499         */
   500        config UInt windowInMs = 500;
   501    
   502        /*!
   503         *  ======== hwiEnabled ========
   504         *  Enables Hwi time monitoring
   505         *
   506         *  When this parameter is set to `true`, {@link ti.sysbios.hal.Hwi Hwi}
   507         *  processing time is accumulated between successive calls of
   508         *  {@link #update} and, as part of Load_update, an
   509         *  {@link #LS_hwiLoad event} with this cumulative time is logged.  This
   510         *  time, together with the total elapsed time, is used to estimate the
   511         *  CPU load due to any Hwi instances run between these updates.
   512         */
   513        config Bool hwiEnabled = false;
   514    
   515        /*!
   516         *  ======== swiEnabled ========
   517         *  Enables Swi time monitoring
   518         *
   519         *  When this parameter is set to `true`, Swi processing time is
   520         *  accumulated between successive calls of {@link #update} and, as
   521         *  part of Load_update, an {@link #LS_swiLoad event} with this
   522         *  cumulative time is logged.  This time together with the total
   523         *  elapsed time is used to estimate the CPU load due to any Swi
   524         *  instances run between these updates.
   525         */
   526        config Bool swiEnabled = false;
   527    
   528        /*!
   529         *  ======== taskEnabled ========
   530         *  Enables Task time monitoring
   531         *
   532         *  When this parameter is set to `true`, each Task's processing time is
   533         *  accumulated between successive calls of {@link #update} and, as
   534         *  part of Load_update, an {@link #LS_taskLoad event} with this
   535         *  cumulative time is logged for each task.  This time together with the
   536         *  total elapsed time is used to estimate the CPU load due to each Task
   537         *  run between these updates.
   538         */
   539        config Bool taskEnabled = true;
   540    
   541        /* -------- Module Functions -------- */
   542    
   543        /*!
   544         *  ======== getTaskLoad ========
   545         *  Return the load and time spent in a specific task
   546         *
   547         *  This function returns the load and time spent in a specific task
   548         *  along with the duration over which the measurement was done. Numbers
   549         *  are reported in  {@link xdc.runtime.Timestamp Timestamp} counts.
   550         *
   551         *  Task handle must be valid and have been registered with Load.
   552         *
   553         *  @param(task) Handle of the Task which time we are interested in.
   554         *  @param(stat) Load and time statistics info
   555         *  @b(returns) TRUE if success, FALSE if failure
   556         *
   557         */
   558        Bool getTaskLoad(Task.Handle task, Stat *stat);
   559    
   560        /*!
   561         *  ======== update ========
   562         *  Record thread statistics and reset all counters
   563         *
   564         *  If {@link #taskEnabled taskEnabled} is set to true, this function can
   565         *  only be called in task context.
   566         */
   567        Void update();
   568    
   569        /*!
   570         *  @_nodoc
   571         *  ======== updateCPULoad ========
   572         *  Record CPU load only.  This function is used only when Power idling
   573         *  is enabled.
   574         *
   575         *  If Power idling is available for the device and enabled, a different
   576         *  method of CPU load calculation must be used. Since the idle loop will
   577         *  not be executing while the CPU is idle, we cannot measure the idle
   578         *  time by multiplying the number of times the idle loop ran, by the
   579         *  minumum time through one iteration of the idle loop.  Instead, we
   580         *  use a {@link ti.sysbios.knl.hal.Hwi} hook function for measuring
   581         *  idle time. The hook function is run at the beginning of each Hwi,
   582         *  and the first Hwi to cause the CPU to come out of idle, will mark
   583         *  the end of idle time.
   584         *
   585         */
   586        @DirectCall
   587        Void updateCPULoad();
   588    
   589        /*!
   590         *  @_nodoc
   591         *  ======== updateLoads ========
   592         *  Record CPU load and thread loads if Task, Swi, or Hwi load logging
   593         *  is enabled. This function is called by Load_update() if Power
   594         *  management is not used.
   595         */
   596        @DirectCall
   597        Void updateLoads();
   598    
   599        /*!
   600         *  @_nodoc
   601         *  ======== updateContextsAndPost ========
   602         *  This function is called by Load_update() when Load.enableCPULoadCalc
   603         *  is false.
   604         *  Updates the current thread's time and hook contexts for all threads.
   605         *  Call the postUpdate() function.  It is up to the application to
   606         *  calculate the loads.
   607         */
   608        @DirectCall
   609        Void updateContextsAndPost();
   610    
   611        /*!
   612         *  @_nodoc
   613         *  ======== updateCurrentThreadTime ========
   614         *  Update the total time for the currently running thread.  This function
   615         *  will be called if Task, Swi, or Hwi Load logging is enabled.
   616         */
   617        @DirectCall
   618        Void updateCurrentThreadTime();
   619    
   620        /*!
   621         *  @_nodoc
   622         *  ======== updateThreadContexts ========
   623         *  Update hook contexts for all threads.  This function
   624         *  will be called if Task, Swi, or Hwi Load logging is enabled.
   625         */
   626        @DirectCall
   627        Void updateThreadContexts();
   628    
   629        /*!
   630         *  ======== reset ========
   631         *  Reset all internal load counters
   632         *
   633         *  If {@link #taskEnabled taskEnabled} is set to true, this function can
   634         *  only be called in task context.
   635         */
   636        Void reset();
   637    
   638        /*!
   639         *  ======== getGlobalSwiLoad ========
   640         *  Return the load and time spent in Swi's
   641         *
   642         *  This function returns the load and time spent in Swi's along with
   643         *  the time duration over which the measurement was done. Numbers are
   644         *  reported in  {@link xdc.runtime.Timestamp Timestamp} counts.
   645         *
   646         *  @param(stat) Load and time statistics info
   647         *  @b(returns) TRUE if success, FALSE if failure
   648         *
   649         */
   650        Bool getGlobalSwiLoad(Stat *stat);
   651    
   652        /*!
   653         *  ======== getGlobalHwiLoad ========
   654         *  Return the load and time spent in hwi's
   655         *
   656         *  This function computes the load and time spent in Hwi's along
   657         *  with the time duration over which the measurement was done. Numbers
   658         *  are reported in  {@link xdc.runtime.Timestamp Timestamp} counts.
   659         *
   660         *  @param(stat) Load and time statistics info
   661         *
   662         *  @b(returns) TRUE if success, FALSE if failure
   663         */
   664        Bool getGlobalHwiLoad(Stat *stat);
   665    
   666        /*!
   667         *  ======== getCPULoad ========
   668         *  Return an estimate of the global CPU load
   669         *
   670         *  This function returns an estimate of CPU load (% utilization of the
   671         *  CPU), with the idle time determined based on number of trips through
   672         *  the idle loop multiplied by the shortest amount of time through the
   673         *  loop.
   674         *
   675         *  This function requires the idle loop to be run during a benchmark time
   676         *  window.
   677         *
   678         *  Note: Time spent in kernel while switching to a Hwi/Swi/Task is
   679         *        considered non-idle time.
   680         *
   681         *  @b(returns) CPU load in %
   682         *
   683         */
   684        UInt32 getCPULoad();
   685    
   686        /*!
   687         *  ======== calculateLoad ========
   688         *  Compute total CPU load from a Load_Stat structure
   689         *
   690         *  This function computes percent load from the
   691         *  values in a Load_Stat structure.
   692         *
   693         *  @a(returns) Load value of a Load_Stat structure in %.
   694         */
   695        UInt32 calculateLoad(Stat *stat);
   696    
   697        /*!
   698         *  ======== setMinIdle ========
   699         *  Set lower bound on idle loop time used to compute CPU load
   700         *
   701         *  @see #minIdle
   702         */
   703        UInt32 setMinIdle(UInt32 newMinIdleTime);
   704    
   705        /*! @_nodoc
   706         *  ======== addTask ========
   707         *  Add a task to the list for benchmarking
   708         *
   709         *  If {@link #taskEnabled} is set to true, this function can only be
   710         *  called in task context.
   711         *
   712         *  @param(task) Handle of the Task to be added to the list.
   713         *  @param(env) Handle of context structure to be used by the Task
   714         */
   715        Void addTask(Task.Handle task, HookContext *env);
   716    
   717        /*! @_nodoc
   718         *  ======== removeTask ========
   719         *  Remove a task from the list for benchmarking
   720         *
   721         *  If {@link #taskEnabled} is set to true, this funciton can only be
   722         *  called in task context.
   723         *
   724         *  @param(taskHandle) Handle of the Task to be removed from the list.
   725         */
   726        Bool removeTask(Task.Handle task);
   727    
   728        /*!
   729         *  @_nodoc
   730         *  ======== idleFxn ========
   731         *  Idle function used to periodically update the Task time values
   732         */
   733        Void idleFxn();
   734    
   735        /*!
   736         *  @_nodoc
   737         *  ======== idleFxnPwr ========
   738         *  Idle function used when Power idling is enabled.
   739         */
   740        @DirectCall
   741        Void idleFxnPwr();
   742    
   743        /*!
   744         *  @_nodoc
   745         *  ======== Load_startup ========
   746         *  Initialize thread load update times.
   747         */
   748        Void startup();
   749    
   750        /* -------- Hook Functions -------- */
   751    
   752        /*!
   753         *  @_nodoc
   754         *  ======== taskCreateHook ========
   755         *  Create hook function used to initialize all task's hook context
   756         *  to NULL during creation time. Also adds the task's hook context
   757         *  when {@link #autoAddTasks} is set to true.
   758         *
   759         *  @param(task) Handle of the Task to initialize.
   760         *  @param(eb) Error block.
   761         */
   762        Void taskCreateHook(Task.Handle task, Error.Block *eb);
   763    
   764        /*!
   765         *  @_nodoc
   766         *  ======== taskDeleteHook ========
   767         *  Delete hook function used to remove the task's hook context
   768         *  when {@link #autoAddTasks} is set to true.
   769         *
   770         *  @param(task) Handle of the Task to delete.
   771         */
   772        Void taskDeleteHook(Task.Handle task);
   773    
   774        /*!
   775         *  @_nodoc
   776         *  ======== taskSwitchHook ========
   777         *  Switch hook function used to perform benchmarks
   778         *
   779         *  @param(curTask) Handle of currently executing Task.
   780         *  @param(nextTask) Handle of the next Task to run
   781         */
   782        Void taskSwitchHook(Task.Handle curTask, Task.Handle nextTask);
   783    
   784        /*!
   785         *  @_nodoc
   786         *  ======== swiBeginHook ========
   787         *  Swi begin hook function used to perform benchmarks
   788         *
   789         *  @param(swi) Handle of Swi to begin execution.
   790         */
   791        Void swiBeginHook(Swi.Handle swi);
   792    
   793        /*!
   794         *  @_nodoc
   795         *  ======== swiEndHook ========
   796         *  Swi end hook function used to perform benchmarks
   797         *
   798         *  @param(swi) Handle of Swi to end execution.
   799         */
   800        Void swiEndHook(Swi.Handle swi);
   801    
   802        /*!
   803         *  @_nodoc
   804         *  ======== hwiBeginHook ========
   805         *  Hwi begin hook function used to perform benchmarks
   806         *
   807         *  @param hwi Handle of Hwi to begin execution.
   808         */
   809        Void hwiBeginHook(IHwi.Handle hwi);
   810    
   811        /*!
   812         *  @_nodoc
   813         *  ======== hwiEndHook ========
   814         *  Hwi end hook function used to perform benchmarks
   815         *
   816         *  @param hwi Handle of Hwi to end execution.
   817         */
   818        Void hwiEndHook(IHwi.Handle hwi);
   819    
   820        /*!
   821         *  @_nodoc
   822         *  ======== taskRegHook ========
   823         *  Registration function for the module's hook
   824         *
   825         *  Moved out of the internal section for ROM purposes. This function
   826         *  is not referenced directly, so it must be a "public" function so
   827         *  that the linker does not drop it when creating a ROM image.
   828         *
   829         *  @param(id) The id of the hook for use in load.
   830         */
   831        Void taskRegHook(Int id);
   832    
   833    internal:   /* not for client use */
   834    
   835        /* -------- Internal Module Types -------- */
   836    
   837        /*!
   838         *  @_nodoc
   839         *  Hook Context
   840         */
   841        struct HookContext {
   842            Queue.Elem qElem;        /*! Queue element */
   843            UInt32 totalTimeElapsed; /*! Total amount of time elapsed */
   844            UInt32 totalTime;        /*! time spent in thread */
   845            UInt32 nextTotalTime;    /*! working counter of time spent in thread */
   846            UInt32 timeOfLastUpdate; /*! time when update was last called */
   847            Ptr threadHandle;        /*! handle to thread whose context this is */
   848        };
   849    
   850        /* -------- Internal Module Parameters -------- */
   851    
   852        /*! @_nodoc
   853         *  Automatically add all tasks
   854         */
   855        config Bool autoAddTasks = true;
   856    
   857        /*! @_nodoc
   858         *  Is power management enabled?
   859         */
   860        metaonly config Bool powerEnabled;
   861    
   862        /* -------- Internal Module Functions -------- */
   863    
   864        /*!
   865         *  @_nodoc
   866         *  ======== logLoads ========
   867         *  Logs load values for all monitored threads.
   868         *  Statistics messages from the kernel must be enabled
   869         *  (via Load.common$.diags_USER4) in order to see the output.
   870         *
   871         *  If {@link #taskEnabled} is set to TRUE, this function can only be
   872         *  called in task context.
   873         */
   874        Void logLoads();
   875    
   876        /*!
   877         *  @_nodoc
   878         *  ======== logCPULoad ========
   879         *  Log CPU load only.
   880         */
   881        Void logCPULoad();
   882    
   883        struct Module_State {
   884            Queue.Object taskList;   /* List to hold registered task instances */
   885    
   886            Int taskHId;             /* Task Hook Context Id for this module */
   887    
   888            UInt32 taskStartTime[];  /* The start time of the current task */
   889            UInt32 timeElapsed;      /* Working count of time elapsed */
   890            Task.Handle runningTask[]; /* Currently running task */
   891            Bool firstSwitchDone;    /* Flag for first task switch */
   892    
   893            UInt32 swiStartTime;     /* Start time of the current Swi */
   894            HookContext swiEnv;      /* Singleton hook context for swi's */
   895            HookContext taskEnv[];   /* Hook contexts for static tasks */
   896            UInt32 swiCnt;           /* number of Swi's currently executing */
   897    
   898            UInt32 hwiStartTime;     /* Start time of the current Hwi */
   899            HookContext hwiEnv;      /* Singleton hook context for hwi's */
   900            UInt32 hwiCnt;           /* number of Hwi's currently executing */
   901    
   902            UInt32 timeSlotCnt;      /* count of number of time windows printed */
   903    
   904            UInt32 minLoop;          /* shortest time thru the idle loop */
   905            UInt32 minIdle;          /* minLoop is never set below this value */
   906            UInt32 t0;               /* start time of previous call to idle fxn */
   907            UInt32 idleCnt;          /* number of times through idle loop */
   908            UInt32 cpuLoad;          /* CPU load in previous time window */
   909    
   910            UInt32 taskEnvLen;       /* Length of static taskEnv array */
   911            UInt32 taskNum;          /* Number of initialized static tasks */
   912    
   913            /* Fields for CPU load calculation with Power idling */
   914            Bool   powerEnabled;
   915            UInt32 idleStartTime;
   916            UInt32 busyStartTime;
   917            UInt32 busyTime;
   918        };
   919    }