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