seL4/include/benchmark/benchmark_utilisation.h
Kent McLeod 4eccea54e5 KernelBenchmarksTrackUtilisation: Fix for SMP
Create per-node global definitions for utilization variables.
This enables the tracking to more cleanly work on SMP configurations.
As resetting and starting the counters via SysBenchmarkResetLog only
updates the counters of the current thread and idle thread on the
current node it was not possible to accurately record utilization
statistics across multiple nodes. Now each node can have its tracking
independently started, stopped and queried. It is possible to add
additional syscalls in the future for doing this for all nodes in a
single syscall.

Signed-off-by: Kent McLeod <Kent.Mcleod@data61.csiro.au>
2020-07-14 14:13:27 +10:00

59 lines
1.8 KiB
C

/*
* Copyright 2016, General Dynamics C4 Systems
*
* SPDX-License-Identifier: GPL-2.0-only
*/
#pragma once
#include <config.h>
#include <arch/benchmark.h>
#include <sel4/benchmark_utilisation_types.h>
#include <sel4/arch/constants.h>
#include <model/statedata.h>
#ifdef CONFIG_BENCHMARK_TRACK_UTILISATION
extern timestamp_t ksEnter;
void benchmark_track_utilisation_dump(void);
void benchmark_track_reset_utilisation(void);
/* Calculate and add the utilisation time from when the heir started to run i.e. scheduled
* and until it's being kicked off
*/
static inline void benchmark_utilisation_switch(tcb_t *heir, tcb_t *next)
{
/* Add heir thread utilisation */
if (likely(NODE_STATE(benchmark_log_utilisation_enabled))) {
/* Check if an overflow occurred while we have been in the kernel */
if (likely(ksEnter > heir->benchmark.schedule_start_time)) {
heir->benchmark.utilisation += (ksEnter - heir->benchmark.schedule_start_time);
} else {
#ifdef CONFIG_ARM_ENABLE_PMU_OVERFLOW_INTERRUPT
heir->benchmark.utilisation += (UINT32_MAX - heir->benchmark.schedule_start_time) + ksEnter;
armv_handleOverflowIRQ();
#endif /* CONFIG_ARM_ENABLE_PMU_OVERFLOW_INTERRUPT */
}
/* Reset next thread utilisation */
next->benchmark.schedule_start_time = ksEnter;
}
}
/* Add the time between the last thread got scheduled and when to stop
* benchmarks
*/
static inline void benchmark_utilisation_finalise(void)
{
/* Add the time between when NODE_STATE(ksCurThread), and benchmark finalise */
benchmark_utilisation_switch(NODE_STATE(ksCurThread), NODE_STATE(ksIdleThread));
NODE_STATE(benchmark_end_time) = ksEnter;
NODE_STATE(benchmark_log_utilisation_enabled) = false;
}
#endif /* CONFIG_BENCHMARK_TRACK_UTILISATION */