Add 2 new benchmark utilization syscalls

- seL4_BenchmarkDumpAllThreadsUtilisation: Prints a JSON formatted
record of total and per-thread utilisation statistics about the system.
This currently includes a thread's total cycles scheduled, total number
of times scheduled, total cycles spent in the kernel and total number of
times entering the kernel and then totals of each for all threads on the
current core.
- seL4_BenchmarkResetAllThreadsUtilisation: Resets the current counts of
every user thread on the current core.

These syscalls are only available in a Debug build configuration as they
use a kernel debug list of all of the threads that exist for a given
node.

Signed-off-by: Kent McLeod <Kent.Mcleod@data61.csiro.au>
This commit is contained in:
Kent McLeod 2020-07-14 14:08:58 +10:00
parent 88a7d138c4
commit e1f6cf0ab0
6 changed files with 140 additions and 0 deletions

View file

@ -748,7 +748,34 @@ LIBSEL4_INLINE_FUNC void seL4_BenchmarkResetThreadUtilisation(seL4_Word tcb_cptr
arm_sys_send_recv(seL4_SysBenchmarkResetThreadUtilisation, tcb_cptr, &unused0, 0, &unused1, &unused2, &unused3,
&unused4, &unused5, 0);
}
#ifdef CONFIG_DEBUG_BUILD
LIBSEL4_INLINE_FUNC void seL4_BenchmarkDumpAllThreadsUtilisation(void)
{
seL4_Word unused0 = 0;
seL4_Word unused1 = 0;
seL4_Word unused2 = 0;
seL4_Word unused3 = 0;
seL4_Word unused4 = 0;
seL4_Word unused5 = 0;
arm_sys_send_recv(seL4_SysBenchmarkDumpAllThreadsUtilisation, 0, &unused0, 0, &unused1, &unused2, &unused3, &unused4,
&unused5, 0);
}
LIBSEL4_INLINE_FUNC void seL4_BenchmarkResetAllThreadsUtilisation(void)
{
seL4_Word unused0 = 0;
seL4_Word unused1 = 0;
seL4_Word unused2 = 0;
seL4_Word unused3 = 0;
seL4_Word unused4 = 0;
seL4_Word unused5 = 0;
arm_sys_send_recv(seL4_SysBenchmarkResetAllThreadsUtilisation, 0, &unused0, 0, &unused1, &unused2, &unused3, &unused4,
&unused5, 0);
}
#endif
#endif /* CONFIG_BENCHMARK_TRACK_UTILISATION */
#endif /* CONFIG_ENABLE_BENCHMARKS */

View file

@ -64,6 +64,10 @@
<syscall name="BenchmarkGetThreadUtilisation" />
<syscall name="BenchmarkResetThreadUtilisation" />
</config>
<config condition="defined CONFIG_DEBUG_BUILD &amp;&amp; defined CONFIG_BENCHMARK_TRACK_UTILISATION">
<syscall name="BenchmarkDumpAllThreadsUtilisation" />
<syscall name="BenchmarkResetAllThreadsUtilisation" />
</config>
<config condition="defined CONFIG_KERNEL_X86_DANGEROUS_MSR">
<syscall name="X86DangerousWRMSR"/>
<syscall name="X86DangerousRDMSR"/>

View file

@ -282,6 +282,29 @@ seL4_BenchmarkGetThreadUtilisation(seL4_Word tcb_cptr);
*/
LIBSEL4_INLINE_FUNC void
seL4_BenchmarkResetThreadUtilisation(seL4_Word tcb_cptr);
#ifdef CONFIG_DEBUG_BUILD
/**
* @xmlonly <manual name="Dump All Threads Utilisation" label="sel4_benchmarkdumpallthreadsutilisation"/> @endxmlonly
* @brief Print the current accumulated cycle count for every thread on the current node.
*
* Uses kernel's printf to print number of cycles on each line in the following format: thread_name,thread_cycles
*
*/
LIBSEL4_INLINE_FUNC void
seL4_BenchmarkDumpAllThreadsUtilisation(void);
/**
* @xmlonly <manual name="Reset All Threads Utilisation" label="sel4_benchmarkresetallthreadsutilisation"/> @endxmlonly
* @brief Reset the accumulated cycle count for every thread on the current node.
*
* Reset the cycle count for each thread to 0.
*
*/
LIBSEL4_INLINE_FUNC void
seL4_BenchmarkResetAllThreadsUtilisation(void);
#endif
#endif
#endif
/** @} */

View file

