[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:
@@ -174,13 +174,17 @@ static inline __ALWAYS_INLINE uintptr_t tls_set(uint entry, uintptr_t val)
|
||||
struct thread_stats {
|
||||
lk_bigtime_t idle_time;
|
||||
lk_bigtime_t last_idle_timestamp;
|
||||
int reschedules;
|
||||
int context_switches;
|
||||
int preempts;
|
||||
int yields;
|
||||
int interrupts; /* platform code increment this */
|
||||
int timer_ints; /* timer code increment this */
|
||||
int timers; /* timer code increment this */
|
||||
ulong reschedules;
|
||||
ulong context_switches;
|
||||
ulong preempts;
|
||||
ulong yields;
|
||||
ulong interrupts; /* platform code increment this */
|
||||
ulong timer_ints; /* timer code increment this */
|
||||
ulong timers; /* timer code increment this */
|
||||
|
||||
#if WITH_SMP
|
||||
ulong reschedule_ipis;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct thread_stats thread_stats[SMP_MAX_CPUS];
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -73,6 +73,8 @@ enum handler_return mp_mbx_reschedule_irq(void)
|
||||
|
||||
LTRACEF("cpu %u\n", cpu);
|
||||
|
||||
THREAD_STATS_INC(reschedule_ipis);
|
||||
|
||||
return (mp.active_cpus & (1U << cpu)) ? INT_RESCHEDULE : INT_NO_RESCHEDULE;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user