Save/Restore the guest clock in XThreads

This commit is contained in:
Dr. Chat 2015-12-12 16:44:59 -06:00 committed by Ben Vanik
parent adec5602c2
commit 44c9e8fe25
3 changed files with 35 additions and 2 deletions

View File

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

View File

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

View File

@ -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();