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;