From 686e891cd262340afe592ded7cfc87366248b5c7 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Thu, 8 Aug 2024 20:01:57 -0400 Subject: [PATCH] system_profiler: Add a mode for scheduling_recorder -r like profile -r. And add the necessary logic in scheduling_recorder. This way we can track scheduling profiling during the boot process. Also remove B_SYSTEM_PROFILER_IO_SCHEDULING_EVENTS as it can't be activated this early in the boot process. Change-Id: If32f9b5d61c8cd2b3b36a4e6f8065301abd46149 Reviewed-on: https://review.haiku-os.org/c/haiku/+/7963 Reviewed-by: waddlesplash --- build/config_headers/kernel_debug_config.h | 1 + .../scheduling_recorder.cpp | 55 ++++++++++++++++++- src/system/kernel/debug/system_profiler.cpp | 19 +++++-- 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/build/config_headers/kernel_debug_config.h b/build/config_headers/kernel_debug_config.h index c72628d7bc..22f0a40b90 100644 --- a/build/config_headers/kernel_debug_config.h +++ b/build/config_headers/kernel_debug_config.h @@ -136,6 +136,7 @@ // Enables the (boot) system profiler for use with "profile -r" #define SYSTEM_PROFILER 0 #define SYSTEM_PROFILE_SIZE 40 * 1024 * 1024 +#define SYSTEM_PROFILE_SCHEDULING 0 #define SYSTEM_PROFILE_STACK_DEPTH 10 #define SYSTEM_PROFILE_INTERVAL 10000 diff --git a/src/bin/debug/scheduling_recorder/scheduling_recorder.cpp b/src/bin/debug/scheduling_recorder/scheduling_recorder.cpp index 4b68d99c96..b549af142f 100644 --- a/src/bin/debug/scheduling_recorder/scheduling_recorder.cpp +++ b/src/bin/debug/scheduling_recorder/scheduling_recorder.cpp @@ -44,6 +44,7 @@ static const char* kUsage = "Options:\n" " -l - When a command line is given: Start recording before\n" " executable has been loaded.\n" + " -r - Don't profile, but evaluate recorded kernel profile data.\n" " -h, --help - Print this usage info.\n" ; @@ -203,6 +204,48 @@ public: _kern_system_profiler_stop(); } + void DumpRecorded() + { + // retrieve recorded samples and parameters + system_profiler_parameters profilerParameters; + status_t error = _kern_system_profiler_recorded(&profilerParameters); + if (error != B_OK) { + fprintf(stderr, "%s: Failed to get recorded profiling buffer: %s\n", + kCommandName, strerror(error)); + exit(1); + } + + // create an area for the sample buffer + area_info info; + error = get_area_info(profilerParameters.buffer_area, &info); + if (error != B_OK) { + fprintf(stderr, "%s: Recorded profiling buffer invalid: %s\n", + kCommandName, strerror(error)); + exit(1); + } + + system_profiler_buffer_header* bufferHeader + = (system_profiler_buffer_header*)info.address; + + uint8* bufferBase = (uint8*)(bufferHeader + 1); + size_t totalBufferSize = info.size - (bufferBase - (uint8*)bufferHeader); + + // get the current buffer + size_t bufferStart = bufferHeader->start; + size_t bufferSize = bufferHeader->size; + uint8* buffer = bufferBase + bufferStart; + + if (bufferStart + bufferSize <= totalBufferSize) { + _ProcessEventBuffer(buffer, bufferSize); + } else { + size_t remainingSize = bufferStart + bufferSize - totalBufferSize; + if (!_ProcessEventBuffer(buffer, + bufferSize - remainingSize)) { + _ProcessEventBuffer(bufferBase, remainingSize); + } + } + } + private: bool _ProcessEventBuffer(uint8* buffer, size_t bufferSize) { @@ -274,6 +317,7 @@ main(int argc, const char* const* argv) { Recorder recorder; + bool dumpRecorded = false; while (true) { static struct option sLongOptions[] = { { "help", no_argument, 0, 'h' }, @@ -281,7 +325,7 @@ main(int argc, const char* const* argv) }; opterr = 0; // don't print errors - int c = getopt_long(argc, (char**)argv, "+hl", sLongOptions, NULL); + int c = getopt_long(argc, (char**)argv, "+hlr", sLongOptions, NULL); if (c == -1) break; @@ -293,6 +337,10 @@ main(int argc, const char* const* argv) recorder.SetSkipLoading(false); break; + case 'r': + dumpRecorded = true; + break; + default: print_usage_and_exit(true); break; @@ -313,7 +361,10 @@ main(int argc, const char* const* argv) exit(1); // start the action - recorder.Run(programArgs, programArgCount); + if (!dumpRecorded) + recorder.Run(programArgs, programArgCount); + else + recorder.DumpRecorded(); return 0; } diff --git a/src/system/kernel/debug/system_profiler.cpp b/src/system/kernel/debug/system_profiler.cpp index f15f8b94fd..a00deb1fc5 100644 --- a/src/system/kernel/debug/system_profiler.cpp +++ b/src/system/kernel/debug/system_profiler.cpp @@ -48,7 +48,10 @@ class SystemProfiler; static spinlock sProfilerLock = B_SPINLOCK_INITIALIZER; static SystemProfiler* sProfiler = NULL; + +#if SYSTEM_PROFILER static struct system_profiler_parameters* sRecordedParameters = NULL; +#endif class SystemProfiler : public BReferenceable, private NotificationListener, @@ -1502,13 +1505,20 @@ start_system_profiler(size_t areaSize, uint32 stackDepth, bigtime_t interval) sRecordedParameters->buffer_area = area; sRecordedParameters->flags = B_SYSTEM_PROFILER_TEAM_EVENTS - | B_SYSTEM_PROFILER_THREAD_EVENTS | B_SYSTEM_PROFILER_IMAGE_EVENTS - | B_SYSTEM_PROFILER_IO_SCHEDULING_EVENTS - | B_SYSTEM_PROFILER_SAMPLING_EVENTS; + | B_SYSTEM_PROFILER_THREAD_EVENTS; + if (interval > 0 && stackDepth > 0) { + sRecordedParameters->flags |= B_SYSTEM_PROFILER_SAMPLING_EVENTS + | B_SYSTEM_PROFILER_IMAGE_EVENTS; + } sRecordedParameters->locking_lookup_size = 4096; sRecordedParameters->interval = interval; sRecordedParameters->stack_depth = stackDepth; +#if SYSTEM_PROFILE_SCHEDULING + sRecordedParameters->flags |= B_SYSTEM_PROFILER_SCHEDULING_EVENTS; + sRecordedParameters->locking_lookup_size = 64 * 1024; +#endif + area_info areaInfo; get_area_info(area, &areaInfo); @@ -1684,10 +1694,11 @@ _user_system_profiler_recorded(system_profiler_parameters* userParameters) if (userParameters == NULL || !IS_USER_ADDRESS(userParameters)) return B_BAD_ADDRESS; + +#if SYSTEM_PROFILER if (sRecordedParameters == NULL) return B_ERROR; -#if SYSTEM_PROFILER stop_system_profiler(); // Transfer the area to the userland process