profiler: Report CPU times and use them to compute "missed" ticks.
This shows that the profiler is still pretty broken, because we are missing quite a lot of ticks on average. One run of "profile pkgman search" here produced an output with 66 total ticks and 423 (!) missed ticks. A brief run of WebPositive was not quite as bad (main thread: 1078 total ticks, 157 missed ticks.) Change-Id: Idfc34534e66eff0fe7e948fcc3576be09db879a3 Reviewed-on: https://review.haiku-os.org/c/haiku/+/7820 Reviewed-by: waddlesplash <[email protected]> Tested-by: Commit checker robot <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
60b260aca1
commit
2813fd13ca
@@ -622,6 +622,7 @@ typedef struct {
|
|||||||
// <sample 1> ... <sample stack_depth>
|
// <sample 1> ... <sample stack_depth>
|
||||||
bool stopped; // if true, the thread is no longer
|
bool stopped; // if true, the thread is no longer
|
||||||
// being profiled
|
// being profiled
|
||||||
|
bigtime_t last_cpu_time; // only set if "stopped" is
|
||||||
} debug_profiler_update;
|
} debug_profiler_update;
|
||||||
|
|
||||||
// B_DEBUGGER_MESSAGE_HANDED_OVER
|
// B_DEBUGGER_MESSAGE_HANDED_OVER
|
||||||
|
|||||||
@@ -112,12 +112,14 @@ struct system_profiler_thread_added {
|
|||||||
team_id team;
|
team_id team;
|
||||||
thread_id thread;
|
thread_id thread;
|
||||||
char name[B_OS_NAME_LENGTH];
|
char name[B_OS_NAME_LENGTH];
|
||||||
|
bigtime_t cpu_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
// B_SYSTEM_PROFILER_THREAD_REMOVED
|
// B_SYSTEM_PROFILER_THREAD_REMOVED
|
||||||
struct system_profiler_thread_removed {
|
struct system_profiler_thread_removed {
|
||||||
team_id team;
|
team_id team;
|
||||||
thread_id thread;
|
thread_id thread;
|
||||||
|
bigtime_t cpu_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
// B_SYSTEM_PROFILER_IMAGE_ADDED
|
// B_SYSTEM_PROFILER_IMAGE_ADDED
|
||||||
|
|||||||
@@ -119,12 +119,20 @@ BasicProfileResult::BasicProfileResult()
|
|||||||
:
|
:
|
||||||
fTotalTicks(0),
|
fTotalTicks(0),
|
||||||
fUnkownTicks(0),
|
fUnkownTicks(0),
|
||||||
|
fExpectedTicks(0),
|
||||||
fDroppedTicks(0),
|
fDroppedTicks(0),
|
||||||
fTotalSampleCount(0)
|
fTotalSampleCount(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BasicProfileResult::AddExpectedTicks(int32 expected)
|
||||||
|
{
|
||||||
|
fExpectedTicks += expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BasicProfileResult::AddDroppedTicks(int32 dropped)
|
BasicProfileResult::AddDroppedTicks(int32 dropped)
|
||||||
{
|
{
|
||||||
@@ -172,6 +180,8 @@ BasicProfileResult::PrintResults(ImageProfileResultContainer* container)
|
|||||||
std::sort(hitSymbols, hitSymbols + hitSymbolCount);
|
std::sort(hitSymbols, hitSymbols + hitSymbolCount);
|
||||||
|
|
||||||
int64 totalTicks = fTotalTicks;
|
int64 totalTicks = fTotalTicks;
|
||||||
|
const int64 missedTicks = fExpectedTicks - fTotalTicks;
|
||||||
|
|
||||||
fprintf(gOptions.output, "\nprofiling results for %s \"%s\" "
|
fprintf(gOptions.output, "\nprofiling results for %s \"%s\" "
|
||||||
"(%" B_PRId32 "):\n", fEntity->EntityType(), fEntity->EntityName(),
|
"(%" B_PRId32 "):\n", fEntity->EntityType(), fEntity->EntityName(),
|
||||||
fEntity->EntityID());
|
fEntity->EntityID());
|
||||||
@@ -180,8 +190,14 @@ BasicProfileResult::PrintResults(ImageProfileResultContainer* container)
|
|||||||
fprintf(gOptions.output,
|
fprintf(gOptions.output,
|
||||||
" total ticks: %" B_PRId64 " (%" B_PRId64 " us)\n",
|
" total ticks: %" B_PRId64 " (%" B_PRId64 " us)\n",
|
||||||
totalTicks, totalTicks * fInterval);
|
totalTicks, totalTicks * fInterval);
|
||||||
|
if (fExpectedTicks != 0) {
|
||||||
|
fprintf(gOptions.output,
|
||||||
|
" expected ticks: %" B_PRId64 " (missed %" B_PRId64 ")\n",
|
||||||
|
fExpectedTicks, missedTicks);
|
||||||
|
}
|
||||||
if (totalTicks == 0)
|
if (totalTicks == 0)
|
||||||
totalTicks = 1;
|
totalTicks = 1;
|
||||||
|
|
||||||
fprintf(gOptions.output,
|
fprintf(gOptions.output,
|
||||||
" unknown ticks: %" B_PRId64 " (%" B_PRId64 " us, %6.2f%%)\n",
|
" unknown ticks: %" B_PRId64 " (%" B_PRId64 " us, %6.2f%%)\n",
|
||||||
fUnkownTicks, fUnkownTicks * fInterval,
|
fUnkownTicks, fUnkownTicks * fInterval,
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class BasicProfileResult : public ProfileResult {
|
|||||||
public:
|
public:
|
||||||
BasicProfileResult();
|
BasicProfileResult();
|
||||||
|
|
||||||
|
virtual void AddExpectedTicks(int32 expected);
|
||||||
virtual void AddDroppedTicks(int32 dropped);
|
virtual void AddDroppedTicks(int32 dropped);
|
||||||
virtual void PrintResults(
|
virtual void PrintResults(
|
||||||
ImageProfileResultContainer* container);
|
ImageProfileResultContainer* container);
|
||||||
@@ -47,6 +48,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
int64 fTotalTicks;
|
int64 fTotalTicks;
|
||||||
int64 fUnkownTicks;
|
int64 fUnkownTicks;
|
||||||
|
int64 fExpectedTicks;
|
||||||
int64 fDroppedTicks;
|
int64 fDroppedTicks;
|
||||||
int64 fTotalSampleCount;
|
int64 fTotalSampleCount;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ CallgrindProfileResult::CallgrindProfileResult()
|
|||||||
:
|
:
|
||||||
fTotalTicks(0),
|
fTotalTicks(0),
|
||||||
fUnkownTicks(0),
|
fUnkownTicks(0),
|
||||||
|
fExpectedTicks(0),
|
||||||
fDroppedTicks(0),
|
fDroppedTicks(0),
|
||||||
fNextImageOutputIndex(1),
|
fNextImageOutputIndex(1),
|
||||||
fNextFunctionOutputIndex(1)
|
fNextFunctionOutputIndex(1)
|
||||||
@@ -163,6 +164,13 @@ CallgrindProfileResult::AddSamples(ImageProfileResultContainer* container,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CallgrindProfileResult::AddExpectedTicks(int32 expected)
|
||||||
|
{
|
||||||
|
fExpectedTicks += expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CallgrindProfileResult::AddDroppedTicks(int32 dropped)
|
CallgrindProfileResult::AddDroppedTicks(int32 dropped)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ public:
|
|||||||
virtual void AddSamples(
|
virtual void AddSamples(
|
||||||
ImageProfileResultContainer* container,
|
ImageProfileResultContainer* container,
|
||||||
addr_t* samples, int32 sampleCount);
|
addr_t* samples, int32 sampleCount);
|
||||||
|
virtual void AddExpectedTicks(int32 expected);
|
||||||
virtual void AddDroppedTicks(int32 dropped);
|
virtual void AddDroppedTicks(int32 dropped);
|
||||||
virtual void PrintResults(
|
virtual void PrintResults(
|
||||||
ImageProfileResultContainer* container);
|
ImageProfileResultContainer* container);
|
||||||
@@ -85,6 +86,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
int64 fTotalTicks;
|
int64 fTotalTicks;
|
||||||
int64 fUnkownTicks;
|
int64 fUnkownTicks;
|
||||||
|
int64 fExpectedTicks;
|
||||||
int64 fDroppedTicks;
|
int64 fDroppedTicks;
|
||||||
int32 fNextImageOutputIndex;
|
int32 fNextImageOutputIndex;
|
||||||
int32 fNextFunctionOutputIndex;
|
int32 fNextFunctionOutputIndex;
|
||||||
|
|||||||
@@ -70,11 +70,13 @@ public:
|
|||||||
ProfiledEntity* Entity() const { return fEntity; }
|
ProfiledEntity* Entity() const { return fEntity; }
|
||||||
|
|
||||||
virtual void SetInterval(bigtime_t interval);
|
virtual void SetInterval(bigtime_t interval);
|
||||||
|
bigtime_t Interval() const { return fInterval; }
|
||||||
|
|
||||||
virtual void AddSamples(
|
virtual void AddSamples(
|
||||||
ImageProfileResultContainer* container,
|
ImageProfileResultContainer* container,
|
||||||
addr_t* samples,
|
addr_t* samples,
|
||||||
int32 sampleCount) = 0;
|
int32 sampleCount) = 0;
|
||||||
|
virtual void AddExpectedTicks(int32 expected) = 0;
|
||||||
virtual void AddDroppedTicks(int32 dropped) = 0;
|
virtual void AddDroppedTicks(int32 dropped) = 0;
|
||||||
virtual void PrintResults(
|
virtual void PrintResults(
|
||||||
ImageProfileResultContainer* container) = 0;
|
ImageProfileResultContainer* container) = 0;
|
||||||
|
|||||||
@@ -75,6 +75,13 @@ SummaryProfileResult::AddSamples(ImageProfileResultContainer* container,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SummaryProfileResult::AddExpectedTicks(int32 expected)
|
||||||
|
{
|
||||||
|
fResult->AddExpectedTicks(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SummaryProfileResult::AddDroppedTicks(int32 dropped)
|
SummaryProfileResult::AddDroppedTicks(int32 dropped)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ public:
|
|||||||
virtual void AddSamples(
|
virtual void AddSamples(
|
||||||
ImageProfileResultContainer* container,
|
ImageProfileResultContainer* container,
|
||||||
addr_t* samples, int32 sampleCount);
|
addr_t* samples, int32 sampleCount);
|
||||||
|
virtual void AddExpectedTicks(int32 expected);
|
||||||
virtual void AddDroppedTicks(int32 dropped);
|
virtual void AddDroppedTicks(int32 dropped);
|
||||||
virtual void PrintResults(
|
virtual void PrintResults(
|
||||||
ImageProfileResultContainer* container);
|
ImageProfileResultContainer* container);
|
||||||
|
|||||||
@@ -38,14 +38,15 @@ ThreadImage::~ThreadImage()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - ThreadI
|
// #pragma mark - Thread
|
||||||
|
|
||||||
|
|
||||||
Thread::Thread(thread_id threadID, const char* name, Team* team)
|
Thread::Thread(Team* team, thread_id threadID, const char* name, bigtime_t initialCPUTime)
|
||||||
:
|
:
|
||||||
|
fTeam(team),
|
||||||
fID(threadID),
|
fID(threadID),
|
||||||
fName(name),
|
fName(name),
|
||||||
fTeam(team),
|
fLastCPUTime(initialCPUTime),
|
||||||
fSampleArea(-1),
|
fSampleArea(-1),
|
||||||
fSamples(NULL),
|
fSamples(NULL),
|
||||||
fProfileResult(NULL),
|
fProfileResult(NULL),
|
||||||
@@ -227,6 +228,17 @@ Thread::AddSamples(addr_t* samples, int32 sampleCount)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Thread::UpdateCPUTime(bigtime_t time)
|
||||||
|
{
|
||||||
|
bigtime_t elapsed = time - fLastCPUTime;
|
||||||
|
int64 expectedTicks = elapsed / fProfileResult->Interval();
|
||||||
|
fLastCPUTime = time;
|
||||||
|
|
||||||
|
fProfileResult->AddExpectedTicks(expectedTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Thread::PrintResults()
|
Thread::PrintResults()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ private:
|
|||||||
class Thread : public ProfiledEntity, public DoublyLinkedListLinkImpl<Thread>,
|
class Thread : public ProfiledEntity, public DoublyLinkedListLinkImpl<Thread>,
|
||||||
private ImageProfileResultContainer {
|
private ImageProfileResultContainer {
|
||||||
public:
|
public:
|
||||||
Thread(thread_id threadID, const char* name,
|
Thread(Team* team, thread_id threadID,
|
||||||
Team* team);
|
const char* name, bigtime_t initialCPUTime);
|
||||||
virtual ~Thread();
|
virtual ~Thread();
|
||||||
|
|
||||||
inline thread_id ID() const;
|
inline thread_id ID() const;
|
||||||
@@ -66,6 +66,8 @@ public:
|
|||||||
int32 stackDepth, bool variableStackDepth,
|
int32 stackDepth, bool variableStackDepth,
|
||||||
int32 event);
|
int32 event);
|
||||||
void AddSamples(addr_t* samples, int32 sampleCount);
|
void AddSamples(addr_t* samples, int32 sampleCount);
|
||||||
|
void UpdateCPUTime(bigtime_t time);
|
||||||
|
|
||||||
void PrintResults();
|
void PrintResults();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -82,9 +84,10 @@ private:
|
|||||||
void _SynchronizeImages(int32 event);
|
void _SynchronizeImages(int32 event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
::Team* fTeam;
|
||||||
thread_id fID;
|
thread_id fID;
|
||||||
BString fName;
|
BString fName;
|
||||||
::Team* fTeam;
|
bigtime_t fLastCPUTime;
|
||||||
area_id fSampleArea;
|
area_id fSampleArea;
|
||||||
addr_t* fSamples;
|
addr_t* fSamples;
|
||||||
ProfileResult* fProfileResult;
|
ProfileResult* fProfileResult;
|
||||||
|
|||||||
@@ -162,10 +162,11 @@ public:
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
return AddThread(threadInfo.team, threadID, threadInfo.name);
|
return AddThread(threadInfo.team, threadID, threadInfo.name,
|
||||||
|
threadInfo.kernel_time + threadInfo.user_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t AddThread(team_id teamID, thread_id threadID, const char* name)
|
status_t AddThread(team_id teamID, thread_id threadID, const char* name, bigtime_t cpuTime)
|
||||||
{
|
{
|
||||||
if (FindThread(threadID) != NULL)
|
if (FindThread(threadID) != NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -174,7 +175,7 @@ public:
|
|||||||
if (team == NULL)
|
if (team == NULL)
|
||||||
return B_BAD_TEAM_ID;
|
return B_BAD_TEAM_ID;
|
||||||
|
|
||||||
Thread* thread = new(std::nothrow) Thread(threadID, name, team);
|
Thread* thread = new(std::nothrow) Thread(team, threadID, name, cpuTime);
|
||||||
if (thread == NULL)
|
if (thread == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -578,7 +579,7 @@ process_event_buffer(ThreadManager& threadManager, uint8* buffer,
|
|||||||
= (system_profiler_thread_added*)buffer;
|
= (system_profiler_thread_added*)buffer;
|
||||||
|
|
||||||
if (threadManager.AddThread(event->team, event->thread,
|
if (threadManager.AddThread(event->team, event->thread,
|
||||||
event->name) != B_OK) {
|
event->name, event->cpu_time) != B_OK) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -590,6 +591,7 @@ process_event_buffer(ThreadManager& threadManager, uint8* buffer,
|
|||||||
= (system_profiler_thread_removed*)buffer;
|
= (system_profiler_thread_removed*)buffer;
|
||||||
|
|
||||||
if (Thread* thread = threadManager.FindThread(event->thread)) {
|
if (Thread* thread = threadManager.FindThread(event->thread)) {
|
||||||
|
thread->UpdateCPUTime(event->cpu_time);
|
||||||
thread->PrintResults();
|
thread->PrintResults();
|
||||||
threadManager.RemoveThread(event->thread);
|
threadManager.RemoveThread(event->thread);
|
||||||
}
|
}
|
||||||
@@ -765,8 +767,19 @@ profile_all(const char* const* programArgs, int programArgCount)
|
|||||||
// stop profiling
|
// stop profiling
|
||||||
_kern_system_profiler_stop();
|
_kern_system_profiler_stop();
|
||||||
|
|
||||||
|
// fetch CPU time for all remaining threads
|
||||||
|
const int32 threadCount = threadManager.CountThreads();
|
||||||
|
for (int32 i = 0; i < threadCount; i++) {
|
||||||
|
Thread* thread = threadManager.ThreadAt(i);
|
||||||
|
thread_info threadInfo;
|
||||||
|
status_t error = get_thread_info(thread->ID(), &threadInfo);
|
||||||
|
if (error != B_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
thread->UpdateCPUTime(threadInfo.kernel_time + threadInfo.user_time);
|
||||||
|
}
|
||||||
|
|
||||||
// print results
|
// print results
|
||||||
int32 threadCount = threadManager.CountThreads();
|
|
||||||
for (int32 i = 0; i < threadCount; i++) {
|
for (int32 i = 0; i < threadCount; i++) {
|
||||||
Thread* thread = threadManager.ThreadAt(i);
|
Thread* thread = threadManager.ThreadAt(i);
|
||||||
thread->PrintResults();
|
thread->PrintResults();
|
||||||
@@ -919,6 +932,7 @@ profile_single(const char* const* programArgs, int programArgCount)
|
|||||||
message.profiler_update.image_event);
|
message.profiler_update.image_event);
|
||||||
|
|
||||||
if (message.profiler_update.stopped) {
|
if (message.profiler_update.stopped) {
|
||||||
|
thread->UpdateCPUTime(message.profiler_update.last_cpu_time);
|
||||||
thread->PrintResults();
|
thread->PrintResults();
|
||||||
threadManager.RemoveThread(thread->ID());
|
threadManager.RemoveThread(thread->ID());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -976,6 +976,10 @@ SystemProfiler::_ThreadAdded(Thread* thread)
|
|||||||
event->team = thread->team->id;
|
event->team = thread->team->id;
|
||||||
event->thread = thread->id;
|
event->thread = thread->id;
|
||||||
strlcpy(event->name, thread->name, sizeof(event->name));
|
strlcpy(event->name, thread->name, sizeof(event->name));
|
||||||
|
{
|
||||||
|
SpinLocker timeLocker(thread->time_lock);
|
||||||
|
event->cpu_time = thread->CPUTime(false);
|
||||||
|
}
|
||||||
|
|
||||||
fHeader->size = fBufferSize;
|
fHeader->size = fBufferSize;
|
||||||
|
|
||||||
@@ -1003,6 +1007,10 @@ SystemProfiler::_ThreadRemoved(Thread* thread)
|
|||||||
|
|
||||||
event->team = thread->team->id;
|
event->team = thread->team->id;
|
||||||
event->thread = thread->id;
|
event->thread = thread->id;
|
||||||
|
{
|
||||||
|
SpinLocker timeLocker(thread->time_lock);
|
||||||
|
event->cpu_time = thread->CPUTime(false);
|
||||||
|
}
|
||||||
|
|
||||||
fHeader->size = fBufferSize;
|
fHeader->size = fBufferSize;
|
||||||
|
|
||||||
|
|||||||
@@ -1177,6 +1177,10 @@ user_debug_thread_exiting(Thread* thread)
|
|||||||
threadDebugInfo.profile.sample_area = -1;
|
threadDebugInfo.profile.sample_area = -1;
|
||||||
threadDebugInfo.profile.samples = NULL;
|
threadDebugInfo.profile.samples = NULL;
|
||||||
threadDebugInfo.profile.buffer_full = false;
|
threadDebugInfo.profile.buffer_full = false;
|
||||||
|
bigtime_t lastCPUTime; {
|
||||||
|
SpinLocker threadTimeLocker(thread->time_lock);
|
||||||
|
lastCPUTime = thread->CPUTime(false);
|
||||||
|
}
|
||||||
|
|
||||||
atomic_or(&threadDebugInfo.flags, B_THREAD_DEBUG_DYING);
|
atomic_or(&threadDebugInfo.flags, B_THREAD_DEBUG_DYING);
|
||||||
|
|
||||||
@@ -1194,6 +1198,7 @@ user_debug_thread_exiting(Thread* thread)
|
|||||||
message.variable_stack_depth = variableStackDepth;
|
message.variable_stack_depth = variableStackDepth;
|
||||||
message.image_event = imageEvent;
|
message.image_event = imageEvent;
|
||||||
message.stopped = true;
|
message.stopped = true;
|
||||||
|
message.last_cpu_time = lastCPUTime;
|
||||||
debugger_write(debuggerPort, B_DEBUGGER_MESSAGE_PROFILER_UPDATE,
|
debugger_write(debuggerPort, B_DEBUGGER_MESSAGE_PROFILER_UPDATE,
|
||||||
&message, sizeof(message), false);
|
&message, sizeof(message), false);
|
||||||
|
|
||||||
@@ -2375,6 +2380,7 @@ debug_nub_thread(void *)
|
|||||||
bool variableStackDepth = false;
|
bool variableStackDepth = false;
|
||||||
int32 imageEvent = 0;
|
int32 imageEvent = 0;
|
||||||
int32 droppedTicks = 0;
|
int32 droppedTicks = 0;
|
||||||
|
bigtime_t lastCPUTime = 0;
|
||||||
|
|
||||||
// get the thread and detach the profile info
|
// get the thread and detach the profile info
|
||||||
Thread* thread = Thread::GetAndLock(threadID);
|
Thread* thread = Thread::GetAndLock(threadID);
|
||||||
@@ -2400,6 +2406,10 @@ debug_nub_thread(void *)
|
|||||||
threadDebugInfo.profile.samples = NULL;
|
threadDebugInfo.profile.samples = NULL;
|
||||||
threadDebugInfo.profile.buffer_full = false;
|
threadDebugInfo.profile.buffer_full = false;
|
||||||
threadDebugInfo.profile.dropped_ticks = 0;
|
threadDebugInfo.profile.dropped_ticks = 0;
|
||||||
|
{
|
||||||
|
SpinLocker threadTimeLocker(thread->time_lock);
|
||||||
|
lastCPUTime = thread->CPUTime(false);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
result = B_BAD_VALUE;
|
result = B_BAD_VALUE;
|
||||||
} else
|
} else
|
||||||
@@ -2417,6 +2427,7 @@ debug_nub_thread(void *)
|
|||||||
reply.profiler_update.sample_count = sampleCount;
|
reply.profiler_update.sample_count = sampleCount;
|
||||||
reply.profiler_update.dropped_ticks = droppedTicks;
|
reply.profiler_update.dropped_ticks = droppedTicks;
|
||||||
reply.profiler_update.stopped = true;
|
reply.profiler_update.stopped = true;
|
||||||
|
reply.profiler_update.last_cpu_time = lastCPUTime;
|
||||||
} else
|
} else
|
||||||
reply.profiler_update.origin.thread = result;
|
reply.profiler_update.origin.thread = result;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user