WaitProcessWideKeyAtomic: Handle case where condition variable was already created.
This commit is contained in:
parent
647364db8f
commit
0b6b147939
3 changed files with 17 additions and 13 deletions
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue