service/am: Implement EnterFatalSection and LeaveFatalSection

These functions act in tandem similar to how a lock or mutex require a
balanced lock()/unlock() sequence.

EnterFatalSection simply increments a counter for how many times it has
been called, while LeaveFatalSection ensures that a previous call to
EnterFatalSection has occured. If a previous call has occurred (the
counter is not zero), then the counter gets decremented as one would
expect. If a previous call has not occurred (the counter is zero), then
an error code is returned.
This commit is contained in:
Lioncash 2019-03-26 15:12:09 -04:00
parent 96d518a59f
commit 758d84db9a
2 changed files with 29 additions and 2 deletions

View file

@ -239,8 +239,8 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
{0, nullptr, "Exit"}, {0, nullptr, "Exit"},
{1, &ISelfController::LockExit, "LockExit"}, {1, &ISelfController::LockExit, "LockExit"},
{2, &ISelfController::UnlockExit, "UnlockExit"}, {2, &ISelfController::UnlockExit, "UnlockExit"},
{3, nullptr, "EnterFatalSection"}, {3, &ISelfController::EnterFatalSection, "EnterFatalSection"},
{4, nullptr, "LeaveFatalSection"}, {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"},
{9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"},
{10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"},
{11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"},
@ -299,6 +299,30 @@ void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
} }
void ISelfController::EnterFatalSection(Kernel::HLERequestContext& ctx) {
++num_fatal_sections_entered;
LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called.");
// Entry and exit of fatal sections must be balanced.
if (num_fatal_sections_entered == 0) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultCode{ErrorModule::AM, 512});
return;
}
--num_fatal_sections_entered;
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called"); LOG_WARNING(Service_AM, "(STUBBED) called");

View file

@ -119,6 +119,8 @@ public:
private: private:
void LockExit(Kernel::HLERequestContext& ctx); void LockExit(Kernel::HLERequestContext& ctx);
void UnlockExit(Kernel::HLERequestContext& ctx); void UnlockExit(Kernel::HLERequestContext& ctx);
void EnterFatalSection(Kernel::HLERequestContext& ctx);
void LeaveFatalSection(Kernel::HLERequestContext& ctx);
void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx); void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx);
void SetScreenShotPermission(Kernel::HLERequestContext& ctx); void SetScreenShotPermission(Kernel::HLERequestContext& ctx);
void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx); void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx);
@ -135,6 +137,7 @@ private:
std::shared_ptr<NVFlinger::NVFlinger> nvflinger; std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
Kernel::EventPair launchable_event; Kernel::EventPair launchable_event;
u32 idle_time_detection_extension = 0; u32 idle_time_detection_extension = 0;
u64 num_fatal_sections_entered = 0;
}; };
class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {