mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-18 08:22:04 +00:00
kern: add SvcExitThread, SvcSendAsyncRequestWithUserBuffer, SvcReplyAndReceiveWithUserBuffer
This commit is contained in:
parent
1b429918de
commit
d52655eaf1
3 changed files with 114 additions and 8 deletions
|
@ -441,8 +441,8 @@ namespace ams::kern {
|
|||
|
||||
Result KPageTableBase::LockMemoryAndOpen(KPageGroup *out_pg, KPhysicalAddress *out_paddr, KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr, KMemoryPermission new_perm, u32 lock_attr) {
|
||||
/* Validate basic preconditions. */
|
||||
MESOSPHERE_ASSERT((attr_mask & lock_attr) == lock_attr);
|
||||
MESOSPHERE_ASSERT((attr & lock_attr) == lock_attr);
|
||||
MESOSPHERE_ASSERT((lock_attr & attr) == 0);
|
||||
MESOSPHERE_ASSERT((lock_attr & (KMemoryAttribute_IpcLocked | KMemoryAttribute_DeviceShared)) == 0);
|
||||
|
||||
/* Validate the lock request. */
|
||||
const size_t num_pages = size / PageSize;
|
||||
|
|
|
@ -153,10 +153,111 @@ namespace ams::kern::svc {
|
|||
return page_table.UnlockForIpcUserBuffer(message, buffer_size);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result SendAsyncRequestWithUserBufferImpl(ams::svc::Handle *out_event_handle, uintptr_t message, size_t buffer_size, ams::svc::Handle session_handle) {
|
||||
/* Get the process and handle table. */
|
||||
auto &process = GetCurrentProcess();
|
||||
auto &handle_table = process.GetHandleTable();
|
||||
|
||||
/* Reserve a new event from the process resource limit. */
|
||||
KScopedResourceReservation event_reservation(std::addressof(process), ams::svc::LimitableResource_EventCountMax);
|
||||
R_UNLESS(event_reservation.Succeeded(), svc::ResultLimitReached());
|
||||
|
||||
/* Get the client session. */
|
||||
KScopedAutoObject session = GetCurrentProcess().GetHandleTable().GetObject<KClientSession>(session_handle);
|
||||
R_UNLESS(session.IsNotNull(), svc::ResultInvalidHandle());
|
||||
|
||||
/* Get the parent, and persist a reference to it until we're done. */
|
||||
KScopedAutoObject parent = session->GetParent();
|
||||
MESOSPHERE_ASSERT(parent.IsNotNull());
|
||||
|
||||
/* Create a new event. */
|
||||
KEvent *event = KEvent::Create();
|
||||
R_UNLESS(event != nullptr, svc::ResultOutOfResource());
|
||||
|
||||
/* Initialize the event. */
|
||||
event->Initialize();
|
||||
|
||||
/* Commit our reservation. */
|
||||
event_reservation.Commit();
|
||||
|
||||
/* At end of scope, kill the standing references to the sub events. */
|
||||
ON_SCOPE_EXIT {
|
||||
event->GetReadableEvent().Close();
|
||||
event->GetWritableEvent().Close();
|
||||
};
|
||||
|
||||
/* Register the event. */
|
||||
R_TRY(KEvent::Register(event));
|
||||
|
||||
/* Add the readable event to the handle table. */
|
||||
R_TRY(handle_table.Add(out_event_handle, std::addressof(event->GetReadableEvent())));
|
||||
|
||||
/* Ensure that if we fail to send the request, we close the readable handle. */
|
||||
auto read_guard = SCOPE_GUARD { handle_table.Remove(*out_event_handle); };
|
||||
|
||||
/* Send the async request. */
|
||||
R_TRY(session->SendAsyncRequest(std::addressof(event->GetWritableEvent()), message, buffer_size));
|
||||
|
||||
/* We succeeded. */
|
||||
read_guard.Cancel();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result SendAsyncRequestWithUserBuffer(ams::svc::Handle *out_event_handle, uintptr_t message, size_t buffer_size, ams::svc::Handle session_handle) {
|
||||
/* Validate that the message buffer is page aligned and does not overflow. */
|
||||
R_UNLESS(util::IsAligned(message, PageSize), svc::ResultInvalidAddress());
|
||||
R_UNLESS(buffer_size > 0, svc::ResultInvalidSize());
|
||||
R_UNLESS(util::IsAligned(buffer_size, PageSize), svc::ResultInvalidSize());
|
||||
R_UNLESS(message < message + buffer_size, svc::ResultInvalidCurrentMemory());
|
||||
|
||||
/* Get the process page table. */
|
||||
auto &page_table = GetCurrentProcess().GetPageTable();
|
||||
|
||||
/* Lock the mesage buffer. */
|
||||
R_TRY(page_table.LockForIpcUserBuffer(nullptr, message, buffer_size));
|
||||
|
||||
/* Ensure that if we fail, we unlock the message buffer. */
|
||||
auto unlock_guard = SCOPE_GUARD { page_table.UnlockForIpcUserBuffer(message, buffer_size); };
|
||||
|
||||
/* Send the request. */
|
||||
MESOSPHERE_ASSERT(message != 0);
|
||||
R_TRY(SendAsyncRequestWithUserBufferImpl(out_event_handle, message, buffer_size, session_handle));
|
||||
|
||||
/* We sent the request successfully. */
|
||||
unlock_guard.Cancel();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result ReplyAndReceive(int32_t *out_index, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) {
|
||||
return ReplyAndReceiveImpl(out_index, 0, 0, Null<KPhysicalAddress>, handles, num_handles, reply_target, timeout_ns);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result ReplyAndReceiveWithUserBuffer(int32_t *out_index, uintptr_t message, size_t buffer_size, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) {
|
||||
/* Validate that the message buffer is page aligned and does not overflow. */
|
||||
R_UNLESS(util::IsAligned(message, PageSize), svc::ResultInvalidAddress());
|
||||
R_UNLESS(buffer_size > 0, svc::ResultInvalidSize());
|
||||
R_UNLESS(util::IsAligned(buffer_size, PageSize), svc::ResultInvalidSize());
|
||||
R_UNLESS(message < message + buffer_size, svc::ResultInvalidCurrentMemory());
|
||||
|
||||
/* Get the process page table. */
|
||||
auto &page_table = GetCurrentProcess().GetPageTable();
|
||||
|
||||
/* Lock the mesage buffer, getting its physical address. */
|
||||
KPhysicalAddress message_paddr;
|
||||
R_TRY(page_table.LockForIpcUserBuffer(std::addressof(message_paddr), message, buffer_size));
|
||||
|
||||
/* Ensure that even if we fail, we unlock the message buffer when done. */
|
||||
auto unlock_guard = SCOPE_GUARD { page_table.UnlockForIpcUserBuffer(message, buffer_size); };
|
||||
|
||||
/* Send the request. */
|
||||
MESOSPHERE_ASSERT(message != 0);
|
||||
R_TRY(ReplyAndReceiveImpl(out_index, message, buffer_size, message_paddr, handles, num_handles, reply_target, timeout_ns));
|
||||
|
||||
/* We sent the request successfully, so cancel our guard and check the unlock result. */
|
||||
unlock_guard.Cancel();
|
||||
return page_table.UnlockForIpcUserBuffer(message, buffer_size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ============================= 64 ABI ============================= */
|
||||
|
@ -170,7 +271,7 @@ namespace ams::kern::svc {
|
|||
}
|
||||
|
||||
Result SendAsyncRequestWithUserBuffer64(ams::svc::Handle *out_event_handle, ams::svc::Address message_buffer, ams::svc::Size message_buffer_size, ams::svc::Handle session_handle) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcSendAsyncRequestWithUserBuffer64 was called.");
|
||||
return SendAsyncRequestWithUserBuffer(out_event_handle, message_buffer, message_buffer_size, session_handle);
|
||||
}
|
||||
|
||||
Result ReplyAndReceive64(int32_t *out_index, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) {
|
||||
|
@ -178,7 +279,7 @@ namespace ams::kern::svc {
|
|||
}
|
||||
|
||||
Result ReplyAndReceiveWithUserBuffer64(int32_t *out_index, ams::svc::Address message_buffer, ams::svc::Size message_buffer_size, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcReplyAndReceiveWithUserBuffer64 was called.");
|
||||
return ReplyAndReceiveWithUserBuffer(out_index, message_buffer, message_buffer_size, handles, num_handles, reply_target, timeout_ns);
|
||||
}
|
||||
|
||||
/* ============================= 64From32 ABI ============================= */
|
||||
|
@ -192,7 +293,7 @@ namespace ams::kern::svc {
|
|||
}
|
||||
|
||||
Result SendAsyncRequestWithUserBuffer64From32(ams::svc::Handle *out_event_handle, ams::svc::Address message_buffer, ams::svc::Size message_buffer_size, ams::svc::Handle session_handle) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcSendAsyncRequestWithUserBuffer64From32 was called.");
|
||||
return SendAsyncRequestWithUserBuffer(out_event_handle, message_buffer, message_buffer_size, session_handle);
|
||||
}
|
||||
|
||||
Result ReplyAndReceive64From32(int32_t *out_index, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) {
|
||||
|
@ -200,7 +301,7 @@ namespace ams::kern::svc {
|
|||
}
|
||||
|
||||
Result ReplyAndReceiveWithUserBuffer64From32(int32_t *out_index, ams::svc::Address message_buffer, ams::svc::Size message_buffer_size, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcReplyAndReceiveWithUserBuffer64From32 was called.");
|
||||
return ReplyAndReceiveWithUserBuffer(out_index, message_buffer, message_buffer_size, handles, num_handles, reply_target, timeout_ns);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -81,6 +81,11 @@ namespace ams::kern::svc {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void ExitThread() {
|
||||
GetCurrentThread().Exit();
|
||||
MESOSPHERE_PANIC("Process survived call to exit");
|
||||
}
|
||||
|
||||
Result GetThreadPriority(int32_t *out_priority, ams::svc::Handle thread_handle) {
|
||||
/* Get the thread from its handle. */
|
||||
KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject<KThread>(thread_handle);
|
||||
|
@ -114,7 +119,7 @@ namespace ams::kern::svc {
|
|||
}
|
||||
|
||||
void ExitThread64() {
|
||||
MESOSPHERE_PANIC("Stubbed SvcExitThread64 was called.");
|
||||
return ExitThread();
|
||||
}
|
||||
|
||||
void SleepThread64(int64_t ns) {
|
||||
|
@ -168,7 +173,7 @@ namespace ams::kern::svc {
|
|||
}
|
||||
|
||||
void ExitThread64From32() {
|
||||
MESOSPHERE_PANIC("Stubbed SvcExitThread64From32 was called.");
|
||||
return ExitThread();
|
||||
}
|
||||
|
||||
void SleepThread64From32(int64_t ns) {
|
||||
|
|
Loading…
Reference in a new issue