[kernel][debug] fix threadload to display idle time properly in SMP world

The post SMP algorithm wasn't taking into account time on any given core
if the core was currently idle at the time the load interrupt fired.
Also track rescheduling ipis and condense the output slightly.
This commit is contained in:
Travis Geiselbrecht
2015-03-02 21:29:48 -08:00
parent ac53b59ca7
commit d0225dd262
3 changed files with 52 additions and 21 deletions

View File

@@ -36,6 +36,7 @@
#include <kernel/thread.h>
#include <kernel/timer.h>
#include <kernel/debug.h>
#include <kernel/mp.h>
#include <err.h>
#include <platform.h>
@@ -74,16 +75,22 @@ static int cmd_threads(int argc, const cmd_args *argv)
static int cmd_threadstats(int argc, const cmd_args *argv)
{
for (uint i = 0; i < SMP_MAX_CPUS; i++) {
if (!(mp.active_cpus & (1 << i)))
continue;
printf("thread stats (cpu %d):\n", i);
printf("\ttotal idle time: %lld\n", thread_stats[i].idle_time);
printf("\ttotal busy time: %lld\n", current_time_hires() - thread_stats[i].idle_time);
printf("\treschedules: %d\n", thread_stats[i].reschedules);
printf("\tcontext_switches: %d\n", thread_stats[i].context_switches);
printf("\tpreempts: %d\n", thread_stats[i].preempts);
printf("\tyields: %d\n", thread_stats[i].yields);
printf("\tinterrupts: %d\n", thread_stats[i].interrupts);
printf("\ttimer interrupts: %d\n", thread_stats[i].timer_ints);
printf("\ttimers: %d\n", thread_stats[i].timers);
printf("\treschedules: %lu\n", thread_stats[i].reschedules);
#if WITH_SMP
printf("\treschedule_ipis: %lu\n", thread_stats[i].reschedule_ipis);
#endif
printf("\tcontext_switches: %lu\n", thread_stats[i].context_switches);
printf("\tpreempts: %lu\n", thread_stats[i].preempts);
printf("\tyields: %lu\n", thread_stats[i].yields);
printf("\tinterrupts: %lu\n", thread_stats[i].interrupts);
printf("\ttimer interrupts: %lu\n", thread_stats[i].timer_ints);
printf("\ttimers: %lu\n", thread_stats[i].timers);
}
return 0;
@@ -95,21 +102,39 @@ static enum handler_return threadload(struct timer *t, lk_time_t now, void *arg)
static lk_bigtime_t last_idle_time[SMP_MAX_CPUS];
for (uint i = 0; i < SMP_MAX_CPUS; i++) {
/* dont display time for inactiv cpus */
if (!(mp.active_cpus & (1 << i)))
continue;
lk_bigtime_t idle_time = thread_stats[i].idle_time;
#if 0
if (get_current_thread()->priority == IDLE_PRIORITY) {
/* if the cpu is currently idle, add the time since it went idle up until now to the idle counter */
bool is_idle = !!(mp.idle_cpus & (1 << i));
if (is_idle) {
idle_time += current_time_hires() - thread_stats[i].last_idle_timestamp;
}
#endif
lk_bigtime_t delta_time = idle_time - last_idle_time[i];
lk_bigtime_t busy_time = 1000000ULL - (delta_time > 1000000ULL ? 1000000ULL : delta_time);
uint busypercent = (busy_time * 10000) / (1000000);
// printf("idle_time %lld, busytime %lld\n", idle_time - last_idle_time, busy_time);
printf("cpu %u LOAD: %d.%02d%%, cs %d, ints %d, timer ints %d, timers %d\n", i,
printf("cpu %u LOAD: "
"%u.%02u%%, "
"cs %lu, "
"pmpts %lu, "
#if WITH_SMP
"rs_ipis %lu, "
#endif
"ints %lu, "
"tmr ints %lu, "
"tmrs %lu\n",
i,
busypercent / 100, busypercent % 100,
thread_stats[i].context_switches - old_stats[i].context_switches,
thread_stats[i].preempts - old_stats[i].preempts,
#if WITH_SMP
thread_stats[i].reschedule_ipis - old_stats[i].reschedule_ipis,
#endif
thread_stats[i].interrupts - old_stats[i].interrupts,
thread_stats[i].timer_ints - old_stats[i].timer_ints,
thread_stats[i].timers - old_stats[i].timers);
@@ -216,4 +241,4 @@ static int cmd_kevlog(int argc, const cmd_args *argv)
#endif // WITH_KERNEL_EVLOG
// vim: set noexpandtab: