Save/Restore the guest clock in XThreads
This commit is contained in:
parent
adec5602c2
commit
44c9e8fe25
|
@ -84,6 +84,16 @@ uint32_t Clock::QueryGuestUptimeMillis() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Clock::SetGuestTickCount(uint64_t tick_count) {
|
||||||
|
last_host_tick_count_ = Clock::QueryHostTickCount();
|
||||||
|
guest_tick_count_ = tick_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clock::SetGuestSystemTime(uint64_t system_time) {
|
||||||
|
last_host_tick_count_ = Clock::QueryHostTickCount();
|
||||||
|
guest_time_filetime_ = system_time - guest_system_time_base_;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t Clock::ScaleGuestDurationMillis(uint32_t guest_ms) {
|
uint32_t Clock::ScaleGuestDurationMillis(uint32_t guest_ms) {
|
||||||
if (guest_ms == UINT_MAX) {
|
if (guest_ms == UINT_MAX) {
|
||||||
return UINT_MAX;
|
return UINT_MAX;
|
||||||
|
|
|
@ -47,6 +47,11 @@ class Clock {
|
||||||
// Queries the milliseconds since the guest began, accounting for scaling.
|
// Queries the milliseconds since the guest began, accounting for scaling.
|
||||||
static uint32_t QueryGuestUptimeMillis();
|
static uint32_t QueryGuestUptimeMillis();
|
||||||
|
|
||||||
|
// Sets the guest tick count for the current thread.
|
||||||
|
static void SetGuestTickCount(uint64_t tick_count);
|
||||||
|
// Sets the system time for the current thread.
|
||||||
|
static void SetGuestSystemTime(uint64_t system_time);
|
||||||
|
|
||||||
// Scales a time duration in milliseconds, from guest time.
|
// Scales a time duration in milliseconds, from guest time.
|
||||||
static uint32_t ScaleGuestDurationMillis(uint32_t guest_ms);
|
static uint32_t ScaleGuestDurationMillis(uint32_t guest_ms);
|
||||||
// Scales a time duration in 100ns ticks like FILETIME, from guest time.
|
// Scales a time duration in 100ns ticks like FILETIME, from guest time.
|
||||||
|
|
|
@ -912,6 +912,7 @@ uint32_t XThread::StepToSafePoint(bool ignore_host) {
|
||||||
if (cpu_frames[i].type == cpu::StackFrame::Type::kGuest &&
|
if (cpu_frames[i].type == cpu::StackFrame::Type::kGuest &&
|
||||||
cpu_frames[i].guest_pc) {
|
cpu_frames[i].guest_pc) {
|
||||||
first_frame = cpu_frames[i];
|
first_frame = cpu_frames[i];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1019,6 +1020,11 @@ uint32_t XThread::StepToSafePoint(bool ignore_host) {
|
||||||
struct ThreadSavedState {
|
struct ThreadSavedState {
|
||||||
uint32_t thread_id;
|
uint32_t thread_id;
|
||||||
bool main_thread;
|
bool main_thread;
|
||||||
|
|
||||||
|
// Clock settings
|
||||||
|
uint64_t tick_count_;
|
||||||
|
uint64_t system_time_;
|
||||||
|
|
||||||
uint32_t apc_head;
|
uint32_t apc_head;
|
||||||
uint32_t tls_address;
|
uint32_t tls_address;
|
||||||
uint32_t pcr_address;
|
uint32_t pcr_address;
|
||||||
|
@ -1076,6 +1082,10 @@ bool XThread::Save(ByteStream* stream) {
|
||||||
state.stack_alloc_base = stack_alloc_base_;
|
state.stack_alloc_base = stack_alloc_base_;
|
||||||
state.stack_alloc_size = stack_alloc_size_;
|
state.stack_alloc_size = stack_alloc_size_;
|
||||||
|
|
||||||
|
state.tick_count_ = Clock::QueryGuestTickCount();
|
||||||
|
state.system_time_ =
|
||||||
|
Clock::QueryGuestSystemTime() - Clock::guest_system_time_base();
|
||||||
|
|
||||||
// Context information
|
// Context information
|
||||||
auto context = thread_state_->context();
|
auto context = thread_state_->context();
|
||||||
state.context.lr = context->lr;
|
state.context.lr = context->lr;
|
||||||
|
@ -1118,6 +1128,8 @@ object_ref<XThread> XThread::Restore(KernelState* kernel_state,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XELOGD("XThread %.8X", thread->handle());
|
||||||
|
|
||||||
thread->name_ = stream->Read<std::string>();
|
thread->name_ = stream->Read<std::string>();
|
||||||
|
|
||||||
ThreadSavedState state;
|
ThreadSavedState state;
|
||||||
|
@ -1160,7 +1172,6 @@ object_ref<XThread> XThread::Restore(KernelState* kernel_state,
|
||||||
context->xer_ov = state.context.xer_ov;
|
context->xer_ov = state.context.xer_ov;
|
||||||
context->xer_so = state.context.xer_so;
|
context->xer_so = state.context.xer_so;
|
||||||
context->vscr_sat = state.context.vscr_sat;
|
context->vscr_sat = state.context.vscr_sat;
|
||||||
auto pc = state.context.pc;
|
|
||||||
|
|
||||||
// Always retain when starting - the thread owns itself until exited.
|
// Always retain when starting - the thread owns itself until exited.
|
||||||
thread->Retain();
|
thread->Retain();
|
||||||
|
@ -1169,7 +1180,7 @@ object_ref<XThread> XThread::Restore(KernelState* kernel_state,
|
||||||
xe::threading::Thread::CreationParameters params;
|
xe::threading::Thread::CreationParameters params;
|
||||||
params.create_suspended = true; // Not done restoring yet.
|
params.create_suspended = true; // Not done restoring yet.
|
||||||
params.stack_size = 16 * 1024 * 1024;
|
params.stack_size = 16 * 1024 * 1024;
|
||||||
thread->thread_ = xe::threading::Thread::Create(params, [thread, pc]() {
|
thread->thread_ = xe::threading::Thread::Create(params, [thread, state]() {
|
||||||
// Set thread ID override. This is used by logging.
|
// Set thread ID override. This is used by logging.
|
||||||
xe::threading::set_current_thread_id(thread->handle());
|
xe::threading::set_current_thread_id(thread->handle());
|
||||||
|
|
||||||
|
@ -1179,10 +1190,17 @@ object_ref<XThread> XThread::Restore(KernelState* kernel_state,
|
||||||
// Profiler needs to know about the thread.
|
// Profiler needs to know about the thread.
|
||||||
xe::Profiler::ThreadEnter(thread->name().c_str());
|
xe::Profiler::ThreadEnter(thread->name().c_str());
|
||||||
|
|
||||||
|
// Setup the time now that we're in the thread.
|
||||||
|
Clock::SetGuestTickCount(state.tick_count_);
|
||||||
|
Clock::SetGuestSystemTime(state.system_time_);
|
||||||
|
|
||||||
// Execute user code.
|
// Execute user code.
|
||||||
thread->running_ = true;
|
thread->running_ = true;
|
||||||
current_thread_tls_ = thread;
|
current_thread_tls_ = thread;
|
||||||
|
|
||||||
|
uint32_t pc = state.context.pc;
|
||||||
thread->kernel_state()->processor()->ExecuteRaw(thread->thread_state_, pc);
|
thread->kernel_state()->processor()->ExecuteRaw(thread->thread_state_, pc);
|
||||||
|
|
||||||
current_thread_tls_ = nullptr;
|
current_thread_tls_ = nullptr;
|
||||||
|
|
||||||
xe::Profiler::ThreadExit();
|
xe::Profiler::ThreadExit();
|
||||||
|
|
Loading…
Reference in New Issue