@ -981,6 +981,31 @@ LIBSEL4_INLINE_FUNC void seL4_BenchmarkResetThreadUtilisation(seL4_Word tcb_cptr
x86_sys_send_recv(seL4_SysBenchmarkResetThreadUtilisation, tcb_cptr, &unused0, 0, &unused1, &unused2, MCS_COND(0,
&unused3));
}
#ifdef CONFIG_DEBUG_BUILD
LIBSEL4_INLINE_FUNC void seL4_BenchmarkDumpAllThreadsUtilisation(void)
{
seL4_Word unused0 = 0;
seL4_Word unused1 = 0;
seL4_Word unused2 = 0;
LIBSEL4_UNUSED seL4_Word unused3 = 0;
x86_sys_send_recv(seL4_SysBenchmarkDumpAllThreadsUtilisation, 0, &unused0, 0, &unused1, &unused2, MCS_COND(0,
&unused3));
}
LIBSEL4_INLINE_FUNC seL4_Word seL4_BenchmarkResetAllThreadsUtilisation(void)
{
seL4_Word unused0 = 0;
seL4_Word unused1 = 0;
seL4_Word unused2 = 0;
LIBSEL4_UNUSED seL4_Word unused3 = 0;
x86_sys_send_recv(seL4_SysBenchmarkResetAllThreadsUtilisation, 0, &unused0, 0, &unused1, &unused2, MCS_COND(0,
&unused3));
}
#endif /* CONFIG_DEBUG_BUILD */
#endif /* CONFIG_BENCHMARK_TRACK_UTILISATION */
#endif /* CONFIG_ENABLE_BENCHMARKS */

View file

@ -764,6 +764,35 @@ LIBSEL4_INLINE_FUNC void seL4_BenchmarkResetThreadUtilisation(seL4_Word tcb_cptr
x64_sys_send_recv(seL4_SysBenchmarkResetThreadUtilisation, tcb_cptr, &unused0, 0, &unused1, &unused2, &unused3,
&unused4, &unused5, 0);
}
#ifdef CONFIG_DEBUG_BUILD
LIBSEL4_INLINE_FUNC void seL4_BenchmarkDumpAllThreadsUtilisation(void)
{
seL4_Word unused0 = 0;
seL4_Word unused1 = 0;
seL4_Word unused2 = 0;
seL4_Word unused3 = 0;
seL4_Word unused4 = 0;
seL4_Word unused5 = 0;
x64_sys_send_recv(seL4_SysBenchmarkDumpAllThreadsUtilisation, 0, &unused0, 0, &unused1, &unused2, &unused3, &unused4,
&unused5, 0);
}
LIBSEL4_INLINE_FUNC void seL4_BenchmarkResetAllThreadsUtilisation(void)
{
seL4_Word unused0 = 0;
seL4_Word unused1 = 0;
seL4_Word unused2 = 0;
seL4_Word unused3 = 0;
seL4_Word unused4 = 0;
seL4_Word unused5 = 0;
x64_sys_send_recv(seL4_SysBenchmarkResetAllThreadsUtilisation, 0, &unused0, 0, &unused1, &unused2, &unused3, &unused4,
&unused5, 0);
}
#endif
#endif /* CONFIG_BENCHMARK_TRACK_UTILISATION */
#endif /* CONFIG_ENABLE_BENCHMARKS */

View file

@ -266,6 +266,38 @@ exception_t handleUnknownSyscall(word_t w)
benchmark_track_reset_utilisation(tcb);
return EXCEPTION_NONE;
}
#ifdef CONFIG_DEBUG_BUILD
else if (w == SysBenchmarkDumpAllThreadsUtilisation) {
printf("{\n");
printf(" \"BENCHMARK_TOTAL_UTILISATION\":%lu,\n",
(word_t)(NODE_STATE(benchmark_end_time) - NODE_STATE(benchmark_start_time)));
printf(" \"BENCHMARK_TOTAL_KERNEL_UTILISATION\":%lu,\n", (word_t) NODE_STATE(benchmark_kernel_time));
printf(" \"BENCHMARK_TOTAL_NUMBER_KERNEL_ENTRIES\":%lu,\n", (word_t) NODE_STATE(benchmark_kernel_number_entries));
printf(" \"BENCHMARK_TOTAL_NUMBER_SCHEDULES\":%lu,\n", (word_t) NODE_STATE(benchmark_kernel_number_schedules));
printf(" \"BENCHMARK_TCB_\": [\n");
for (tcb_t *curr = NODE_STATE(ksDebugTCBs); curr != NULL; curr = curr->tcbDebugNext) {
printf(" {\n");
printf(" \"NAME\":\"%s\",\n", curr->tcbName);
printf(" \"UTILISATION\":%lu,\n", (word_t) curr->benchmark.utilisation);
printf(" \"NUMBER_SCHEDULES\":%lu,\n", (word_t) curr->benchmark.number_schedules);
printf(" \"KERNEL_UTILISATION\":%lu,\n", (word_t) curr->benchmark.kernel_utilisation);
printf(" \"NUMBER_KERNEL_ENTRIES\":%lu\n", (word_t) curr->benchmark.number_kernel_entries);
printf(" }");
if (curr->tcbDebugNext != NULL) {
printf(",\n");
} else {
printf("\n");
}
}
printf(" ]\n}\n");
return EXCEPTION_NONE;
} else if (w == SysBenchmarkResetAllThreadsUtilisation) {
for (tcb_t *curr = NODE_STATE(ksDebugTCBs); curr != NULL; curr = curr->tcbDebugNext) {
benchmark_track_reset_utilisation(curr);
}
return EXCEPTION_NONE;
}
#endif /* CONFIG_DEBUG_BUILD */
#endif /* CONFIG_BENCHMARK_TRACK_UTILISATION */
else if (w == SysBenchmarkNullSyscall) {