WaitProcessWideKeyAtomic: Handle case where condition variable was already created.

This commit is contained in:
bunnei 2018-02-04 12:30:51 -05:00
parent 647364db8f
commit 0b6b147939
3 changed files with 17 additions and 13 deletions

View file

@ -15,13 +15,12 @@ ConditionVariable::ConditionVariable() {}
ConditionVariable::~ConditionVariable() {} ConditionVariable::~ConditionVariable() {}
ResultVal<SharedPtr<ConditionVariable>> ConditionVariable::Create(VAddr guest_addr, ResultVal<SharedPtr<ConditionVariable>> ConditionVariable::Create(VAddr guest_addr,
VAddr mutex_addr,
std::string name) { std::string name) {
SharedPtr<ConditionVariable> condition_variable(new ConditionVariable); SharedPtr<ConditionVariable> condition_variable(new ConditionVariable);
condition_variable->name = std::move(name); condition_variable->name = std::move(name);
condition_variable->guest_addr = guest_addr; condition_variable->guest_addr = guest_addr;
condition_variable->mutex_addr = mutex_addr; condition_variable->mutex_addr = 0;
// Condition variables are referenced by guest address, so track this in the kernel // Condition variables are referenced by guest address, so track this in the kernel
g_object_address_table.Insert(guest_addr, condition_variable); g_object_address_table.Insert(guest_addr, condition_variable);

View file

@ -19,12 +19,10 @@ public:
* Creates a condition variable. * Creates a condition variable.
* @param guest_addr Address of the object tracking the condition variable in guest memory. If * @param guest_addr Address of the object tracking the condition variable in guest memory. If
* specified, this condition variable will update the guest object when its state changes. * specified, this condition variable will update the guest object when its state changes.
* @param mutex_addr Optional address of a guest mutex associated with this condition variable,
* used by the OS for implementing events.
* @param name Optional name of condition variable. * @param name Optional name of condition variable.
* @return The created condition variable. * @return The created condition variable.
*/ */
static ResultVal<SharedPtr<ConditionVariable>> Create(VAddr guest_addr, VAddr mutex_addr = 0, static ResultVal<SharedPtr<ConditionVariable>> Create(VAddr guest_addr,
std::string name = "Unknown"); std::string name = "Unknown");
std::string GetTypeName() const override { std::string GetTypeName() const override {

View file

@ -612,20 +612,29 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr); mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr);
} }
ASSERT(mutex->GetOwnerHandle() == thread_handle);
SharedPtr<ConditionVariable> condition_variable = SharedPtr<ConditionVariable> condition_variable =
g_object_address_table.Get<ConditionVariable>(condition_variable_addr); g_object_address_table.Get<ConditionVariable>(condition_variable_addr);
if (!condition_variable) { if (!condition_variable) {
// Create a new condition_variable for the specified address if one does not already exist // Create a new condition_variable for the specified address if one does not already exist
condition_variable = condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap();
ConditionVariable::Create(condition_variable_addr, mutex_addr).Unwrap();
condition_variable->name = condition_variable->name =
Common::StringFromFormat("condition-variable-%llx", condition_variable_addr); Common::StringFromFormat("condition-variable-%llx", condition_variable_addr);
} }
ASSERT(condition_variable->GetAvailableCount() == 0); if (condition_variable->mutex_addr) {
// Previously created the ConditionVariable using WaitProcessWideKeyAtomic, verify
// everything is correct
ASSERT(condition_variable->mutex_addr == mutex_addr); ASSERT(condition_variable->mutex_addr == mutex_addr);
} else {
// Previously created the ConditionVariable using SignalProcessWideKey, set the mutex
// associated with it
condition_variable->mutex_addr = mutex_addr;
}
if (mutex->GetOwnerHandle()) {
// Release the mutex if the current thread is holding it
mutex->Release(thread.get());
}
auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason, auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason,
SharedPtr<Thread> thread, SharedPtr<Thread> thread,
@ -667,8 +676,6 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
CASCADE_CODE( CASCADE_CODE(
WaitSynchronization1(condition_variable, thread.get(), nano_seconds, wakeup_callback)); WaitSynchronization1(condition_variable, thread.get(), nano_seconds, wakeup_callback));
mutex->Release(thread.get());
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }