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
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;
250 String swiLoad;
251 String hwiLoad;
252 String idleError; 253 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
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
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
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
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:
700
701
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
717
718 /*! @_nodoc
719 * Automatically add all tasks
720 */
721 config Bool autoAddTasks = true;
722
723
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;
740
741 Int taskHId;
742
743 UInt32 taskStartTime;
744 UInt32 timeElapsed;
745 Task.Handle runningTask;
746 Bool firstSwitchDone;
747
748 UInt32 swiStartTime;
749 HookContext swiEnv;
750 UInt32 swiCnt;
751
752 UInt32 hwiStartTime;
753 HookContext hwiEnv;
754 UInt32 hwiCnt;
755
756 UInt32 timeSlotCnt;
757
758 UInt32 minLoop;
759 UInt32 minIdle;
760 UInt32 t0;
761 UInt32 idleCnt;
762 UInt32 cpuLoad;
763
764 GateMutex.Object gate;
765 };
766 }
767 768 769 770
771