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 <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
2ef4221668
commit
686e891cd2
@@ -136,6 +136,7 @@
|
|||||||
// Enables the (boot) system profiler for use with "profile -r"
|
// Enables the (boot) system profiler for use with "profile -r"
|
||||||
#define SYSTEM_PROFILER 0
|
#define SYSTEM_PROFILER 0
|
||||||
#define SYSTEM_PROFILE_SIZE 40 * 1024 * 1024
|
#define SYSTEM_PROFILE_SIZE 40 * 1024 * 1024
|
||||||
|
#define SYSTEM_PROFILE_SCHEDULING 0
|
||||||
#define SYSTEM_PROFILE_STACK_DEPTH 10
|
#define SYSTEM_PROFILE_STACK_DEPTH 10
|
||||||
#define SYSTEM_PROFILE_INTERVAL 10000
|
#define SYSTEM_PROFILE_INTERVAL 10000
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ static const char* kUsage =
|
|||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -l - When a command line is given: Start recording before\n"
|
" -l - When a command line is given: Start recording before\n"
|
||||||
" executable has been loaded.\n"
|
" executable has been loaded.\n"
|
||||||
|
" -r - Don't profile, but evaluate recorded kernel profile data.\n"
|
||||||
" -h, --help - Print this usage info.\n"
|
" -h, --help - Print this usage info.\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -203,6 +204,48 @@ public:
|
|||||||
_kern_system_profiler_stop();
|
_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:
|
private:
|
||||||
bool _ProcessEventBuffer(uint8* buffer, size_t bufferSize)
|
bool _ProcessEventBuffer(uint8* buffer, size_t bufferSize)
|
||||||
{
|
{
|
||||||
@@ -274,6 +317,7 @@ main(int argc, const char* const* argv)
|
|||||||
{
|
{
|
||||||
Recorder recorder;
|
Recorder recorder;
|
||||||
|
|
||||||
|
bool dumpRecorded = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
static struct option sLongOptions[] = {
|
static struct option sLongOptions[] = {
|
||||||
{ "help", no_argument, 0, 'h' },
|
{ "help", no_argument, 0, 'h' },
|
||||||
@@ -281,7 +325,7 @@ main(int argc, const char* const* argv)
|
|||||||
};
|
};
|
||||||
|
|
||||||
opterr = 0; // don't print errors
|
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)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -293,6 +337,10 @@ main(int argc, const char* const* argv)
|
|||||||
recorder.SetSkipLoading(false);
|
recorder.SetSkipLoading(false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
dumpRecorded = true;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
print_usage_and_exit(true);
|
print_usage_and_exit(true);
|
||||||
break;
|
break;
|
||||||
@@ -313,7 +361,10 @@ main(int argc, const char* const* argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
// start the action
|
// start the action
|
||||||
recorder.Run(programArgs, programArgCount);
|
if (!dumpRecorded)
|
||||||
|
recorder.Run(programArgs, programArgCount);
|
||||||
|
else
|
||||||
|
recorder.DumpRecorded();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,10 @@ class SystemProfiler;
|
|||||||
|
|
||||||
static spinlock sProfilerLock = B_SPINLOCK_INITIALIZER;
|
static spinlock sProfilerLock = B_SPINLOCK_INITIALIZER;
|
||||||
static SystemProfiler* sProfiler = NULL;
|
static SystemProfiler* sProfiler = NULL;
|
||||||
|
|
||||||
|
#if SYSTEM_PROFILER
|
||||||
static struct system_profiler_parameters* sRecordedParameters = NULL;
|
static struct system_profiler_parameters* sRecordedParameters = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class SystemProfiler : public BReferenceable, private NotificationListener,
|
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->buffer_area = area;
|
||||||
sRecordedParameters->flags = B_SYSTEM_PROFILER_TEAM_EVENTS
|
sRecordedParameters->flags = B_SYSTEM_PROFILER_TEAM_EVENTS
|
||||||
| B_SYSTEM_PROFILER_THREAD_EVENTS | B_SYSTEM_PROFILER_IMAGE_EVENTS
|
| B_SYSTEM_PROFILER_THREAD_EVENTS;
|
||||||
| B_SYSTEM_PROFILER_IO_SCHEDULING_EVENTS
|
if (interval > 0 && stackDepth > 0) {
|
||||||
| B_SYSTEM_PROFILER_SAMPLING_EVENTS;
|
sRecordedParameters->flags |= B_SYSTEM_PROFILER_SAMPLING_EVENTS
|
||||||
|
| B_SYSTEM_PROFILER_IMAGE_EVENTS;
|
||||||
|
}
|
||||||
sRecordedParameters->locking_lookup_size = 4096;
|
sRecordedParameters->locking_lookup_size = 4096;
|
||||||
sRecordedParameters->interval = interval;
|
sRecordedParameters->interval = interval;
|
||||||
sRecordedParameters->stack_depth = stackDepth;
|
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;
|
area_info areaInfo;
|
||||||
get_area_info(area, &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))
|
if (userParameters == NULL || !IS_USER_ADDRESS(userParameters))
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
#if SYSTEM_PROFILER
|
||||||
if (sRecordedParameters == NULL)
|
if (sRecordedParameters == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
#if SYSTEM_PROFILER
|
|
||||||
stop_system_profiler();
|
stop_system_profiler();
|
||||||
|
|
||||||
// Transfer the area to the userland process
|
// Transfer the area to the userland process
|
||||||
|
|||||||
Reference in New Issue
Block a user