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.
This commit is contained in:
Augustin Cavalier
2024-07-16 20:37:40 -04:00
parent 6d5c99effe
commit 7eb6aafc30
8 changed files with 31 additions and 8 deletions
+1
View File
@@ -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 {
+2
View File
@@ -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 {
@@ -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
};
+1 -1
View File
@@ -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),
+1
View File
@@ -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,
+3 -2
View File
@@ -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 <output> - Print the results to file <output>.\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;
+10 -2
View File
@@ -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);
+12 -3
View File
@@ -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;