kernel/svc: Move address arbiter waiting behind a unified API function

Rather than let the service call itself work out which function is the
proper one to call, we can make that a behavior of the arbiter itself,
so we don't need to directly expose those implementation details.
This commit is contained in:
Lioncash 2019-03-07 18:34:22 -05:00
parent 3b63a46ca4
commit 0209de123b
3 changed files with 24 additions and 19 deletions

View File

@ -92,6 +92,20 @@ ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr a
return RESULT_SUCCESS;
}
ResultCode AddressArbiter::WaitForAddress(VAddr address, ArbitrationType type, s32 value,
s64 timeout_ns) {
switch (type) {
case ArbitrationType::WaitIfLessThan:
return WaitForAddressIfLessThan(address, value, timeout_ns, false);
case ArbitrationType::DecrementAndWaitIfLessThan:
return WaitForAddressIfLessThan(address, value, timeout_ns, true);
case ArbitrationType::WaitIfEqual:
return WaitForAddressIfEqual(address, value, timeout_ns);
default:
return ERR_INVALID_ENUM_VALUE;
}
}
ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout,
bool should_decrement) {
// Ensure that we can read the address.
@ -113,7 +127,7 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6
return RESULT_TIMEOUT;
}
return WaitForAddress(address, timeout);
return WaitForAddressImpl(address, timeout);
}
ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) {
@ -130,10 +144,10 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t
return RESULT_TIMEOUT;
}
return WaitForAddress(address, timeout);
return WaitForAddressImpl(address, timeout);
}
ResultCode AddressArbiter::WaitForAddress(VAddr address, s64 timeout) {
ResultCode AddressArbiter::WaitForAddressImpl(VAddr address, s64 timeout) {
SharedPtr<Thread> current_thread = system.CurrentScheduler().GetCurrentThread();
current_thread->SetArbiterWaitAddress(address);
current_thread->SetStatus(ThreadStatus::WaitArb);

View File

@ -51,6 +51,10 @@ public:
ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value,
s32 num_to_wake);
/// Waits on an address with a particular arbitration type.
ResultCode WaitForAddress(VAddr address, ArbitrationType type, s32 value, s64 timeout_ns);
private:
/// Waits on an address if the value passed is less than the argument value,
/// optionally decrementing.
ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout,
@ -59,9 +63,8 @@ public:
/// Waits on an address if the value passed is equal to the argument value.
ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout);
private:
// Waits on the given address with a timeout in nanoseconds
ResultCode WaitForAddress(VAddr address, s64 timeout);
ResultCode WaitForAddressImpl(VAddr address, s64 timeout);
// Gets the threads waiting on an address.
std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) const;

View File

@ -1479,21 +1479,9 @@ static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout
return ERR_INVALID_ADDRESS;
}
const auto arbitration_type = static_cast<AddressArbiter::ArbitrationType>(type);
auto& address_arbiter = Core::System::GetInstance().Kernel().AddressArbiter();
switch (static_cast<AddressArbiter::ArbitrationType>(type)) {
case AddressArbiter::ArbitrationType::WaitIfLessThan:
return address_arbiter.WaitForAddressIfLessThan(address, value, timeout, false);
case AddressArbiter::ArbitrationType::DecrementAndWaitIfLessThan:
return address_arbiter.WaitForAddressIfLessThan(address, value, timeout, true);
case AddressArbiter::ArbitrationType::WaitIfEqual:
return address_arbiter.WaitForAddressIfEqual(address, value, timeout);
default:
LOG_ERROR(Kernel_SVC,
"Invalid arbitration type, expected WaitIfLessThan, DecrementAndWaitIfLessThan "
"or WaitIfEqual but got {}",
type);
return ERR_INVALID_ENUM_VALUE;
}
return address_arbiter.WaitForAddress(address, arbitration_type, value, timeout);
}
// Signals to an address (via Address Arbiter)