mirror of
https://review.haiku-os.org/haiku
synced 2024-11-23 07:18:40 +01:00
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:
parent
2ef4221668
commit
686e891cd2
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user