1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 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;
331 String swiLoad;
332 String hwiLoad;
333 String idleError; 334 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
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
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
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
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:
834
835
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
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
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;
885
886 Int taskHId;
887
888 UInt32 taskStartTime[];
889 UInt32 timeElapsed;
890 Task.Handle runningTask[];
891 Bool firstSwitchDone;
892
893 UInt32 swiStartTime;
894 HookContext swiEnv;
895 HookContext taskEnv[];
896 UInt32 swiCnt;
897
898 UInt32 hwiStartTime;
899 HookContext hwiEnv;
900 UInt32 hwiCnt;
901
902 UInt32 timeSlotCnt;
903
904 UInt32 minLoop;
905 UInt32 minIdle;
906 UInt32 t0;
907 UInt32 idleCnt;
908 UInt32 cpuLoad;
909
910 UInt32 taskEnvLen;
911 UInt32 taskNum;
912
913
914 Bool powerEnabled;
915 UInt32 idleStartTime;
916 UInt32 busyStartTime;
917 UInt32 busyTime;
918 };
919 }