mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-10 07:06:34 +00:00
Stratosphere: Fix remaining bugs in sm, which now works as a KIP1 on hardware
This commit is contained in:
parent
52730d2188
commit
30f975a558
6 changed files with 30 additions and 45 deletions
|
@ -40,14 +40,8 @@ void WaitableManager::process() {
|
||||||
handles.resize(signalables.size());
|
handles.resize(signalables.size());
|
||||||
std::transform(signalables.begin(), signalables.end(), handles.begin(), [](IWaitable *w) { return w->get_handle(); });
|
std::transform(signalables.begin(), signalables.end(), handles.begin(), [](IWaitable *w) { return w->get_handle(); });
|
||||||
|
|
||||||
unsigned int num_not_deferred = 0;
|
|
||||||
for (auto & signalable : signalables) {
|
|
||||||
if (!signalable->get_deferred()) {
|
|
||||||
num_not_deferred++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = svcWaitSynchronization(&handle_index, handles.data(), num_not_deferred, this->timeout);
|
rc = svcWaitSynchronization(&handle_index, handles.data(), signalables.size(), this->timeout);
|
||||||
if (R_SUCCEEDED(rc)) {
|
if (R_SUCCEEDED(rc)) {
|
||||||
/* Handle a signaled waitable. */
|
/* Handle a signaled waitable. */
|
||||||
/* TODO: What timeout should be passed here? */
|
/* TODO: What timeout should be passed here? */
|
||||||
|
@ -82,12 +76,19 @@ void WaitableManager::process() {
|
||||||
delete signalables[handle_index];
|
delete signalables[handle_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If relevant, remove from signalables. */
|
||||||
|
signalables.erase(std::remove(signalables.begin(), signalables.end(), signalables[handle_index]), signalables.end());
|
||||||
|
|
||||||
for (int i = 0; i < handle_index; i++) {
|
for (int i = 0; i < handle_index; i++) {
|
||||||
signalables[i]->update_priority();
|
signalables[i]->update_priority();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do deferred callback for each waitable. */
|
/* Do deferred callback for each waitable. */
|
||||||
std::for_each(signalables.begin() + num_not_deferred, signalables.end(), [](IWaitable *w) { w->handle_deferred(); });
|
for (auto & waitable : signalables) {
|
||||||
|
if (waitable->get_deferred()) {
|
||||||
|
waitable->handle_deferred();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
Result ManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
|
Result ManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
|
||||||
Result rc = 0xF601;
|
Result rc = 0xF601;
|
||||||
|
|
||||||
switch ((ManagerServiceCmd)cmd_id) {
|
switch ((ManagerServiceCmd)cmd_id) {
|
||||||
case Manager_Cmd_RegisterProcess:
|
case Manager_Cmd_RegisterProcess:
|
||||||
rc = WrapIpcCommandImpl<&ManagerService::register_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
rc = WrapIpcCommandImpl<&ManagerService::register_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||||
|
|
|
@ -6,6 +6,15 @@
|
||||||
static Registration::Process g_process_list[REGISTRATION_LIST_MAX_PROCESS] = {0};
|
static Registration::Process g_process_list[REGISTRATION_LIST_MAX_PROCESS] = {0};
|
||||||
static Registration::Service g_service_list[REGISTRATION_LIST_MAX_SERVICE] = {0};
|
static Registration::Service g_service_list[REGISTRATION_LIST_MAX_SERVICE] = {0};
|
||||||
|
|
||||||
|
u64 GetServiceNameLength(u64 service) {
|
||||||
|
u64 service_name_len = 0;
|
||||||
|
while (service & 0xFF) {
|
||||||
|
service_name_len++;
|
||||||
|
service >>= 8;
|
||||||
|
}
|
||||||
|
return service_name_len;
|
||||||
|
}
|
||||||
|
|
||||||
/* Utilities. */
|
/* Utilities. */
|
||||||
Registration::Process *Registration::GetProcessForPid(u64 pid) {
|
Registration::Process *Registration::GetProcessForPid(u64 pid) {
|
||||||
for (unsigned int i = 0; i < REGISTRATION_LIST_MAX_PROCESS; i++) {
|
for (unsigned int i = 0; i < REGISTRATION_LIST_MAX_PROCESS; i++) {
|
||||||
|
@ -162,13 +171,10 @@ Result Registration::GetServiceForPid(u64 pid, u64 service, Handle *out) {
|
||||||
return 0xC15;
|
return 0xC15;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 service_name_len = 0;
|
u64 service_name_len = GetServiceNameLength(service);
|
||||||
while ((service >> (8 * service_name_len)) & 0xFF) {
|
|
||||||
service_name_len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the service has bytes after a null terminator, that's no good. */
|
/* If the service has bytes after a null terminator, that's no good. */
|
||||||
if ((service >> (8 * service_name_len))) {
|
if (service_name_len != 8 && (service >> (8 * service_name_len))) {
|
||||||
return 0xC15;
|
return 0xC15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,13 +197,10 @@ Result Registration::RegisterServiceForPid(u64 pid, u64 service, u64 max_session
|
||||||
return 0xC15;
|
return 0xC15;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 service_name_len = 0;
|
u64 service_name_len = GetServiceNameLength(service);
|
||||||
while ((service >> (8 * service_name_len)) & 0xFF) {
|
|
||||||
service_name_len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the service has bytes after a null terminator, that's no good. */
|
/* If the service has bytes after a null terminator, that's no good. */
|
||||||
if ((service >> (8 * service_name_len))) {
|
if (service_name_len != 8 && (service >> (8 * service_name_len))) {
|
||||||
return 0xC15;
|
return 0xC15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,13 +243,10 @@ Result Registration::RegisterServiceForSelf(u64 service, u64 max_sessions, bool
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 service_name_len = 0;
|
u64 service_name_len = GetServiceNameLength(service);
|
||||||
while ((service >> (8 * service_name_len)) & 0xFF) {
|
|
||||||
service_name_len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the service has bytes after a null terminator, that's no good. */
|
/* If the service has bytes after a null terminator, that's no good. */
|
||||||
if ((service >> (8 * service_name_len))) {
|
if (service_name_len != 8 && (service >> (8 * service_name_len))) {
|
||||||
return 0xC15;
|
return 0xC15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,27 +276,13 @@ Result Registration::UnregisterServiceForPid(u64 pid, u64 service) {
|
||||||
return 0xC15;
|
return 0xC15;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 service_name_len = 0;
|
u64 service_name_len = GetServiceNameLength(service);
|
||||||
while ((service >> (8 * service_name_len)) & 0xFF) {
|
|
||||||
service_name_len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the service has bytes after a null terminator, that's no good. */
|
/* If the service has bytes after a null terminator, that's no good. */
|
||||||
if ((service >> (8 * service_name_len))) {
|
if (service_name_len != 8 && (service >> (8 * service_name_len))) {
|
||||||
return 0xC15;
|
return 0xC15;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid >= REGISTRATION_PID_BUILTIN_MAX) {
|
|
||||||
Registration::Process *proc = GetProcessForPid(pid);
|
|
||||||
if (proc == NULL) {
|
|
||||||
return 0x415;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsValidForSac(proc->sac, proc->sac_size, service, true)) {
|
|
||||||
return 0x1015;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Registration::Service *target_service = GetService(service);
|
Registration::Service *target_service = GetService(service);
|
||||||
if (target_service == NULL) {
|
if (target_service == NULL) {
|
||||||
return 0xE15;
|
return 0xE15;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#define REGISTRATION_LIST_MAX_PROCESS (0x40)
|
#define REGISTRATION_LIST_MAX_PROCESS (0x40)
|
||||||
#define REGISTRATION_LIST_MAX_SERVICE (0x100)
|
#define REGISTRATION_LIST_MAX_SERVICE (0x100)
|
||||||
#define REGISTRATION_MAX_SAC_SIZE (0x200)
|
#define REGISTRATION_MAX_SAC_SIZE (0x200)
|
||||||
#define REGISTRATION_PID_BUILTIN_MAX 0x7
|
#define REGISTRATION_PID_BUILTIN_MAX 0x50
|
||||||
|
|
||||||
class Registration {
|
class Registration {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
|
Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
|
||||||
Result rc = 0xF601;
|
Result rc = 0xF601;
|
||||||
|
|
||||||
switch ((UserServiceCmd)cmd_id) {
|
switch ((UserServiceCmd)cmd_id) {
|
||||||
case User_Cmd_Initialize:
|
case User_Cmd_Initialize:
|
||||||
rc = WrapIpcCommandImpl<&UserService::initialize>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
rc = WrapIpcCommandImpl<&UserService::initialize>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||||
|
@ -27,7 +26,7 @@ Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id,
|
||||||
|
|
||||||
Result UserService::handle_deferred() {
|
Result UserService::handle_deferred() {
|
||||||
/* If we're deferred, GetService failed. */
|
/* If we're deferred, GetService failed. */
|
||||||
return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service);
|
return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service);;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue