XThread acquire mutants on restore

This commit is contained in:
Dr. Chat 2015-12-27 17:16:35 -06:00 committed by Ben Vanik
parent 5c94062110
commit bca5fb5382
3 changed files with 31 additions and 10 deletions

View File

@ -54,12 +54,14 @@ X_STATUS XMutant::ReleaseMutant(uint32_t priority_increment, bool abandon,
}
bool XMutant::Save(ByteStream* stream) {
XELOGD("XMutant %.8X", handle());
if (!SaveObject(stream)) {
return false;
}
stream->Write(owning_thread_->handle());
uint32_t owning_thread_handle = owning_thread_ ? owning_thread_->handle() : 0;
stream->Write<uint32_t>(owning_thread_handle);
XELOGD("XMutant %.8X (owner: %.8X)", handle(), owning_thread_handle);
return true;
}
@ -75,11 +77,13 @@ object_ref<XMutant> XMutant::Restore(KernelState* kernel_state,
mutant->Initialize(false);
// TODO: Make the thread acquire this mutex... Somehow.
auto owning_thread_handle = stream->Read<uint32_t>();
mutant->owning_thread_ = kernel_state->object_table()
->LookupObject<XThread>(owning_thread_handle)
.get();
if (owning_thread_handle) {
mutant->owning_thread_ = kernel_state->object_table()
->LookupObject<XThread>(owning_thread_handle)
.get();
mutant->owning_thread_->AcquireMutantOnStartup(retain_object(mutant));
}
return object_ref<XMutant>(mutant);
}

View File

@ -27,6 +27,7 @@
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/user_module.h"
#include "xenia/kernel/xevent.h"
#include "xenia/kernel/xmutant.h"
DEFINE_bool(ignore_thread_priorities, true,
"Ignores game-specified thread priorities.");
@ -1218,13 +1219,21 @@ object_ref<XThread> XThread::Restore(KernelState* kernel_state,
Clock::SetGuestTickCount(state.tick_count_);
Clock::SetGuestSystemTime(state.system_time_);
// Execute user code.
thread->running_ = true;
current_thread_tls_ = thread;
// Acquire any mutants
for (auto mutant : thread->pending_mutant_acquires_) {
uint64_t timeout = 0;
auto status = mutant->Wait(0, 0, 0, &timeout);
assert_true(status == X_STATUS_SUCCESS);
}
thread->pending_mutant_acquires_.clear();
// Execute user code.
thread->running_ = true;
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;

View File

@ -18,6 +18,7 @@
#include "xenia/cpu/thread_state.h"
#include "xenia/kernel/util/native_list.h"
#include "xenia/kernel/xobject.h"
#include "xenia/kernel/xmutant.h"
#include "xenia/xbox.h"
namespace xe {
@ -190,6 +191,11 @@ class XThread : public XObject {
static object_ref<XThread> Restore(KernelState* kernel_state,
ByteStream* stream);
// Internal - do not use.
void AcquireMutantOnStartup(object_ref<XMutant> mutant) {
pending_mutant_acquires_.push_back(mutant);
}
// Steps the thread to a point where it's safe to terminate or read its
// context. Returns the PC after we've finished stepping.
// Pass true for ignore_host if you've stopped the thread yourself
@ -210,6 +216,8 @@ class XThread : public XObject {
CreationParams creation_params_ = {0};
std::vector<object_ref<XMutant>> pending_mutant_acquires_;
uint32_t thread_id_ = 0;
std::unique_ptr<xe::threading::Thread> thread_;
uint32_t scratch_address_ = 0;