From 7eb6aafc307e7442d5b523d034870fd029d56aa5 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 16 Jul 2024 20:37:40 -0400 Subject: [PATCH] profiler: Actually support profiling user stack frames only. The "-k" argument (which never did anything before) is now inverted compared to what it used to be, i.e. now specifying it will profile kernel frames, too, whereas by default only user frames will be sampled. --- headers/os/kernel/debugger.h | 1 + headers/private/kernel/user_debugger.h | 2 ++ headers/private/system/system_profiler_defs.h | 1 + src/bin/debug/profile/Options.h | 2 +- src/bin/debug/profile/Team.cpp | 1 + src/bin/debug/profile/profile.cpp | 5 +++-- src/system/kernel/debug/system_profiler.cpp | 12 ++++++++++-- src/system/kernel/debug/user_debugger.cpp | 15 ++++++++++++--- 8 files changed, 31 insertions(+), 8 deletions(-) diff --git a/headers/os/kernel/debugger.h b/headers/os/kernel/debugger.h index c2ac40b1f0..cefe316892 100644 --- a/headers/os/kernel/debugger.h +++ b/headers/os/kernel/debugger.h @@ -407,6 +407,7 @@ typedef struct { bool variable_stack_depth; // variable number of samples per hit; // cf. debug_profiler_update + bool profile_kernel; // sample kernel stack frames } debug_nub_start_profiler; typedef struct { diff --git a/headers/private/kernel/user_debugger.h b/headers/private/kernel/user_debugger.h index 49f33edce2..51fe66916b 100644 --- a/headers/private/kernel/user_debugger.h +++ b/headers/private/kernel/user_debugger.h @@ -147,6 +147,8 @@ struct thread_debug_info { // the buffer bool variable_stack_depth; // record a variable number of samples per hit + bool profile_kernel; + // record samples in kernel stack frames bool buffer_full; // indicates that the sample buffer is full union { diff --git a/headers/private/system/system_profiler_defs.h b/headers/private/system/system_profiler_defs.h index 64a1a35526..0b0f04c4a8 100644 --- a/headers/private/system/system_profiler_defs.h +++ b/headers/private/system/system_profiler_defs.h @@ -21,6 +21,7 @@ struct system_profiler_parameters { // sampling bigtime_t interval; // interval at which to take samples uint32 stack_depth; // maximum stack depth to sample + bool profile_kernel; // sample kernel stack frames }; diff --git a/src/bin/debug/profile/Options.h b/src/bin/debug/profile/Options.h index eeaac04c21..9451c33b86 100644 --- a/src/bin/debug/profile/Options.h +++ b/src/bin/debug/profile/Options.h @@ -19,7 +19,7 @@ struct Options { output(NULL), callgrind_directory(NULL), profile_all(false), - profile_kernel(true), + profile_kernel(false), profile_loading(false), profile_teams(true), profile_threads(true), diff --git a/src/bin/debug/profile/Team.cpp b/src/bin/debug/profile/Team.cpp index cfc58889f7..5e23609585 100644 --- a/src/bin/debug/profile/Team.cpp +++ b/src/bin/debug/profile/Team.cpp @@ -157,6 +157,7 @@ Team::InitThread(Thread* thread) message.sample_area = sampleArea; message.stack_depth = gOptions.stack_depth; message.variable_stack_depth = gOptions.analyze_full_stack; + message.profile_kernel = gOptions.profile_kernel; debug_nub_start_profiler_reply reply; error = send_debug_message(&fDebugContext, diff --git a/src/bin/debug/profile/profile.cpp b/src/bin/debug/profile/profile.cpp index acd28fef3e..1e99759725 100644 --- a/src/bin/debug/profile/profile.cpp +++ b/src/bin/debug/profile/profile.cpp @@ -79,7 +79,7 @@ static const char* kUsage = " Default is 1000 (1 ms). On a fast machine, a shorter\n" " interval might lead to better results, while it might\n" " make them worse on slow machines.\n" - " -k - Don't check kernel images for hits.\n" + " -k - Also profile kernel frames.\n" " -l - Also profile loading the executable.\n" " -o - Print the results to file .\n" " -r, --recorded - Don't profile, but evaluate a recorded kernel profile\n" @@ -712,6 +712,7 @@ profile_all(const char* const* programArgs, int programArgCount) | B_SYSTEM_PROFILER_SAMPLING_EVENTS; profilerParameters.interval = gOptions.interval; profilerParameters.stack_depth = gOptions.stack_depth; + profilerParameters.profile_kernel = gOptions.profile_kernel; error = _kern_system_profiler_start(&profilerParameters); if (error != B_OK) { @@ -1055,7 +1056,7 @@ main(int argc, const char* const* argv) gOptions.interval = atol(optarg); break; case 'k': - gOptions.profile_kernel = false; + gOptions.profile_kernel = true; break; case 'l': gOptions.profile_loading = true; diff --git a/src/system/kernel/debug/system_profiler.cpp b/src/system/kernel/debug/system_profiler.cpp index 5a864e85c3..f15f8b94fd 100644 --- a/src/system/kernel/debug/system_profiler.cpp +++ b/src/system/kernel/debug/system_profiler.cpp @@ -180,6 +180,7 @@ private: uint32 fFlags; uint32 fStackDepth; bigtime_t fInterval; + bool fProfileKernel; system_profiler_buffer_header* fHeader; uint8* fBufferBase; size_t fBufferCapacity; @@ -257,6 +258,7 @@ SystemProfiler::SystemProfiler(team_id team, const area_info& userAreaInfo, fFlags(parameters.flags), fStackDepth(parameters.stack_depth), fInterval(parameters.interval), + fProfileKernel(parameters.profile_kernel), fHeader(NULL), fBufferBase(NULL), fBufferCapacity(0), @@ -1413,8 +1415,14 @@ SystemProfiler::_DoSample() CPUProfileData& cpuData = fCPUData[cpu]; // get the samples - int32 count = arch_debug_get_stack_trace(cpuData.buffer, fStackDepth, 1, - 0, STACK_TRACE_KERNEL | STACK_TRACE_USER); + uint32 flags = STACK_TRACE_USER; + int32 skipIFrames = 0; + if (fProfileKernel) { + flags |= STACK_TRACE_KERNEL; + skipIFrames = 1; + } + int32 count = arch_debug_get_stack_trace(cpuData.buffer, fStackDepth, + skipIFrames, 0, flags); InterruptsSpinLocker locker(fLock); diff --git a/src/system/kernel/debug/user_debugger.cpp b/src/system/kernel/debug/user_debugger.cpp index c9041d564b..d1111a6b9f 100644 --- a/src/system/kernel/debug/user_debugger.cpp +++ b/src/system/kernel/debug/user_debugger.cpp @@ -1367,19 +1367,26 @@ profiling_do_sample(bool& flushBuffer) } // get the samples + uint32 flags = STACK_TRACE_USER; + int32 skipIFrames = 0; + if (debugInfo.profile.profile_kernel) { + flags |= STACK_TRACE_KERNEL; + skipIFrames = 1; + } + addr_t* returnAddresses = debugInfo.profile.samples + debugInfo.profile.sample_count; if (debugInfo.profile.variable_stack_depth) { // variable sample count per hit *returnAddresses = arch_debug_get_stack_trace(returnAddresses + 1, - stackDepth - 1, 1, 0, STACK_TRACE_KERNEL | STACK_TRACE_USER); + stackDepth - 1, skipIFrames, 0, flags); debugInfo.profile.sample_count += *returnAddresses + 1; } else { // fixed sample count per hit - if (stackDepth > 1) { + if (stackDepth > 1 || !debugInfo.profile.profile_kernel) { int32 count = arch_debug_get_stack_trace(returnAddresses, - stackDepth, 1, 0, STACK_TRACE_KERNEL | STACK_TRACE_USER); + stackDepth, skipIFrames, 0, flags); for (int32 i = count; i < stackDepth; i++) returnAddresses[i] = 0; @@ -2262,6 +2269,7 @@ debug_nub_thread(void *) int32 stackDepth = message.start_profiler.stack_depth; bool variableStackDepth = message.start_profiler.variable_stack_depth; + bool profileKernel = message.start_profiler.profile_kernel; bigtime_t interval = max_c(message.start_profiler.interval, B_DEBUG_MIN_PROFILE_INTERVAL); status_t result = B_OK; @@ -2333,6 +2341,7 @@ debug_nub_thread(void *) threadDebugInfo.profile.stack_depth = stackDepth; threadDebugInfo.profile.variable_stack_depth = variableStackDepth; + threadDebugInfo.profile.profile_kernel = profileKernel; threadDebugInfo.profile.buffer_full = false; threadDebugInfo.profile.interval_left = interval; threadDebugInfo.profile.installed_timer = NULL;