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

View File

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

View File

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

View File

@ -17,11 +17,13 @@ namespace skyline::service::am {
private: private:
std::shared_ptr<kernel::type::KEvent> onNormalDataPushFromApplet; std::shared_ptr<kernel::type::KEvent> onNormalDataPushFromApplet;
std::shared_ptr<kernel::type::KEvent> onInteractiveDataPushFromApplet; 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: protected:
std::shared_ptr<kernel::type::KEvent> onAppletStateChanged; 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 * @brief Utility to send data to the guest and trigger the onNormalDataPushFromApplet event