Make Applet accesses to the data queues lock

Avoids potential races when the guest access the same applet from more than one thread.
This commit is contained in:
MCredstoner2004 2022-06-01 17:17:38 -05:00 committed by GitHub
parent 91b2c47991
commit c15b3a8d40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 8 deletions

View File

@ -21,12 +21,12 @@ namespace skyline::applet {
// Generic macro due to both versions of arguments sharing the same fields but having different layouts
auto handle{[&](auto controllerSupportModeArg) {
Logger::InfoNoPrefix("Controller Support: "
"Player Count: {} - {}, "
"Take Over Connection: {}, Left Justify: {}, Dual Joy-Con Allowed: {}, Single Mode Enabled: {}, "
"Identification Color Enabled: {}, Explain Text Enabled: {}",
controllerSupportModeArg.playerCountMin, controllerSupportModeArg.playerCountMax,
controllerSupportModeArg.enableTakeOverConnection, controllerSupportModeArg.enableLeftJustify, controllerSupportModeArg.enablePermitJoyDual, controllerSupportModeArg.enableSingleMode,
controllerSupportModeArg.enableIdentificationColor, controllerSupportModeArg.enableExplainText);
"Player Count: {} - {}, "
"Take Over Connection: {}, Left Justify: {}, Dual Joy-Con Allowed: {}, Single Mode Enabled: {}, "
"Identification Color Enabled: {}, Explain Text Enabled: {}",
controllerSupportModeArg.playerCountMin, controllerSupportModeArg.playerCountMax,
controllerSupportModeArg.enableTakeOverConnection, controllerSupportModeArg.enableLeftJustify, controllerSupportModeArg.enablePermitJoyDual, controllerSupportModeArg.enableSingleMode,
controllerSupportModeArg.enableIdentificationColor, controllerSupportModeArg.enableExplainText);
// Here is where we would trigger the applet UI
@ -62,6 +62,7 @@ namespace skyline::applet {
break;
}
}
Result ControllerApplet::Start() {
auto commonArg{PopNormalInput<service::applet::CommonArguments>()};
ControllerAppletVersion appletVersion{commonArg.apiVersion};
@ -81,6 +82,7 @@ namespace skyline::applet {
}
}
std::scoped_lock lock{inputDataMutex};
switch (argPrivate.mode) {
case ControllerSupportMode::ShowControllerSupport:
HandleShowControllerSupport(argPrivate.styleSet, appletVersion, normalInputData.front()->GetSpan());
@ -105,6 +107,7 @@ namespace skyline::applet {
}
void ControllerApplet::PushNormalDataToApplet(std::shared_ptr<service::am::IStorage> data) {
std::scoped_lock lock{inputDataMutex};
normalInputData.emplace(std::move(data));
}

View File

@ -98,10 +98,12 @@ namespace skyline::applet {
};
static_assert(sizeof(ControllerSupportResultInfo) == 0xC);
std::mutex inputDataMutex;
std::queue<std::shared_ptr<service::am::IStorage>> normalInputData;
template<typename T>
T PopNormalInput() {
std::scoped_lock lock{inputDataMutex};
auto data{normalInputData.front()->GetSpan().as<T>()};
normalInputData.pop();
return static_cast<T>(data);

View File

@ -13,16 +13,19 @@ namespace skyline::service::am {
IApplet::~IApplet() = default;
void IApplet::PushNormalDataAndSignal(std::shared_ptr<IStorage> data) {
std::scoped_lock lock{outputDataMutex};
normalOutputData.emplace(std::move(data));
onNormalDataPushFromApplet->Signal();
}
void IApplet::PushInteractiveDataAndSignal(std::shared_ptr<IStorage> data) {
std::scoped_lock lock{interactiveOutputDataMutex};
interactiveOutputData.emplace(std::move(data));
onInteractiveDataPushFromApplet->Signal();
}
std::shared_ptr<IStorage> IApplet::PopNormalAndClear() {
std::scoped_lock lock{outputDataMutex};
if (normalOutputData.empty())
return {};
std::shared_ptr<IStorage> data(normalOutputData.front());
@ -32,6 +35,7 @@ namespace skyline::service::am {
}
std::shared_ptr<IStorage> IApplet::PopInteractiveAndClear() {
std::scoped_lock lock{interactiveOutputDataMutex};
if (interactiveOutputData.empty())
return {};
std::shared_ptr<IStorage> data(interactiveOutputData.front());

View File

@ -17,11 +17,13 @@ namespace skyline::service::am {
private:
std::shared_ptr<kernel::type::KEvent> onNormalDataPushFromApplet;
std::shared_ptr<kernel::type::KEvent> onInteractiveDataPushFromApplet;
std::mutex outputDataMutex;
std::queue<std::shared_ptr<IStorage>> normalOutputData; //!< Stores data sent by the applet so the guest can read it when it needs to
std::mutex interactiveOutputDataMutex;
std::queue<std::shared_ptr<IStorage>> interactiveOutputData; //!< Stores interactive data sent by the applet so the guest can read it when it needs to
protected:
std::shared_ptr<kernel::type::KEvent> onAppletStateChanged;
std::queue<std::shared_ptr<IStorage>> normalOutputData; //!< Stores data sent by the applet so the guest can read it when it needs to
std::queue<std::shared_ptr<IStorage>> interactiveOutputData; //!< Stores interactive data sent by the applet so the guest can read it when it needs to
/**
* @brief Utility to send data to the guest and trigger the onNormalDataPushFromApplet event