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 <waddlesplash@gmail.com>
This commit is contained in:
Augustin Cavalier 2024-08-08 20:01:57 -04:00 committed by waddlesplash
parent 2ef4221668
commit 686e891cd2
3 changed files with 69 additions and 6 deletions

View File

@ -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

View File

@ -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
if (!dumpRecorded)
recorder.Run(programArgs, programArgCount);
else
recorder.DumpRecorded();
return 0;
}

View File

@ -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