Make KernelState::TerminateTitle try to terminate XThreads safely.
This commit is contained in:
parent
3007a98d2d
commit
24f8295daa
|
@ -358,8 +358,6 @@ bool Emulator::SaveToFile(const std::wstring& path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Emulator::RestoreFromFile(const std::wstring& path) {
|
bool Emulator::RestoreFromFile(const std::wstring& path) {
|
||||||
auto lock = global_critical_region::AcquireDirect();
|
|
||||||
|
|
||||||
// Restore the emulator state from a file
|
// Restore the emulator state from a file
|
||||||
auto map = MappedMemory::Open(path, MappedMemory::Mode::kReadWrite);
|
auto map = MappedMemory::Open(path, MappedMemory::Mode::kReadWrite);
|
||||||
if (!map) {
|
if (!map) {
|
||||||
|
@ -372,6 +370,7 @@ bool Emulator::RestoreFromFile(const std::wstring& path) {
|
||||||
Pause();
|
Pause();
|
||||||
kernel_state_->TerminateTitle();
|
kernel_state_->TerminateTitle();
|
||||||
|
|
||||||
|
auto lock = global_critical_region::AcquireDirect();
|
||||||
ByteStream stream(map->data(), map->size());
|
ByteStream stream(map->data(), map->size());
|
||||||
if (stream.Read<uint32_t>() != 'XSAV') {
|
if (stream.Read<uint32_t>() != 'XSAV') {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -120,6 +120,7 @@ class Emulator {
|
||||||
|
|
||||||
void Pause();
|
void Pause();
|
||||||
void Resume();
|
void Resume();
|
||||||
|
bool is_paused() const { return paused_; }
|
||||||
|
|
||||||
bool SaveToFile(const std::wstring& path);
|
bool SaveToFile(const std::wstring& path);
|
||||||
bool RestoreFromFile(const std::wstring& path);
|
bool RestoreFromFile(const std::wstring& path);
|
||||||
|
|
|
@ -334,6 +334,7 @@ object_ref<UserModule> KernelState::LoadUserModule(const char* raw_name,
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelState::TerminateTitle(bool from_guest_thread) {
|
void KernelState::TerminateTitle(bool from_guest_thread) {
|
||||||
|
XELOGD("KernelState::TerminateTitle");
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
|
|
||||||
// Call terminate routines.
|
// Call terminate routines.
|
||||||
|
@ -351,6 +352,8 @@ void KernelState::TerminateTitle(bool from_guest_thread) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Kill all guest threads.
|
// Kill all guest threads.
|
||||||
|
// Need to not be holding the lock to do this.
|
||||||
|
global_lock.unlock();
|
||||||
for (auto it = threads_by_id_.begin(); it != threads_by_id_.end();) {
|
for (auto it = threads_by_id_.begin(); it != threads_by_id_.end();) {
|
||||||
if (it->second->is_guest_thread()) {
|
if (it->second->is_guest_thread()) {
|
||||||
auto thread = it->second;
|
auto thread = it->second;
|
||||||
|
@ -362,10 +365,14 @@ void KernelState::TerminateTitle(bool from_guest_thread) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread->is_running()) {
|
if (thread->is_running()) {
|
||||||
// TODO: Need to step the thread to a safe point (returns it to guest
|
// Need to step the thread to a safe point (returns it to guest code
|
||||||
// code so it's guaranteed to not be holding any locks / in host kernel
|
// so it's guaranteed to not be holding any locks / in host kernel
|
||||||
// code / etc). Can't do that properly if we have the lock.
|
// code / etc). Can't do that properly if we have the lock.
|
||||||
// thread->StepToSafePoint();
|
if (!emulator_->is_paused()) {
|
||||||
|
thread->thread()->Suspend();
|
||||||
|
}
|
||||||
|
|
||||||
|
thread->StepToSafePoint();
|
||||||
thread->Terminate(0);
|
thread->Terminate(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,6 +382,7 @@ void KernelState::TerminateTitle(bool from_guest_thread) {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
global_lock.lock();
|
||||||
|
|
||||||
// Third: Unload all user modules (including the executable)
|
// Third: Unload all user modules (including the executable)
|
||||||
for (int i = 0; i < user_modules_.size(); i++) {
|
for (int i = 0; i < user_modules_.size(); i++) {
|
||||||
|
@ -611,6 +619,8 @@ bool KernelState::Save(ByteStream* stream) {
|
||||||
|
|
||||||
stream->Write((uint32_t)object->type());
|
stream->Write((uint32_t)object->type());
|
||||||
if (object->is_host_object() || !object->Save(stream)) {
|
if (object->is_host_object() || !object->Save(stream)) {
|
||||||
|
XELOGD("Did not save object of type %d", object->type());
|
||||||
|
|
||||||
// Revert backwards and overwrite if a save failed.
|
// Revert backwards and overwrite if a save failed.
|
||||||
stream->set_offset(prev_offset);
|
stream->set_offset(prev_offset);
|
||||||
num_objects--;
|
num_objects--;
|
||||||
|
|
|
@ -142,6 +142,7 @@ class KernelState {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Terminates a title: Unloads all modules, and kills all guest threads.
|
// Terminates a title: Unloads all modules, and kills all guest threads.
|
||||||
|
// This DOES NOT RETURN if called from a guest thread!
|
||||||
void TerminateTitle(bool from_guest_thread = false);
|
void TerminateTitle(bool from_guest_thread = false);
|
||||||
|
|
||||||
void RegisterThread(XThread* thread);
|
void RegisterThread(XThread* thread);
|
||||||
|
|
Loading…
Reference in New Issue