core: hle: kernel: Update KSynchronizationObject.

This commit is contained in:
bunnei 2020-12-21 22:36:53 -08:00
commit 2feb4d56e9
33 changed files with 397 additions and 621 deletions

View file

@ -164,6 +164,8 @@ add_library(core STATIC
hle/kernel/k_scheduler_lock.h
hle/kernel/k_scoped_lock.h
hle/kernel/k_scoped_scheduler_lock_and_sleep.h
hle/kernel/k_synchronization_object.cpp
hle/kernel/k_synchronization_object.h
hle/kernel/kernel.cpp
hle/kernel/kernel.h
hle/kernel/memory/address_space_info.cpp
@ -213,10 +215,6 @@ add_library(core STATIC
hle/kernel/svc_results.h
hle/kernel/svc_types.h
hle/kernel/svc_wrap.h
hle/kernel/synchronization_object.cpp
hle/kernel/synchronization_object.h
hle/kernel/synchronization.cpp
hle/kernel/synchronization.h
hle/kernel/thread.cpp
hle/kernel/thread.h
hle/kernel/time_manager.cpp

View file

@ -37,7 +37,7 @@ void AddressArbiter::WakeThreads(const std::vector<std::shared_ptr<Thread>>& wai
waiting_threads[i]->SetSynchronizationResults(nullptr, RESULT_SUCCESS);
RemoveThread(waiting_threads[i]);
waiting_threads[i]->WaitForArbitration(false);
waiting_threads[i]->ResumeFromWait();
waiting_threads[i]->Wakeup();
}
}
@ -160,7 +160,7 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6
{
KScopedSchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout);
if (current_thread->IsPendingTermination()) {
if (current_thread->IsTerminationRequested()) {
lock.CancelSleep();
return ERR_THREAD_TERMINATING;
}
@ -201,7 +201,7 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6
current_thread->SetArbiterWaitAddress(address);
InsertThread(SharedFrom(current_thread));
current_thread->SetStatus(ThreadStatus::WaitArb);
current_thread->SetState(ThreadStatus::WaitArb);
current_thread->WaitForArbitration(true);
}
@ -230,7 +230,7 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t
{
KScopedSchedulerLockAndSleep lock(kernel, event_handle, current_thread, timeout);
if (current_thread->IsPendingTermination()) {
if (current_thread->IsTerminationRequested()) {
lock.CancelSleep();
return ERR_THREAD_TERMINATING;
}
@ -256,7 +256,7 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t
current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
current_thread->SetArbiterWaitAddress(address);
InsertThread(SharedFrom(current_thread));
current_thread->SetStatus(ThreadStatus::WaitArb);
current_thread->SetState(ThreadStatus::WaitArb);
current_thread->WaitForArbitration(true);
}

View file

@ -33,9 +33,6 @@ ResultVal<std::shared_ptr<ClientSession>> ClientPort::Connect() {
server_port->AppendPendingSession(std::move(server));
}
// Wake the threads waiting on the ServerPort
server_port->Signal();
return MakeResult(std::move(client));
}

View file

@ -12,7 +12,7 @@
namespace Kernel {
ClientSession::ClientSession(KernelCore& kernel) : SynchronizationObject{kernel} {}
ClientSession::ClientSession(KernelCore& kernel) : KSynchronizationObject{kernel} {}
ClientSession::~ClientSession() {
// This destructor will be called automatically when the last ClientSession handle is closed by
@ -22,15 +22,6 @@ ClientSession::~ClientSession() {
}
}
bool ClientSession::ShouldWait(const Thread* thread) const {
UNIMPLEMENTED();
return {};
}
void ClientSession::Acquire(Thread* thread) {
UNIMPLEMENTED();
}
bool ClientSession::IsSignaled() const {
UNIMPLEMENTED();
return true;

View file

@ -7,7 +7,7 @@
#include <memory>
#include <string>
#include "core/hle/kernel/synchronization_object.h"
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/result.h"
union ResultCode;
@ -26,7 +26,7 @@ class KernelCore;
class Session;
class Thread;
class ClientSession final : public SynchronizationObject {
class ClientSession final : public KSynchronizationObject {
public:
explicit ClientSession(KernelCore& kernel);
~ClientSession() override;
@ -49,10 +49,6 @@ public:
ResultCode SendSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory,
Core::Timing::CoreTiming& core_timing);
bool ShouldWait(const Thread* thread) const override;
void Acquire(Thread* thread) override;
bool IsSignaled() const override;
private:

View file

@ -13,12 +13,14 @@ namespace Kernel {
constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED{ErrorModule::Kernel, 7};
constexpr ResultCode ERR_INVALID_CAPABILITY_DESCRIPTOR{ErrorModule::Kernel, 14};
constexpr ResultCode ERR_THREAD_TERMINATING{ErrorModule::Kernel, 59};
constexpr ResultCode ERR_TERMINATION_REQUESTED{ErrorModule::Kernel, 59};
constexpr ResultCode ERR_INVALID_SIZE{ErrorModule::Kernel, 101};
constexpr ResultCode ERR_INVALID_ADDRESS{ErrorModule::Kernel, 102};
constexpr ResultCode ERR_OUT_OF_RESOURCES{ErrorModule::Kernel, 103};
constexpr ResultCode ERR_OUT_OF_MEMORY{ErrorModule::Kernel, 104};
constexpr ResultCode ERR_HANDLE_TABLE_FULL{ErrorModule::Kernel, 105};
constexpr ResultCode ERR_INVALID_ADDRESS_STATE{ErrorModule::Kernel, 106};
constexpr ResultCode ERR_INVALID_CURRENT_MEMORY{ErrorModule::Kernel, 106};
constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS{ErrorModule::Kernel, 108};
constexpr ResultCode ERR_INVALID_MEMORY_RANGE{ErrorModule::Kernel, 110};
constexpr ResultCode ERR_INVALID_PROCESSOR_ID{ErrorModule::Kernel, 113};
@ -28,6 +30,7 @@ constexpr ResultCode ERR_INVALID_POINTER{ErrorModule::Kernel, 115};
constexpr ResultCode ERR_INVALID_COMBINATION{ErrorModule::Kernel, 116};
constexpr ResultCode RESULT_TIMEOUT{ErrorModule::Kernel, 117};
constexpr ResultCode ERR_SYNCHRONIZATION_CANCELED{ErrorModule::Kernel, 118};
constexpr ResultCode ERR_CANCELLED{ErrorModule::Kernel, 118};
constexpr ResultCode ERR_OUT_OF_RANGE{ErrorModule::Kernel, 119};
constexpr ResultCode ERR_INVALID_ENUM_VALUE{ErrorModule::Kernel, 120};
constexpr ResultCode ERR_NOT_FOUND{ErrorModule::Kernel, 121};

View file

@ -645,8 +645,7 @@ void KScheduler::Unload(Thread* thread) {
void KScheduler::Reload(Thread* thread) {
if (thread) {
ASSERT_MSG(thread->GetSchedulingStatus() == ThreadSchedStatus::Runnable,
"Thread must be runnable.");
ASSERT_MSG(thread->GetState() == ThreadSchedStatus::Runnable, "Thread must be runnable.");
// Cancel any outstanding wakeup events for this thread
thread->SetIsRunning(true);
@ -772,7 +771,7 @@ void KScheduler::Initialize() {
{
KScopedSchedulerLock lock{system.Kernel()};
idle_thread->SetStatus(ThreadStatus::Ready);
idle_thread->SetState(ThreadStatus::Ready);
}
}

View file

@ -0,0 +1,171 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/assert.h"
#include "common/common_types.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/thread.h"
namespace Kernel {
ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
KSynchronizationObject** objects, const s32 num_objects,
s64 timeout) {
// Allocate space on stack for thread nodes.
std::vector<ThreadListNode> thread_nodes(num_objects);
// Prepare for wait.
Thread* thread = kernel.CurrentScheduler()->GetCurrentThread();
Handle timer = InvalidHandle;
{
// Setup the scheduling lock and sleep.
KScopedSchedulerLockAndSleep slp(kernel, timer, thread, timeout);
// Check if any of the objects are already signaled.
for (auto i = 0; i < num_objects; ++i) {
ASSERT(objects[i] != nullptr);
if (objects[i]->IsSignaled()) {
*out_index = i;
slp.CancelSleep();
return RESULT_SUCCESS;
}
}
// Check if the timeout is zero.
if (timeout == 0) {
slp.CancelSleep();
return Svc::ResultTimedOut;
}
// Check if the thread should terminate.
if (thread->IsTerminationRequested()) {
slp.CancelSleep();
return Svc::ResultTerminationRequested;
}
// Check if waiting was canceled.
if (thread->IsWaitCancelled()) {
slp.CancelSleep();
thread->ClearWaitCancelled();
return Svc::ResultCancelled;
}
// Add the waiters.
for (auto i = 0; i < num_objects; ++i) {
thread_nodes[i].thread = thread;
thread_nodes[i].next = nullptr;
if (objects[i]->thread_list_tail == nullptr) {
objects[i]->thread_list_head = std::addressof(thread_nodes[i]);
} else {
objects[i]->thread_list_tail->next = std::addressof(thread_nodes[i]);
}
objects[i]->thread_list_tail = std::addressof(thread_nodes[i]);
}
// For debugging only
thread->SetWaitObjectsForDebugging(objects, num_objects);
// Mark the thread as waiting.
thread->SetCancellable();
thread->SetSyncedObject(nullptr, Svc::ResultTimedOut);
thread->SetState(ThreadState::WaitSynch);
}
// The lock/sleep is done, so we should be able to get our result.
// Thread is no longer cancellable.
thread->ClearCancellable();
// For debugging only
thread->SetWaitObjectsForDebugging(nullptr, 0);
// Cancel the timer as needed.
if (timer != InvalidHandle) {
auto& time_manager = kernel.TimeManager();
time_manager.UnscheduleTimeEvent(timer);
}
// Get the wait result.
ResultCode wait_result{RESULT_SUCCESS};
s32 sync_index = -1;
{
KScopedSchedulerLock lock(kernel);
KSynchronizationObject* synced_obj;
wait_result = thread->GetWaitResult(std::addressof(synced_obj));
for (auto i = 0; i < num_objects; ++i) {
// Unlink the object from the list.
ThreadListNode* prev_ptr =
reinterpret_cast<ThreadListNode*>(std::addressof(objects[i]->thread_list_head));
ThreadListNode* prev_val = nullptr;
ThreadListNode *prev, *tail_prev;
do {
prev = prev_ptr;
prev_ptr = prev_ptr->next;
tail_prev = prev_val;
prev_val = prev_ptr;
} while (prev_ptr != std::addressof(thread_nodes[i]));
if (objects[i]->thread_list_tail == std::addressof(thread_nodes[i])) {
objects[i]->thread_list_tail = tail_prev;
}
prev->next = thread_nodes[i].next;
if (objects[i] == synced_obj) {
sync_index = i;
}
}
}
// Set output.
*out_index = sync_index;
return wait_result;
}
KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : Object{kernel} {}
KSynchronizationObject ::~KSynchronizationObject() = default;
void KSynchronizationObject::NotifyAvailable(ResultCode result) {
KScopedSchedulerLock lock(kernel);
// If we're not signaled, we've nothing to notify.
if (!this->IsSignaled()) {
return;
}
// Iterate over each thread.
for (auto* cur_node = thread_list_head; cur_node != nullptr; cur_node = cur_node->next) {
Thread* thread = cur_node->thread;
if (thread->GetState() == ThreadSchedStatus::Paused) {
thread->SetSyncedObject(this, result);
thread->SetState(ThreadStatus::Ready);
}
}
}
std::vector<Thread*> KSynchronizationObject::GetWaitingThreadsForDebugging() const {
std::vector<Thread*> threads;
// If debugging, dump the list of waiters.
{
KScopedSchedulerLock lock(kernel);
for (auto* cur_node = thread_list_head; cur_node != nullptr; cur_node = cur_node->next) {
threads.emplace_back(cur_node->thread);
}
}
return threads;
}
} // namespace Kernel

View file

@ -0,0 +1,58 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <vector>
#include "core/hle/kernel/object.h"
#include "core/hle/result.h"
namespace Kernel {
class KernelCore;
class Synchronization;
class Thread;
/// Class that represents a Kernel object that a thread can be waiting on
class KSynchronizationObject : public Object {
public:
struct ThreadListNode {
ThreadListNode* next{};
Thread* thread{};
};
[[nodiscard]] static ResultCode Wait(KernelCore& kernel, s32* out_index,
KSynchronizationObject** objects, const s32 num_objects,
s64 timeout);
[[nodiscard]] virtual bool IsSignaled() const = 0;
[[nodiscard]] std::vector<Thread*> GetWaitingThreadsForDebugging() const;
protected:
explicit KSynchronizationObject(KernelCore& kernel);
virtual ~KSynchronizationObject();
void NotifyAvailable(ResultCode result);
void NotifyAvailable() {
return this->NotifyAvailable(RESULT_SUCCESS);
}
private:
ThreadListNode* thread_list_head{};
ThreadListNode* thread_list_tail{};
};
// Specialization of DynamicObjectCast for KSynchronizationObjects
template <>
inline std::shared_ptr<KSynchronizationObject> DynamicObjectCast<KSynchronizationObject>(
std::shared_ptr<Object> object) {
if (object != nullptr && object->IsWaitable()) {
return std::static_pointer_cast<KSynchronizationObject>(object);
}
return nullptr;
}
} // namespace Kernel

View file

@ -38,7 +38,6 @@
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/service_thread.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/kernel/synchronization.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/time_manager.h"
#include "core/hle/lock.h"
@ -51,8 +50,7 @@ namespace Kernel {
struct KernelCore::Impl {
explicit Impl(Core::System& system, KernelCore& kernel)
: synchronization{system}, time_manager{system}, global_handle_table{kernel}, system{
system} {}
: time_manager{system}, global_handle_table{kernel}, system{system} {}
void SetMulticore(bool is_multicore) {
this->is_multicore = is_multicore;
@ -307,7 +305,6 @@ struct KernelCore::Impl {
std::vector<std::shared_ptr<Process>> process_list;
Process* current_process = nullptr;
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
Kernel::Synchronization synchronization;
Kernel::TimeManager time_manager;
std::shared_ptr<ResourceLimit> system_resource_limit;
@ -461,14 +458,6 @@ const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Kern
return impl->interrupts;
}
Kernel::Synchronization& KernelCore::Synchronization() {
return impl->synchronization;
}
const Kernel::Synchronization& KernelCore::Synchronization() const {
return impl->synchronization;
}
Kernel::TimeManager& KernelCore::TimeManager() {
return impl->time_manager;
}
@ -615,7 +604,7 @@ void KernelCore::Suspend(bool in_suspention) {
KScopedSchedulerLock lock(*this);
ThreadStatus status = should_suspend ? ThreadStatus::Ready : ThreadStatus::WaitSleep;
for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
impl->suspend_threads[i]->SetStatus(status);
impl->suspend_threads[i]->SetState(status);
}
}
}

View file

@ -129,12 +129,6 @@ public:
/// Gets the an instance of the current physical CPU core.
const Kernel::PhysicalCore& CurrentPhysicalCore() const;
/// Gets the an instance of the Synchronization Interface.
Kernel::Synchronization& Synchronization();
/// Gets the an instance of the Synchronization Interface.
const Kernel::Synchronization& Synchronization() const;
/// Gets the an instance of the TimeManager Interface.
Kernel::TimeManager& TimeManager();

View file

@ -107,7 +107,7 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle,
current_thread->SetMutexWaitAddress(address);
current_thread->SetWaitHandle(requesting_thread_handle);
current_thread->SetStatus(ThreadStatus::WaitMutex);
current_thread->SetState(ThreadStatus::WaitMutex);
// Update the lock holder thread's priority to prevent priority inversion.
holding_thread->AddMutexWaiter(current_thread);
@ -145,7 +145,7 @@ std::pair<ResultCode, std::shared_ptr<Thread>> Mutex::Unlock(std::shared_ptr<Thr
}
new_owner->SetSynchronizationResults(nullptr, RESULT_SUCCESS);
new_owner->SetLockOwner(nullptr);
new_owner->ResumeFromWait();
new_owner->Wakeup();
system.Memory().Write32(address, mutex_value);
return {RESULT_SUCCESS, new_owner};

View file

@ -55,7 +55,7 @@ void SetupMainThread(Core::System& system, Process& owner_process, u32 priority,
// Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
{
KScopedSchedulerLock lock{kernel};
thread->SetStatus(ThreadStatus::Ready);
thread->SetState(ThreadStatus::Ready);
}
}
} // Anonymous namespace
@ -406,21 +406,18 @@ void Process::LoadModule(CodeSet code_set, VAddr base_addr) {
ReprotectSegment(code_set.DataSegment(), Memory::MemoryPermission::ReadAndWrite);
}
bool Process::IsSignaled() const {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
return is_signaled;
}
Process::Process(Core::System& system)
: SynchronizationObject{system.Kernel()}, page_table{std::make_unique<Memory::PageTable>(
system)},
: KSynchronizationObject{system.Kernel()}, page_table{std::make_unique<Memory::PageTable>(
system)},
handle_table{system.Kernel()}, address_arbiter{system}, mutex{system}, system{system} {}
Process::~Process() = default;
void Process::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "Object unavailable!");
}
bool Process::ShouldWait(const Thread* thread) const {
return !is_signaled;
}
void Process::ChangeStatus(ProcessStatus new_status) {
if (status == new_status) {
return;
@ -428,7 +425,7 @@ void Process::ChangeStatus(ProcessStatus new_status) {
status = new_status;
is_signaled = true;
Signal();
NotifyAvailable();
}
ResultCode Process::AllocateMainThreadStack(std::size_t stack_size) {

View file

@ -13,9 +13,9 @@
#include "common/common_types.h"
#include "core/hle/kernel/address_arbiter.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/process_capability.h"
#include "core/hle/kernel/synchronization_object.h"
#include "core/hle/result.h"
namespace Core {
@ -63,7 +63,7 @@ enum class ProcessStatus {
DebugBreak,
};
class Process final : public SynchronizationObject {
class Process final : public KSynchronizationObject {
public:
explicit Process(Core::System& system);
~Process() override;
@ -304,6 +304,8 @@ public:
void LoadModule(CodeSet code_set, VAddr base_addr);
bool IsSignaled() const override;
///////////////////////////////////////////////////////////////////////////////////////////////
// Thread-local storage management
@ -314,12 +316,6 @@ public:
void FreeTLSRegion(VAddr tls_address);
private:
/// Checks if the specified thread should wait until this process is available.
bool ShouldWait(const Thread* thread) const override;
/// Acquires/locks this process for the specified thread if it's available.
void Acquire(Thread* thread) override;
/// Changes the process status. If the status is different
/// from the current process status, then this will trigger
/// a process signal.
@ -410,6 +406,8 @@ private:
/// Schedule count of this process
s64 schedule_count{};
bool is_signaled{};
/// System context
Core::System& system;
};

View file

@ -14,24 +14,22 @@
namespace Kernel {
ReadableEvent::ReadableEvent(KernelCore& kernel) : SynchronizationObject{kernel} {}
ReadableEvent::ReadableEvent(KernelCore& kernel) : KSynchronizationObject{kernel} {}
ReadableEvent::~ReadableEvent() = default;
bool ReadableEvent::ShouldWait(const Thread* thread) const {
return !is_signaled;
}
void ReadableEvent::Acquire(Thread* thread) {
ASSERT_MSG(IsSignaled(), "object unavailable!");
}
void ReadableEvent::Signal() {
if (is_signaled) {
return;
}
is_signaled = true;
SynchronizationObject::Signal();
NotifyAvailable();
}
bool ReadableEvent::IsSignaled() const {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
return is_signaled;
}
void ReadableEvent::Clear() {

View file

@ -4,8 +4,8 @@
#pragma once
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/synchronization_object.h"
union ResultCode;
@ -14,7 +14,7 @@ namespace Kernel {
class KernelCore;
class WritableEvent;
class ReadableEvent final : public SynchronizationObject {
class ReadableEvent final : public KSynchronizationObject {
friend class WritableEvent;
public:
@ -32,9 +32,6 @@ public:
return HANDLE_TYPE;
}
bool ShouldWait(const Thread* thread) const override;
void Acquire(Thread* thread) override;
/// Unconditionally clears the readable event's state.
void Clear();
@ -46,11 +43,14 @@ public:
/// then ERR_INVALID_STATE will be returned.
ResultCode Reset();
void Signal() override;
void Signal();
bool IsSignaled() const override;
private:
explicit ReadableEvent(KernelCore& kernel);
bool is_signaled{};
std::string name; ///< Name of event (optional)
};

View file

@ -13,7 +13,7 @@
namespace Kernel {
ServerPort::ServerPort(KernelCore& kernel) : SynchronizationObject{kernel} {}
ServerPort::ServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {}
ServerPort::~ServerPort() = default;
ResultVal<std::shared_ptr<ServerSession>> ServerPort::Accept() {
@ -28,15 +28,9 @@ ResultVal<std::shared_ptr<ServerSession>> ServerPort::Accept() {
void ServerPort::AppendPendingSession(std::shared_ptr<ServerSession> pending_session) {
pending_sessions.push_back(std::move(pending_session));
}
bool ServerPort::ShouldWait(const Thread* thread) const {
// If there are no pending sessions, we wait until a new one is added.
return pending_sessions.empty();
}
void ServerPort::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
if (pending_sessions.size() == 1) {
NotifyAvailable();
}
}
bool ServerPort::IsSignaled() const {

View file

@ -9,8 +9,8 @@
#include <utility>
#include <vector>
#include "common/common_types.h"
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/synchronization_object.h"
#include "core/hle/result.h"
namespace Kernel {
@ -20,7 +20,7 @@ class KernelCore;
class ServerSession;
class SessionRequestHandler;
class ServerPort final : public SynchronizationObject {
class ServerPort final : public KSynchronizationObject {
public:
explicit ServerPort(KernelCore& kernel);
~ServerPort() override;
@ -79,9 +79,6 @@ public:
/// waiting to be accepted by this port.
void AppendPendingSession(std::shared_ptr<ServerSession> pending_session);
bool ShouldWait(const Thread* thread) const override;
void Acquire(Thread* thread) override;
bool IsSignaled() const override;
private:

View file

@ -24,7 +24,7 @@
namespace Kernel {
ServerSession::ServerSession(KernelCore& kernel) : SynchronizationObject{kernel} {}
ServerSession::ServerSession(KernelCore& kernel) : KSynchronizationObject{kernel} {}
ServerSession::~ServerSession() {
kernel.ReleaseServiceThread(service_thread);
@ -42,16 +42,6 @@ ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kern
return MakeResult(std::move(session));
}
bool ServerSession::ShouldWait(const Thread* thread) const {
// Closed sessions should never wait, an error will be returned from svcReplyAndReceive.
if (!parent->Client()) {
return false;
}
// Wait if we have no pending requests, or if we're currently handling a request.
return pending_requesting_threads.empty() || currently_handling != nullptr;
}
bool ServerSession::IsSignaled() const {
// Closed sessions should never wait, an error will be returned from svcReplyAndReceive.
if (!parent->Client()) {
@ -62,15 +52,6 @@ bool ServerSession::IsSignaled() const {
return !pending_requesting_threads.empty() && currently_handling == nullptr;
}
void ServerSession::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
// We are now handling a request, pop it from the stack.
// TODO(Subv): What happens if the client endpoint is closed before any requests are made?
ASSERT(!pending_requesting_threads.empty());
currently_handling = pending_requesting_threads.back();
pending_requesting_threads.pop_back();
}
void ServerSession::ClientDisconnected() {
// We keep a shared pointer to the hle handler to keep it alive throughout
// the call to ClientDisconnected, as ClientDisconnected invalidates the
@ -172,7 +153,7 @@ ResultCode ServerSession::CompleteSyncRequest(HLERequestContext& context) {
{
KScopedSchedulerLock lock(kernel);
if (!context.IsThreadWaiting()) {
context.GetThread().ResumeFromWait();
context.GetThread().Wakeup();
context.GetThread().SetSynchronizationResults(nullptr, result);
}
}

View file

@ -10,8 +10,8 @@
#include <vector>
#include "common/threadsafe_queue.h"
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/service_thread.h"
#include "core/hle/kernel/synchronization_object.h"
#include "core/hle/result.h"
namespace Core::Memory {
@ -43,7 +43,7 @@ class Thread;
* After the server replies to the request, the response is marshalled back to the caller's
* TLS buffer and control is transferred back to it.
*/
class ServerSession final : public SynchronizationObject {
class ServerSession final : public KSynchronizationObject {
friend class ServiceThread;
public:
@ -77,8 +77,6 @@ public:
return parent.get();
}
bool IsSignaled() const override;
/**
* Sets the HLE handler for the session. This handler will be called to service IPC requests
* instead of the regular IPC machinery. (The regular IPC machinery is currently not
@ -100,10 +98,6 @@ public:
ResultCode HandleSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory,
Core::Timing::CoreTiming& core_timing);
bool ShouldWait(const Thread* thread) const override;
void Acquire(Thread* thread) override;
/// Called when a client disconnection occurs.
void ClientDisconnected();
@ -130,6 +124,8 @@ public:
convert_to_domain = true;
}
bool IsSignaled() const override;
private:
/// Queues a sync request from the emulated application.
ResultCode QueueSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory);

Some files were not shown because too many files have changed in this diff Show more