mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-18 17:14:28 -04:00
kern: implement KEvent, KWritableEvent, KServerSession::OnClientClosed
This commit is contained in:
parent
d0d8914f28
commit
16c9c53a4a
9 changed files with 449 additions and 4 deletions
|
@ -17,6 +17,23 @@
|
|||
|
||||
namespace ams::kern {
|
||||
|
||||
namespace {
|
||||
|
||||
ALWAYS_INLINE void ReplyAsyncError(KProcess *to_process, uintptr_t to_msg_buf, size_t to_msg_buf_size, Result result) {
|
||||
/* Convert the buffer to a physical address. */
|
||||
KPhysicalAddress phys_addr;
|
||||
to_process->GetPageTable().GetPhysicalAddress(std::addressof(phys_addr), KProcessAddress(to_msg_buf));
|
||||
|
||||
/* Convert the physical address to a linear pointer. */
|
||||
u32 *to_msg = GetPointer<u32>(KPageTable::GetHeapVirtualAddress(phys_addr));
|
||||
|
||||
/* Set the error. */
|
||||
ams::svc::ipc::MessageBuffer msg(to_msg, to_msg_buf_size);
|
||||
msg.SetAsyncResult(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void KServerSession::Destroy() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
|
@ -33,7 +50,95 @@ namespace ams::kern {
|
|||
|
||||
void KServerSession::OnClientClosed() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
|
||||
KScopedLightLock lk(this->lock);
|
||||
|
||||
/* Handle any pending requests. */
|
||||
KSessionRequest *prev_request = nullptr;
|
||||
while (true) {
|
||||
/* Declare variables for processing the request. */
|
||||
KSessionRequest *request = nullptr;
|
||||
KWritableEvent *event = nullptr;
|
||||
KThread *thread = nullptr;
|
||||
bool cur_request = false;
|
||||
bool terminate = false;
|
||||
|
||||
/* Get the next request. */
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
if (this->current_request != nullptr && this->current_request != prev_request) {
|
||||
/* Set the request, open a reference as we process it. */
|
||||
request = this->current_request;
|
||||
request->Open();
|
||||
cur_request = true;
|
||||
|
||||
/* Get thread and event for the request. */
|
||||
thread = request->GetThread();
|
||||
event = request->GetEvent();
|
||||
|
||||
/* If the thread is terminating, handle that. */
|
||||
if (thread->IsTerminationRequested()) {
|
||||
request->ClearThread();
|
||||
request->ClearEvent();
|
||||
terminate = true;
|
||||
}
|
||||
prev_request = request;
|
||||
} else if (!this->request_list.empty()) {
|
||||
/* Pop the request from the front of the list. */
|
||||
request = std::addressof(this->request_list.front());
|
||||
this->request_list.pop_front();
|
||||
|
||||
/* Get thread and event for the request. */
|
||||
thread = request->GetThread();
|
||||
event = request->GetEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/* If there are no requests, we're done. */
|
||||
if (request == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* All requests must have threads. */
|
||||
MESOSPHERE_ASSERT(thread != nullptr);
|
||||
|
||||
/* Ensure that we close the request when done. */
|
||||
ON_SCOPE_EXIT { request->Close(); };
|
||||
|
||||
/* If we're terminating, close a reference to the thread and event. */
|
||||
if (terminate) {
|
||||
thread->Close();
|
||||
if (event != nullptr) {
|
||||
event->Close();
|
||||
}
|
||||
}
|
||||
|
||||
/* If we need to, reply. */
|
||||
if (event != nullptr && !cur_request) {
|
||||
/* There must be no mappings. */
|
||||
MESOSPHERE_ASSERT(request->GetSendCount() == 0);
|
||||
MESOSPHERE_ASSERT(request->GetReceiveCount() == 0);
|
||||
MESOSPHERE_ASSERT(request->GetExchangeCount() == 0);
|
||||
|
||||
/* Get the process and page table. */
|
||||
KProcess *client_process = thread->GetOwner();
|
||||
auto &client_pt = client_process->GetPageTable();
|
||||
|
||||
/* Reply to the request. */
|
||||
ReplyAsyncError(client_process, request->GetAddress(), request->GetSize(), svc::ResultSessionClosed());
|
||||
|
||||
/* Unlock the buffer. */
|
||||
/* NOTE: Nintendo does not check the result of this. */
|
||||
client_pt.UnlockForIpcUserBuffer(request->GetAddress(), request->GetSize());
|
||||
|
||||
/* Signal the event. */
|
||||
event->Signal();
|
||||
}
|
||||
}
|
||||
|
||||
/* Notify. */
|
||||
this->NotifyAbort(svc::ResultSessionClosed());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue