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