diff options
Diffstat (limited to '')
70 files changed, 367 insertions, 372 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ac173c486..0ab0e440c 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -26,6 +26,7 @@ set(SRCS hle/kernel/kernel.cpp hle/kernel/mutex.cpp hle/kernel/semaphore.cpp + hle/kernel/session.cpp hle/kernel/shared_memory.cpp hle/kernel/timer.cpp hle/kernel/thread.cpp diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 2d01e2ef5..42f8ce2d9 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -15,14 +15,15 @@ namespace Kernel { -ResultVal<SharedPtr<AddressArbiter>> AddressArbiter::Create(std::string name) { +AddressArbiter::AddressArbiter() {} +AddressArbiter::~AddressArbiter() {} + +SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) { SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter); - // TOOD(yuriks): Don't create Handle (see Thread::Create()) - CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(address_arbiter)); address_arbiter->name = std::move(name); - return MakeResult<SharedPtr<AddressArbiter>>(std::move(address_arbiter)); + return address_arbiter; } ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, @@ -51,7 +52,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, case ArbitrationType::WaitIfLessThanWithTimeout: if ((s32)Memory::Read32(address) <= value) { Kernel::WaitCurrentThread_ArbitrateAddress(address); - Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds); + GetCurrentThread()->WakeAfterDelay(nanoseconds); HLE::Reschedule(__func__); } break; @@ -71,7 +72,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, Memory::Write32(address, memory_value); if (memory_value <= value) { Kernel::WaitCurrentThread_ArbitrateAddress(address); - Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds); + GetCurrentThread()->WakeAfterDelay(nanoseconds); HLE::Reschedule(__func__); } break; diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index 638afff9e..8f6a1a8df 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h @@ -34,7 +34,7 @@ public: * @param name Optional name used for debugging. * @returns The created AddressArbiter. */ - static ResultVal<SharedPtr<AddressArbiter>> Create(std::string name = "Unknown"); + static SharedPtr<AddressArbiter> Create(std::string name = "Unknown"); std::string GetTypeName() const override { return "Arbiter"; } std::string GetName() const override { return name; } @@ -47,7 +47,8 @@ public: ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); private: - AddressArbiter() = default; + AddressArbiter(); + ~AddressArbiter() override; }; } // namespace FileSys diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index d9ad40c6a..898e1c98f 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -14,16 +14,17 @@ namespace Kernel { -ResultVal<SharedPtr<Event>> Event::Create(ResetType reset_type, std::string name) { +Event::Event() {} +Event::~Event() {} + +SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) { SharedPtr<Event> evt(new Event); - // TOOD(yuriks): Don't create Handle (see Thread::Create()) - CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(evt)); evt->signaled = false; evt->reset_type = evt->intitial_reset_type = reset_type; evt->name = std::move(name); - return MakeResult<SharedPtr<Event>>(evt); + return evt; } bool Event::ShouldWait() { diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 2c3e6b14e..fba960d2a 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -18,7 +18,7 @@ public: * @param reset_type ResetType describing how to create event * @param name Optional name of event */ - static ResultVal<SharedPtr<Event>> Create(ResetType reset_type, std::string name = "Unknown"); + static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown"); std::string GetTypeName() const override { return "Event"; } std::string GetName() const override { return name; } @@ -39,7 +39,8 @@ public: void Clear(); private: - Event() = default; + Event(); + ~Event() override; }; } // namespace diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index d7fa4dcea..7e0b9542e 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -14,14 +14,16 @@ namespace Kernel { +unsigned int Object::next_object_id = 0; + SharedPtr<Thread> g_main_thread = nullptr; HandleTable g_handle_table; u64 g_program_id = 0; -void WaitObject::AddWaitingThread(Thread* thread) { +void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) { auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); if (itr == waiting_threads.end()) - waiting_threads.push_back(thread); + waiting_threads.push_back(std::move(thread)); } void WaitObject::RemoveWaitingThread(Thread* thread) { @@ -30,11 +32,11 @@ void WaitObject::RemoveWaitingThread(Thread* thread) { waiting_threads.erase(itr); } -Thread* WaitObject::WakeupNextThread() { +SharedPtr<Thread> WaitObject::WakeupNextThread() { if (waiting_threads.empty()) return nullptr; - auto next_thread = waiting_threads.front(); + auto next_thread = std::move(waiting_threads.front()); waiting_threads.erase(waiting_threads.begin()); next_thread->ReleaseWaitObject(this); @@ -74,13 +76,10 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { // CTR-OS doesn't use generation 0, so skip straight to 1. if (next_generation >= (1 << 15)) next_generation = 1; - Handle handle = generation | (slot << 15); - if (obj->handle == INVALID_HANDLE) - obj->handle = handle; - generations[slot] = generation; objects[slot] = std::move(obj); + Handle handle = generation | (slot << 15); return MakeResult<Handle>(handle); } @@ -102,7 +101,7 @@ ResultCode HandleTable::Close(Handle handle) { objects[slot] = nullptr; - generations[generation] = next_free_slot; + generations[slot] = next_free_slot; next_free_slot = slot; return RESULT_SUCCESS; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 9860479ac..4d8e388b6 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -58,14 +58,12 @@ enum { DEFAULT_STACK_SIZE = 0x4000, }; -class HandleTable; - class Object : NonCopyable { - friend class HandleTable; - u32 handle = INVALID_HANDLE; public: virtual ~Object() {} - Handle GetHandle() const { return handle; } + + /// Returns a unique identifier for the object. For debugging purposes only. + unsigned int GetObjectId() const { return object_id; } virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } @@ -101,7 +99,10 @@ private: friend void intrusive_ptr_add_ref(Object*); friend void intrusive_ptr_release(Object*); + static unsigned int next_object_id; + unsigned int ref_count = 0; + unsigned int object_id = next_object_id++; }; // Special functions used by boost::instrusive_ptr to do automatic ref-counting @@ -135,25 +136,26 @@ public: * Add a thread to wait on this object * @param thread Pointer to thread to add */ - void AddWaitingThread(Thread* thread); + void AddWaitingThread(SharedPtr<Thread> thread); /** * Removes a thread from waiting on this object (e.g. if it was resumed already) * @param thread Pointer to thread to remove */ - void RemoveWaitingThread(Thread* thead); + void RemoveWaitingThread(Thread* thread); /** * Wake up the next thread waiting on this object * @return Pointer to the thread that was resumed, nullptr if no threads are waiting */ - Thread* WakeupNextThread(); + SharedPtr<Thread> WakeupNextThread(); /// Wake up all threads waiting on this object void WakeupAllWaitingThreads(); private: - std::vector<Thread*> waiting_threads; ///< Threads waiting for this object to become available + /// Threads waiting for this object to become available + std::vector<SharedPtr<Thread>> waiting_threads; }; /** @@ -274,7 +276,6 @@ private: }; extern HandleTable g_handle_table; -extern SharedPtr<Thread> g_main_thread; /// The ID code of the currently running game /// TODO(Subv): This variable should not be here, diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index acf484659..9f7166ca4 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -5,6 +5,8 @@ #include <map> #include <vector> +#include <boost/range/algorithm_ext/erase.hpp> + #include "common/common.h" #include "core/hle/kernel/kernel.h" @@ -13,9 +15,6 @@ namespace Kernel { -typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap; -static MutexMap g_mutex_held_locks; - /** * Resumes a thread waiting for the specified mutex * @param mutex The mutex that some thread is waiting on @@ -33,21 +32,17 @@ static void ResumeWaitingThread(Mutex* mutex) { } void ReleaseThreadMutexes(Thread* thread) { - auto locked_range = g_mutex_held_locks.equal_range(thread); - - // Release every mutex that the thread holds, and resume execution on the waiting threads - for (auto iter = locked_range.first; iter != locked_range.second; ++iter) { - ResumeWaitingThread(iter->second.get()); + for (auto& mtx : thread->held_mutexes) { + ResumeWaitingThread(mtx.get()); } - - // Erase all the locks that this thread holds - g_mutex_held_locks.erase(thread); + thread->held_mutexes.clear(); } -ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) { +Mutex::Mutex() {} +Mutex::~Mutex() {} + +SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) { SharedPtr<Mutex> mutex(new Mutex); - // TOOD(yuriks): Don't create Handle (see Thread::Create()) - CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(mutex)); mutex->initial_locked = initial_locked; mutex->locked = false; @@ -58,7 +53,7 @@ ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) if (initial_locked) mutex->Acquire(); - return MakeResult<SharedPtr<Mutex>>(mutex); + return mutex; } bool Mutex::ShouldWait() { @@ -69,30 +64,22 @@ void Mutex::Acquire() { Acquire(GetCurrentThread()); } -void Mutex::Acquire(Thread* thread) { +void Mutex::Acquire(SharedPtr<Thread> thread) { _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); if (locked) return; locked = true; - g_mutex_held_locks.insert(std::make_pair(thread, this)); - holding_thread = thread; + thread->held_mutexes.insert(this); + holding_thread = std::move(thread); } void Mutex::Release() { if (!locked) return; - auto locked_range = g_mutex_held_locks.equal_range(holding_thread); - - for (MutexMap::iterator iter = locked_range.first; iter != locked_range.second; ++iter) { - if (iter->second == this) { - g_mutex_held_locks.erase(iter); - break; - } - } - + holding_thread->held_mutexes.erase(this); ResumeWaitingThread(this); } diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 1e69528f1..548403614 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -22,7 +22,7 @@ public: * @param name Optional name of mutex * @return Pointer to new Mutex object */ - static ResultVal<SharedPtr<Mutex>> Create(bool initial_locked, std::string name = "Unknown"); + static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown"); std::string GetTypeName() const override { return "Mutex"; } std::string GetName() const override { return name; } @@ -43,11 +43,12 @@ public: * @param mutex Mutex that is to be acquired * @param thread Thread that will acquire the mutex */ - void Acquire(Thread* thread); + void Acquire(SharedPtr<Thread> thread); void Release(); private: - Mutex() = default; + Mutex(); + ~Mutex() override; }; /** diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index a9e406ef4..c8cf8b9a2 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp @@ -10,6 +10,9 @@ namespace Kernel { +Semaphore::Semaphore() {} +Semaphore::~Semaphore() {} + ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, std::string name) { @@ -18,8 +21,6 @@ ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_cou ErrorSummary::WrongArgument, ErrorLevel::Permanent); SharedPtr<Semaphore> semaphore(new Semaphore); - // TOOD(yuriks): Don't create Handle (see Thread::Create()) - CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore)); // When the semaphore is created, some slots are reserved for other threads, // and the rest is reserved for the caller thread diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h index 9bb404ab6..d8dc1fd78 100644 --- a/src/core/hle/kernel/semaphore.h +++ b/src/core/hle/kernel/semaphore.h @@ -47,7 +47,8 @@ public: ResultVal<s32> Release(s32 release_count); private: - Semaphore() = default; + Semaphore(); + ~Semaphore() override; }; } // namespace diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp new file mode 100644 index 000000000..0594967f8 --- /dev/null +++ b/src/core/hle/kernel/session.cpp @@ -0,0 +1,13 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/kernel/session.h" +#include "core/hle/kernel/thread.h" + +namespace Kernel { + +Session::Session() {} +Session::~Session() {} + +} diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h index 1788e4375..7cc9332c9 100644 --- a/src/core/hle/kernel/session.h +++ b/src/core/hle/kernel/session.h @@ -5,6 +5,7 @@ #pragma once #include "core/hle/kernel/kernel.h" +#include "core/mem_map.h" namespace Kernel { @@ -43,6 +44,9 @@ inline static u32* GetCommandBuffer(const int offset=0) { */ class Session : public WaitObject { public: + Session(); + ~Session() override; + std::string GetTypeName() const override { return "Session"; } static const HandleType HANDLE_TYPE = HandleType::Session; diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index eff68d481..4211fcf04 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -9,22 +9,23 @@ namespace Kernel { -ResultVal<SharedPtr<SharedMemory>> SharedMemory::Create(std::string name) { - SharedPtr<SharedMemory> shared_memory(new SharedMemory); +SharedMemory::SharedMemory() {} +SharedMemory::~SharedMemory() {} - // TOOD(yuriks): Don't create Handle (see Thread::Create()) - CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(shared_memory)); +SharedPtr<SharedMemory> SharedMemory::Create(std::string name) { + SharedPtr<SharedMemory> shared_memory(new SharedMemory); shared_memory->name = std::move(name); - return MakeResult<SharedPtr<SharedMemory>>(std::move(shared_memory)); + + return shared_memory; } ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions, MemoryPermission other_permissions) { if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { - LOG_ERROR(Kernel, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", - GetHandle(), address); + LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X outside of shared mem bounds!", + GetObjectId(), address); // TODO: Verify error code with hardware return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); @@ -41,7 +42,7 @@ ResultVal<u8*> SharedMemory::GetPointer(u32 offset) { if (base_address != 0) return MakeResult<u8*>(Memory::GetPointer(base_address + offset)); - LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", GetHandle()); + LOG_ERROR(Kernel_SVC, "memory block id=%u not mapped!", GetObjectId()); // TODO(yuriks): Verify error code. return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, ErrorSummary::InvalidState, ErrorLevel::Permanent); diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index d393e8175..5833b411c 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h @@ -29,7 +29,7 @@ public: * Creates a shared memory object * @param name Optional object name, used only for debugging purposes. */ - static ResultVal<SharedPtr<SharedMemory>> Create(std::string name = "Unknown"); + static SharedPtr<SharedMemory> Create(std::string name = "Unknown"); std::string GetTypeName() const override { return "SharedMemory"; } @@ -57,7 +57,8 @@ public: std::string name; ///< Name of shared memory object (optional) private: - SharedMemory() = default; + SharedMemory(); + ~SharedMemory() override; }; } // namespace diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 56950ebd4..3987f9608 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -4,7 +4,6 @@ #include <algorithm> #include <list> -#include <map> #include <vector> #include "common/common.h" @@ -41,6 +40,9 @@ static Thread* current_thread; static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup static u32 next_thread_id; ///< The next available thread id +Thread::Thread() {} +Thread::~Thread() {} + Thread* GetCurrentThread() { return current_thread; } @@ -108,6 +110,9 @@ void Thread::Stop(const char* reason) { WakeupAllWaitingThreads(); // Stopped threads are never waiting. + for (auto& wait_object : wait_objects) { + wait_object->RemoveWaitingThread(this); + } wait_objects.clear(); wait_address = 0; } @@ -228,13 +233,15 @@ void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) { /// Event type for the thread wake up event static int ThreadWakeupEventType = -1; +// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing +// us to simply use a pool index or similar. +static Kernel::HandleTable wakeup_callback_handle_table; /// Callback that will wake up the thread it was scheduled for -static void ThreadWakeupCallback(u64 parameter, int cycles_late) { - Handle handle = static_cast<Handle>(parameter); - SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(handle); +static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { + SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle); if (thread == nullptr) { - LOG_ERROR(Kernel, "Thread doesn't exist %u", handle); + LOG_CRITICAL(Kernel, "Callback fired for invalid thread %08X", thread_handle); return; } @@ -248,14 +255,13 @@ static void ThreadWakeupCallback(u64 parameter, int cycles_late) { } -void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds) { +void Thread::WakeAfterDelay(s64 nanoseconds) { // Don't schedule a wakeup if the thread wants to wait forever if (nanoseconds == -1) return; - _dbg_assert_(Kernel, thread != nullptr); u64 microseconds = nanoseconds / 1000; - CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, thread->GetHandle()); + CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, callback_handle); } void Thread::ReleaseWaitObject(WaitObject* wait_object) { @@ -302,7 +308,7 @@ void Thread::ReleaseWaitObject(WaitObject* wait_object) { void Thread::ResumeFromWait() { // Cancel any outstanding wakeup events - CoreTiming::UnscheduleEvent(ThreadWakeupEventType, GetHandle()); + CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle); status &= ~THREADSTATUS_WAIT; @@ -326,11 +332,11 @@ static void DebugThreadQueue() { if (!thread) { return; } - LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThread()->GetHandle()); + LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, GetCurrentThread()->GetObjectId()); for (auto& t : thread_list) { s32 priority = thread_ready_queue.contains(t.get()); if (priority != -1) { - LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, t->GetHandle()); + LOG_DEBUG(Kernel, "0x%02X %u", priority, t->GetObjectId()); } } } @@ -362,14 +368,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, SharedPtr<Thread> thread(new Thread); - // TODO(yuriks): Thread requires a handle to be inserted into the various scheduling queues for - // the time being. Create a handle here, it will be copied to the handle field in - // the object and use by the rest of the code. This should be removed when other - // code doesn't rely on the handle anymore. - ResultVal<Handle> handle = Kernel::g_handle_table.Create(thread); - if (handle.Failed()) - return handle.Code(); - thread_list.push_back(thread); thread_ready_queue.prepare(priority); @@ -385,6 +383,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, thread->wait_objects.clear(); thread->wait_address = 0; thread->name = std::move(name); + thread->callback_handle = wakeup_callback_handle_table.Create(thread).MoveFrom(); ResetThread(thread.get(), arg, 0); CallThread(thread.get()); @@ -418,16 +417,14 @@ void Thread::SetPriority(s32 priority) { } } -Handle SetupIdleThread() { +SharedPtr<Thread> SetupIdleThread() { // We need to pass a few valid values to get around parameter checking in Thread::Create. - auto thread_res = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0, - THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE); - _dbg_assert_(Kernel, thread_res.Succeeded()); - SharedPtr<Thread> thread = std::move(*thread_res); + auto thread = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0, + THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE).MoveFrom(); thread->idle = true; CallThread(thread.get()); - return thread->GetHandle(); + return thread; } SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size) { @@ -460,13 +457,13 @@ void Reschedule() { HLE::g_reschedule = false; if (next != nullptr) { - LOG_TRACE(Kernel, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle()); + LOG_TRACE(Kernel, "context switch %u -> %u", prev->GetObjectId(), next->GetObjectId()); SwitchContext(next); } else { - LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); + LOG_TRACE(Kernel, "cannot context switch from %u, no higher priority thread!", prev->GetObjectId()); for (auto& thread : thread_list) { - LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X", thread->GetHandle(), + LOG_TRACE(Kernel, "\tid=%u prio=0x%02X, status=0x%08X", thread->GetObjectId(), thread->current_priority, thread->status); } } diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index d6299364a..633bb7c98 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -7,6 +7,8 @@ #include <string> #include <vector> +#include <boost/container/flat_set.hpp> + #include "common/common_types.h" #include "core/core.h" @@ -40,6 +42,8 @@ enum ThreadStatus { namespace Kernel { +class Mutex; + class Thread final : public WaitObject { public: static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, @@ -78,6 +82,12 @@ public: void ResumeFromWait(); /** + * Schedules an event to wake up the specified thread after the specified delay. + * @param nanoseconds The time this thread will be allowed to sleep for. + */ + void WakeAfterDelay(s64 nanoseconds); + + /** * Sets the result after the thread awakens (from either WaitSynchronization SVC) * @param result Value to set to the returned result */ @@ -103,8 +113,10 @@ public: s32 processor_id; - std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on + /// Mutexes currently held by this thread, which will be released when it exits. + boost::container::flat_set<SharedPtr<Mutex>> held_mutexes; + std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address bool wait_all; ///< True if the thread is waiting on all objects before resuming bool wait_set_output; ///< True if the output parameter should be set on thread wakeup @@ -115,9 +127,15 @@ public: bool idle = false; private: - Thread() = default; + Thread(); + ~Thread() override; + + /// Handle used as userdata to reference this object when inserting into the CoreTiming queue. + Handle callback_handle; }; +extern SharedPtr<Thread> g_main_thread; + /// Sets up the primary application thread SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size); @@ -151,19 +169,12 @@ void WaitCurrentThread_WaitSynchronization(SharedPtr<WaitObject> wait_object, bo void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); /** - * Schedules an event to wake up the specified thread after the specified delay. - * @param handle The thread handle. - * @param nanoseconds The time this thread will be allowed to sleep for. - */ -void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds); - -/** * Sets up the idle thread, this is a thread that is intended to never execute instructions, * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue * and will try to yield on every call. * @returns The handle of the idle thread */ -Handle SetupIdleThread(); +SharedPtr<Thread> SetupIdleThread(); /// Initialize threading void ThreadingInit(); diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index 503a5d2ce..4352fc99c 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp @@ -2,8 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include <set> - #include "common/common.h" #include "core/core_timing.h" @@ -15,18 +13,24 @@ namespace Kernel { /// The event type of the generic timer callback event static int timer_callback_event_type = -1; +// TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future, allowing +// us to simply use a pool index or similar. +static Kernel::HandleTable timer_callback_handle_table; + +Timer::Timer() {} +Timer::~Timer() {} -ResultVal<SharedPtr<Timer>> Timer::Create(ResetType reset_type, std::string name) { +SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) { SharedPtr<Timer> timer(new Timer); - // TOOD(yuriks): Don't create Handle (see Thread::Create()) - CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(timer)); timer->reset_type = reset_type; timer->signaled = false; timer->name = std::move(name); timer->initial_delay = 0; timer->interval_delay = 0; - return MakeResult<SharedPtr<Timer>>(timer); + timer->callback_handle = timer_callback_handle_table.Create(timer).MoveFrom(); + + return timer; } bool Timer::ShouldWait() { @@ -38,17 +42,19 @@ void Timer::Acquire() { } void Timer::Set(s64 initial, s64 interval) { + // Ensure we get rid of any previous scheduled event + Cancel(); + initial_delay = initial; interval_delay = interval; u64 initial_microseconds = initial / 1000; - // TODO(yuriks): Figure out a replacement for GetHandle here - CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type, - GetHandle()); + CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), + timer_callback_event_type, callback_handle); } void Timer::Cancel() { - CoreTiming::UnscheduleEvent(timer_callback_event_type, GetHandle()); + CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_handle); } void Timer::Clear() { @@ -57,7 +63,7 @@ void Timer::Clear() { /// The timer callback event, called when a timer is fired static void TimerCallback(u64 timer_handle, int cycles_late) { - SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle); + SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(timer_handle); if (timer == nullptr) { LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle); diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h index c45e79954..540e4e187 100644 --- a/src/core/hle/kernel/timer.h +++ b/src/core/hle/kernel/timer.h @@ -19,7 +19,7 @@ public: * @param name Optional name of timer * @return The created Timer */ - static ResultVal<SharedPtr<Timer>> Create(ResetType reset_type, std::string name = "Unknown"); + static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown"); std::string GetTypeName() const override { return "Timer"; } std::string GetName() const override { return name; } @@ -49,7 +49,11 @@ public: void Clear(); private: - Timer() = default; + Timer(); + ~Timer() override; + + /// Handle used as userdata to reference this object when inserting into the CoreTiming queue. + Handle callback_handle; }; /// Initializes the required variables for timers diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp index 20a3fa2e5..53d920de1 100644 --- a/src/core/hle/service/ac_u.cpp +++ b/src/core/hle/service/ac_u.cpp @@ -53,7 +53,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/act_u.cpp b/src/core/hle/service/act_u.cpp index 10870f14b..4ea7a9fb2 100644 --- a/src/core/hle/service/act_u.cpp +++ b/src/core/hle/service/act_u.cpp @@ -18,7 +18,7 @@ namespace ACT_U { // Interface class Interface::Interface() { - //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + //Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/am_app.cpp b/src/core/hle/service/am_app.cpp index 0b396b6d3..df10db87f 100644 --- a/src/core/hle/service/am_app.cpp +++ b/src/core/hle/service/am_app.cpp @@ -18,7 +18,7 @@ namespace AM_APP { // Interface class Interface::Interface() { - //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + //Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/am_net.cpp b/src/core/hle/service/am_net.cpp index 112844e5b..c74012d9d 100644 --- a/src/core/hle/service/am_net.cpp +++ b/src/core/hle/service/am_net.cpp @@ -38,7 +38,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/am_sys.cpp b/src/core/hle/service/am_sys.cpp index b63c8c087..c5df8abda 100644 --- a/src/core/hle/service/am_sys.cpp +++ b/src/core/hle/service/am_sys.cpp @@ -18,7 +18,7 @@ namespace AM_SYS { // Interface class Interface::Interface() { - //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + //Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/apt_a.cpp b/src/core/hle/service/apt_a.cpp index 42f2879c1..e1dd2a5fb 100644 --- a/src/core/hle/service/apt_a.cpp +++ b/src/core/hle/service/apt_a.cpp @@ -39,7 +39,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/apt_s.cpp b/src/core/hle/service/apt_s.cpp index 7ad428ee7..686335428 100644 --- a/src/core/hle/service/apt_s.cpp +++ b/src/core/hle/service/apt_s.cpp @@ -117,7 +117,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp index 4c3f621d0..ccfd04591 100644 --- a/src/core/hle/service/apt_u.cpp +++ b/src/core/hle/service/apt_u.cpp @@ -69,8 +69,8 @@ void Initialize(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); // TODO(bunnei): Check if these are created in Initialize or on APT process startup. - notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification").MoveFrom(); - pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause").MoveFrom(); + notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification"); + pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause"); cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); cmd_buff[4] = Kernel::g_handle_table.Create(pause_event).MoveFrom(); @@ -512,15 +512,15 @@ Interface::Interface() { file.ReadBytes(shared_font.data(), (size_t)file.GetSize()); // Create shared font memory object - shared_font_mem = Kernel::SharedMemory::Create("APT_U:shared_font_mem").MoveFrom(); + shared_font_mem = Kernel::SharedMemory::Create("APT_U:shared_font_mem"); } else { LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str()); shared_font_mem = nullptr; } - lock = Kernel::Mutex::Create(false, "APT_U:Lock").MoveFrom(); + lock = Kernel::Mutex::Create(false, "APT_U:Lock"); - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/boss_p.cpp b/src/core/hle/service/boss_p.cpp index f245a38e9..b3aa6acee 100644 --- a/src/core/hle/service/boss_p.cpp +++ b/src/core/hle/service/boss_p.cpp @@ -18,7 +18,7 @@ namespace BOSS_P { // Interface class Interface::Interface() { - //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + //Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/boss_u.cpp b/src/core/hle/service/boss_u.cpp index 1820ea7ad..50bb5d426 100644 --- a/src/core/hle/service/boss_u.cpp +++ b/src/core/hle/service/boss_u.cpp @@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/cam_u.cpp b/src/core/hle/service/cam_u.cpp index 549095339..cf3b27664 100644 --- a/src/core/hle/service/cam_u.cpp +++ b/src/core/hle/service/cam_u.cpp @@ -18,7 +18,7 @@ namespace CAM_U { // Interface class Interface::Interface() { - //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + //Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/cecd_s.cpp b/src/core/hle/service/cecd_s.cpp index 9c4992f13..2c707baff 100644 --- a/src/core/hle/service/cecd_s.cpp +++ b/src/core/hle/service/cecd_s.cpp @@ -18,7 +18,7 @@ namespace CECD_S { // Interface class Interface::Interface() { - //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + //Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/cecd_u.cpp b/src/core/hle/service/cecd_u.cpp index b7655ef0b..b7ea3a186 100644 --- a/src/core/hle/service/cecd_u.cpp +++ b/src/core/hle/service/cecd_u.cpp @@ -18,7 +18,7 @@ namespace CECD_U { // Interface class Interface::Interface() { - //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + //Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp index 7c1ee8ac3..555b7884a 100644 --- a/src/core/hle/service/cfg/cfg_i.cpp +++ b/src/core/hle/service/cfg/cfg_i.cpp @@ -104,7 +104,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp index cf4e82152..2170894d6 100644 --- a/src/core/hle/service/cfg/cfg_s.cpp +++ b/src/core/hle/service/cfg/cfg_s.cpp @@ -92,7 +92,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp index 835620909..1da9f59f6 100644 --- a/src/core/hle/service/cfg/cfg_u.cpp +++ b/src/core/hle/service/cfg/cfg_u.cpp @@ -186,7 +186,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp index 3a557efe1..39b00982c 100644 --- a/src/core/hle/service/csnd_snd.cpp +++ b/src/core/hle/service/csnd_snd.cpp @@ -29,7 +29,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 9a38be393..0f86894a6 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -201,12 +201,11 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, - "DSP_DSP::semaphore_event").MoveFrom(); + semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event"); interrupt_event = nullptr; read_pipe_count = 0; - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp index 8c900eabc..962de2170 100644 --- a/src/core/hle/service/err_f.cpp +++ b/src/core/hle/service/err_f.cpp @@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/frd_a.cpp b/src/core/hle/service/frd_a.cpp index 53edc2cd8..79140a756 100644 --- a/src/core/hle/service/frd_a.cpp +++ b/src/core/hle/service/frd_a.cpp @@ -18,7 +18,7 @@ namespace FRD_A { // Interface class Interface::Interface() { - //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + //Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/frd_u.cpp b/src/core/hle/service/frd_u.cpp index 021186e57..59faca77a 100644 --- a/src/core/hle/service/frd_u.cpp +++ b/src/core/hle/service/frd_u.cpp @@ -27,7 +27,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 43eef034e..ccf132f31 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -163,7 +163,7 @@ public: case FileCommand::OpenLinkFile: { LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); - cmd_buff[3] = GetHandle(); + cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE); break; } @@ -303,7 +303,8 @@ ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, Arc return RESULT_SUCCESS; } -ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { +ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle, + const FileSys::Path& path, const FileSys::Mode mode) { Archive* archive = GetArchive(archive_handle); if (archive == nullptr) return ERR_INVALID_HANDLE; @@ -314,10 +315,8 @@ ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSy ErrorSummary::NotFound, ErrorLevel::Status); } - auto file = Common::make_unique<File>(std::move(backend), path); - // TOOD(yuriks): Fix error reporting - Handle handle = Kernel::g_handle_table.Create(file.release()).ValueOr(INVALID_HANDLE); - return MakeResult<Handle>(handle); + auto file = Kernel::SharedPtr<File>(new File(std::move(backend), path)); + return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(file)); } ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { @@ -403,13 +402,8 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons ErrorSummary::NothingHappened, ErrorLevel::Status); } -/** - * Open a Directory from an Archive - * @param archive_handle Handle to an open Archive object - * @param path Path to the Directory inside of the Archive - * @return Opened Directory object - */ -ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { +ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, + const FileSys::Path& path) { Archive* archive = GetArchive(archive_handle); if (archive == nullptr) return ERR_INVALID_HANDLE; @@ -420,10 +414,8 @@ ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const F ErrorSummary::NotFound, ErrorLevel::Permanent); } - auto directory = Common::make_unique<Directory>(std::move(backend), path); - // TOOD(yuriks): Fix error reporting - Handle handle = Kernel::g_handle_table.Create(directory.release()).ValueOr(INVALID_HANDLE); - return MakeResult<Handle>(handle); + auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path)); + return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(directory)); } ResultCode FormatSaveData() { diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index ba674d7f6..ab5ea4da8 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h @@ -15,6 +15,10 @@ extern const std::string SYSTEM_ID; /// The scrambled SD card CID, also known as ID1 extern const std::string SDCARD_ID; +namespace Kernel { + class Session; +} + namespace Service { namespace FS { @@ -58,9 +62,10 @@ ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, Arc * @param archive_handle Handle to an open Archive object * @param path Path to the File inside of the Archive * @param mode Mode under which to open the File - * @return Handle to the opened File object + * @return The opened File object as a Session */ -ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); +ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle, + const FileSys::Path& path, const FileSys::Mode mode); /** * Delete a File from an Archive @@ -121,9 +126,10 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons * Open a Directory from an Archive * @param archive_handle Handle to an open Archive object * @param path Path to the Directory inside of the Archive - * @return Handle to the opened File object + * @return The opened Directory object as a Session */ -ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path); +ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, + const FileSys::Path& path); /** * Creates a blank SaveData archive. diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index c495b6f3c..94a3a31c8 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -14,6 +14,9 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace FS_User +using Kernel::SharedPtr; +using Kernel::Session; + namespace Service { namespace FS { @@ -58,10 +61,10 @@ static void OpenFile(Service::Interface* self) { LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); - ResultVal<Handle> handle = OpenFileFromArchive(archive_handle, file_path, mode); - cmd_buff[1] = handle.Code().raw; - if (handle.Succeeded()) { - cmd_buff[3] = *handle; + ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); + cmd_buff[1] = file_res.Code().raw; + if (file_res.Succeeded()) { + cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); } else { cmd_buff[3] = 0; LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); @@ -114,10 +117,10 @@ static void OpenFileDirectly(Service::Interface* self) { } SCOPE_EXIT({ CloseArchive(*archive_handle); }); - ResultVal<Handle> handle = OpenFileFromArchive(*archive_handle, file_path, mode); - cmd_buff[1] = handle.Code().raw; - if (handle.Succeeded()) { - cmd_buff[3] = *handle; + ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); + cmd_buff[1] = file_res.Code().raw; + if (file_res.Succeeded()) { + cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); } else { cmd_buff[3] = 0; LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); @@ -334,10 +337,10 @@ static void OpenDirectory(Service::Interface* self) { LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); - ResultVal<Handle> handle = OpenDirectoryFromArchive(archive_handle, dir_path); - cmd_buff[1] = handle.Code().raw; - if (handle.Succeeded()) { - cmd_buff[3] = *handle; + ResultVal<SharedPtr<Session>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); + cmd_buff[1] = dir_res.Code().raw; + if (dir_res.Succeeded()) { + cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom(); } else { LOG_ERROR(Service_FS, "failed to get a handle for directory"); } @@ -588,7 +591,7 @@ const FSUserInterface::FunctionInfo FunctionTable[] = { // Interface class FSUserInterface::FSUserInterface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace FS diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 5b91f17d2..495c117ee 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -187,7 +187,7 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { g_interrupt_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[3]); _assert_msg_(GSP, (g_interrupt_event != nullptr), "handle is not valid!"); - g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem").MoveFrom(); + g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem"); Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); @@ -389,7 +389,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); g_interrupt_event = 0; g_shared_memory = 0; diff --git a/src/core/hle/service/gsp_lcd.cpp b/src/core/hle/service/gsp_lcd.cpp index 6213472ff..d63fa1ee2 100644 --- a/src/core/hle/service/gsp_lcd.cpp +++ b/src/core/hle/service/gsp_lcd.cpp @@ -20,7 +20,7 @@ namespace GSP_LCD { // Interface class Interface::Interface() { - //Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + //Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 835055af4..7cb01729e 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -30,6 +30,8 @@ static s16 next_circle_y = 0; * Gets a pointer to the PadData structure inside HID shared memory */ static inline PadData* GetPadData() { + if (g_shared_mem == nullptr) + return nullptr; return reinterpret_cast<PadData*>(g_shared_mem->GetPointer().ValueOr(nullptr)); } @@ -122,14 +124,14 @@ void PadUpdateComplete() { void HIDInit() { using namespace Kernel; - g_shared_mem = SharedMemory::Create("HID:SharedMem").MoveFrom(); + g_shared_mem = SharedMemory::Create("HID:SharedMem"); // Create event handles - g_event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1").MoveFrom(); - g_event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2").MoveFrom(); - g_event_accelerometer = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer").MoveFrom(); - g_event_gyroscope = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope").MoveFrom(); - g_event_debug_pad = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad").MoveFrom(); + g_event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1"); + g_event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2"); + g_event_accelerometer = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer"); + g_event_gyroscope = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope"); + g_event_debug_pad = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad"); } void HIDShutdown() { diff --git a/src/core/hle/service/hid/hid_spvr.cpp b/src/core/hle/service/hid/hid_spvr.cpp index 76c40b659..054aa8b59 100644 --- a/src/core/hle/service/hid/hid_spvr.cpp +++ b/src/core/hle/service/hid/hid_spvr.cpp @@ -32,7 +32,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp index 5444aa5ee..68edafebb 100644 --- a/src/core/hle/service/hid/hid_user.cpp +++ b/src/core/hle/service/hid/hid_user.cpp @@ -72,7 +72,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp index d0bff552f..6595ca572 100644 --- a/src/core/hle/service/http_c.cpp +++ b/src/core/hle/service/http_c.cpp @@ -58,7 +58,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/ir_rst.cpp b/src/core/hle/service/ir_rst.cpp index d49bd5335..31da8e160 100644 --- a/src/core/hle/service/ir_rst.cpp +++ b/src/core/hle/service/ir_rst.cpp @@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/ir_u.cpp b/src/core/hle/service/ir_u.cpp index da6f38e41..7fa233048 100644 --- a/src/core/hle/service/ir_u.cpp +++ b/src/core/hle/service/ir_u.cpp @@ -36,7 +36,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/ldr_ro.cpp b/src/core/hle/service/ldr_ro.cpp index 7d6e2e8e8..459717fff 100644 --- a/src/core/hle/service/ldr_ro.cpp +++ b/src/core/hle/service/ldr_ro.cpp @@ -27,7 +27,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp index 82bce9180..af967b5b6 100644 --- a/src/core/hle/service/mic_u.cpp +++ b/src/core/hle/service/mic_u.cpp @@ -34,7 +34,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/ndm_u.cpp b/src/core/hle/service/ndm_u.cpp index 0f03de6ae..df3c97193 100644 --- a/src/core/hle/service/ndm_u.cpp +++ b/src/core/hle/service/ndm_u.cpp @@ -24,7 +24,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/news_s.cpp b/src/core/hle/service/news_s.cpp index 1850f59bd..d7537875b 100644 --- a/src/core/hle/service/news_s.cpp +++ b/src/core/hle/service/news_s.cpp @@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/news_u.cpp b/src/core/hle/service/news_u.cpp index b5adad4c6..a9e161c23 100644 --- a/src/core/hle/service/news_u.cpp +++ b/src/core/hle/service/news_u.cpp @@ -19,7 +19,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/nim_aoc.cpp b/src/core/hle/service/nim_aoc.cpp index 17d1c4ff5..ab2ef4429 100644 --- a/src/core/hle/service/nim_aoc.cpp +++ b/src/core/hle/service/nim_aoc.cpp @@ -25,7 +25,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/ns_s.cpp b/src/core/hle/service/ns_s.cpp index b9aca4257..5cf3e2039 100644 --- a/src/core/hle/service/ns_s.cpp +++ b/src/core/hle/service/ns_s.cpp @@ -21,7 +21,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp index ce456a966..61fcb54ce 100644 --- a/src/core/hle/service/nwm_uds.cpp +++ b/src/core/hle/service/nwm_uds.cpp @@ -26,7 +26,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp index 529dccafb..d61eaf80f 100644 --- a/src/core/hle/service/pm_app.cpp +++ b/src/core/hle/service/pm_app.cpp @@ -26,7 +26,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/ptm_play.cpp b/src/core/hle/service/ptm_play.cpp index ae9e2925c..b357057fd 100644 --- a/src/core/hle/service/ptm_play.cpp +++ b/src/core/hle/service/ptm_play.cpp @@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/ptm_sysm.cpp b/src/core/hle/service/ptm_sysm.cpp index 4b5f86a47..b6f688de3 100644 --- a/src/core/hle/service/ptm_sysm.cpp +++ b/src/core/hle/service/ptm_sysm.cpp @@ -50,7 +50,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp index 753180add..7b465a348 100644 --- a/src/core/hle/service/ptm_u.cpp +++ b/src/core/hle/service/ptm_u.cpp @@ -137,7 +137,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); // Create the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file // TODO(Subv): In the future we should use the FS service to query this archive std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 355196fd3..e0979ea5d 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -54,96 +54,76 @@ namespace Service { -Manager* g_manager = nullptr; ///< Service manager +std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports; +std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services; //////////////////////////////////////////////////////////////////////////////////////////////////// -// Service Manager class - -void Manager::AddService(Interface* service) { - // TOOD(yuriks): Fix error reporting - m_port_map[service->GetPortName()] = Kernel::g_handle_table.Create(service).ValueOr(INVALID_HANDLE); - m_services.push_back(service); -} - -void Manager::DeleteService(const std::string& port_name) { - Interface* service = FetchFromPortName(port_name); - m_services.erase(std::remove(m_services.begin(), m_services.end(), service), m_services.end()); - m_port_map.erase(port_name); -} +// Module interface -Interface* Manager::FetchFromHandle(Handle handle) { - // TODO(yuriks): This function is very suspicious and should probably be exterminated. - return Kernel::g_handle_table.Get<Interface>(handle).get(); +static void AddNamedPort(Interface* interface) { + g_kernel_named_ports.emplace(interface->GetPortName(), interface); } -Interface* Manager::FetchFromPortName(const std::string& port_name) { - auto itr = m_port_map.find(port_name); - if (itr == m_port_map.end()) { - return nullptr; - } - return FetchFromHandle(itr->second); +static void AddService(Interface* interface) { + g_srv_services.emplace(interface->GetPortName(), interface); } - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Module interface - /// Initialize ServiceManager void Init() { - g_manager = new Manager; - - g_manager->AddService(new SRV::Interface); - g_manager->AddService(new AC_U::Interface); - g_manager->AddService(new ACT_U::Interface); - g_manager->AddService(new AM_APP::Interface); - g_manager->AddService(new AM_NET::Interface); - g_manager->AddService(new AM_SYS::Interface); - g_manager->AddService(new APT_A::Interface); - g_manager->AddService(new APT_S::Interface); - g_manager->AddService(new APT_U::Interface); - g_manager->AddService(new BOSS_P::Interface); - g_manager->AddService(new BOSS_U::Interface); - g_manager->AddService(new CAM_U::Interface); - g_manager->AddService(new CECD_S::Interface); - g_manager->AddService(new CECD_U::Interface); - g_manager->AddService(new CFG_I::Interface); - g_manager->AddService(new CFG_S::Interface); - g_manager->AddService(new CFG_U::Interface); - g_manager->AddService(new CSND_SND::Interface); - g_manager->AddService(new DSP_DSP::Interface); - g_manager->AddService(new ERR_F::Interface); - g_manager->AddService(new FRD_A::Interface); - g_manager->AddService(new FRD_U::Interface); - g_manager->AddService(new FS::FSUserInterface); - g_manager->AddService(new GSP_GPU::Interface); - g_manager->AddService(new GSP_LCD::Interface); - g_manager->AddService(new HID_User::Interface); - g_manager->AddService(new HID_SPVR::Interface); - g_manager->AddService(new HTTP_C::Interface); - g_manager->AddService(new IR_RST::Interface); - g_manager->AddService(new IR_U::Interface); - g_manager->AddService(new LDR_RO::Interface); - g_manager->AddService(new MIC_U::Interface); - g_manager->AddService(new NDM_U::Interface); - g_manager->AddService(new NEWS_S::Interface); - g_manager->AddService(new NEWS_U::Interface); - g_manager->AddService(new NIM_AOC::Interface); - g_manager->AddService(new NS_S::Interface); - g_manager->AddService(new NWM_UDS::Interface); - g_manager->AddService(new PM_APP::Interface); - g_manager->AddService(new PTM_PLAY::Interface); - g_manager->AddService(new PTM_U::Interface); - g_manager->AddService(new PTM_SYSM::Interface); - g_manager->AddService(new SOC_U::Interface); - g_manager->AddService(new SSL_C::Interface); - g_manager->AddService(new Y2R_U::Interface); + AddNamedPort(new SRV::Interface); + + AddService(new AC_U::Interface); + AddService(new ACT_U::Interface); + AddService(new AM_APP::Interface); + AddService(new AM_NET::Interface); + AddService(new AM_SYS::Interface); + AddService(new APT_A::Interface); + AddService(new APT_S::Interface); + AddService(new APT_U::Interface); + AddService(new BOSS_P::Interface); + AddService(new BOSS_U::Interface); + AddService(new CAM_U::Interface); + AddService(new CECD_S::Interface); + AddService(new CECD_U::Interface); + AddService(new CFG_I::Interface); + AddService(new CFG_S::Interface); + AddService(new CFG_U::Interface); + AddService(new CSND_SND::Interface); + AddService(new DSP_DSP::Interface); + AddService(new ERR_F::Interface); + AddService(new FRD_A::Interface); + AddService(new FRD_U::Interface); + AddService(new FS::FSUserInterface); + AddService(new GSP_GPU::Interface); + AddService(new GSP_LCD::Interface); + AddService(new HID_User::Interface); + AddService(new HID_SPVR::Interface); + AddService(new HTTP_C::Interface); + AddService(new IR_RST::Interface); + AddService(new IR_U::Interface); + AddService(new LDR_RO::Interface); + AddService(new MIC_U::Interface); + AddService(new NDM_U::Interface); + AddService(new NEWS_S::Interface); + AddService(new NEWS_U::Interface); + AddService(new NIM_AOC::Interface); + AddService(new NS_S::Interface); + AddService(new NWM_UDS::Interface); + AddService(new PM_APP::Interface); + AddService(new PTM_PLAY::Interface); + AddService(new PTM_U::Interface); + AddService(new PTM_SYSM::Interface); + AddService(new SOC_U::Interface); + AddService(new SSL_C::Interface); + AddService(new Y2R_U::Interface); LOG_DEBUG(Service, "initialized OK"); } /// Shutdown ServiceManager void Shutdown() { - delete g_manager; + g_srv_services.clear(); + g_kernel_named_ports.clear(); LOG_DEBUG(Service, "shutdown OK"); } diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index e75d5008b..3370f9f9b 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -5,9 +5,11 @@ #pragma once #include <algorithm> -#include <vector> -#include <map> #include <string> +#include <unordered_map> +#include <vector> + +#include <boost/container/flat_map.hpp> #include "common/common.h" #include "common/string_util.h" @@ -27,7 +29,7 @@ static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 character class Manager; /// Interface to a CTROS service -class Interface : public Kernel::Session { +class Interface : public Kernel::Session { // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be // just something that encapsulates a session and acts as a helper to implement service // processes. @@ -38,11 +40,11 @@ class Interface : public Kernel::Session { * Creates a function string for logging, complete with the name (or header code, depending * on what's passed in) the port name, and all the cmd_buff arguments. */ - std::string MakeFunctionString(const std::string& name, const std::string& port_name, const u32* cmd_buff) { + std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) { // Number of params == bits 0-5 + bits 6-11 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); - std::string function_string = Common::StringFromFormat("function '%s': port=%s", name.c_str(), port_name.c_str()); + std::string function_string = Common::StringFromFormat("function '%s': port=%s", name, port_name); for (int i = 1; i <= num_params; ++i) { function_string += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]); } @@ -57,7 +59,7 @@ public: struct FunctionInfo { u32 id; Function func; - std::string name; + const char* name; }; /** @@ -68,34 +70,19 @@ public: return "[UNKNOWN SERVICE PORT]"; } - /// Allocates a new handle for the service - Handle CreateHandle(Kernel::Object *obj) { - // TODO(yuriks): Fix error reporting - Handle handle = Kernel::g_handle_table.Create(obj).ValueOr(INVALID_HANDLE); - m_handles.push_back(handle); - return handle; - } - - /// Frees a handle from the service - template <class T> - void DeleteHandle(const Handle handle) { - Kernel::g_handle_table.Close(handle); - m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end()); - } - ResultVal<bool> SyncRequest() override { u32* cmd_buff = Kernel::GetCommandBuffer(); auto itr = m_functions.find(cmd_buff[0]); if (itr == m_functions.end() || itr->second.func == nullptr) { std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name; - LOG_ERROR(Service, "%s %s", "unknown/unimplemented", MakeFunctionString(function_name, GetPortName(), cmd_buff).c_str()); + LOG_ERROR(Service, "unknown / unimplemented %s", MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str()); // TODO(bunnei): Hack - ignore error cmd_buff[1] = 0; return MakeResult<bool>(false); } else { - LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName(), cmd_buff).c_str()); + LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str()); } itr->second.func(this); @@ -108,37 +95,18 @@ protected: /** * Registers the functions in the service */ - void Register(const FunctionInfo* functions, int len) { - for (int i = 0; i < len; i++) { - m_functions[functions[i].id] = functions[i]; + template <size_t N> + void Register(const FunctionInfo (&functions)[N]) { + m_functions.reserve(N); + for (auto& fn : functions) { + // Usually this array is sorted by id already, so hint to instead at the end + m_functions.emplace_hint(m_functions.cend(), fn.id, fn); } } private: + boost::container::flat_map<u32, FunctionInfo> m_functions; - std::vector<Handle> m_handles; - std::map<u32, FunctionInfo> m_functions; - -}; - -/// Simple class to manage accessing services from ports and UID handles -class Manager { -public: - /// Add a service to the manager - void AddService(Interface* service); - - /// Removes a service from the manager - void DeleteService(const std::string& port_name); - - /// Get a Service Interface from its Handle - Interface* FetchFromHandle(Handle handle); - - /// Get a Service Interface from its port - Interface* FetchFromPortName(const std::string& port_name); - -private: - std::vector<Interface*> m_services; - std::map<std::string, u32> m_port_map; }; /// Initialize ServiceManager @@ -147,8 +115,9 @@ void Init(); /// Shutdown ServiceManager void Shutdown(); - -extern Manager* g_manager; ///< Service manager - +/// Map of named ports managed by the kernel, which can be retrieved using the ConnectToPort SVC. +extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_kernel_named_ports; +/// Map of services registered with the "srv:" service, retrieved using GetServiceHandle. +extern std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services; } // namespace diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index bb8ee86be..414c53c54 100644 --- a/src/core/hle/service/soc_u.cpp +++ b/src/core/hle/service/soc_u.cpp @@ -734,7 +734,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } Interface::~Interface() { diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index aa0aac3bb..cc59a03ce 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -23,7 +23,7 @@ static void GetProcSemaphore(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); // TODO(bunnei): Change to a semaphore once these have been implemented - event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event").MoveFrom(); + event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event"); event_handle->Clear(); cmd_buff[1] = 0; // No error @@ -35,10 +35,10 @@ static void GetServiceHandle(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); - Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); + auto it = Service::g_srv_services.find(port_name); - if (nullptr != service) { - cmd_buff[3] = service->GetHandle(); + if (it != Service::g_srv_services.end()) { + cmd_buff[3] = Kernel::g_handle_table.Create(it->second).MoveFrom(); LOG_TRACE(Service_SRV, "called port=%s, handle=0x%08X", port_name.c_str(), cmd_buff[3]); } else { LOG_ERROR(Service_SRV, "(UNIMPLEMENTED) called port=%s", port_name.c_str()); @@ -63,7 +63,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp index 360516cdf..3f49c1c97 100644 --- a/src/core/hle/service/ssl_c.cpp +++ b/src/core/hle/service/ssl_c.cpp @@ -22,7 +22,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp index b3d873ef0..fc76d2721 100644 --- a/src/core/hle/service/y2r_u.cpp +++ b/src/core/hle/service/y2r_u.cpp @@ -54,7 +54,7 @@ const Interface::FunctionInfo FunctionTable[] = { // Interface class Interface::Interface() { - Register(FunctionTable, ARRAY_SIZE(FunctionTable)); + Register(FunctionTable); } } // namespace diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 88813c2ce..34a27917f 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -30,6 +30,11 @@ using Kernel::ERR_INVALID_HANDLE; namespace SVC { +const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, + ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA +const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E + /// An invalid result code that is meant to be overwritten when a thread resumes from waiting const ResultCode RESULT_INVALID(0xDEADC0DE); @@ -94,14 +99,21 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o } /// Connect to an OS service given the port name, returns the handle to the port to out -static ResultCode ConnectToPort(Handle* out, const char* port_name) { - Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); +static ResultCode ConnectToPort(Handle* out_handle, const char* port_name) { + if (port_name == nullptr) + return ERR_NOT_FOUND; + if (std::strlen(port_name) > 11) + return ERR_PORT_NAME_TOO_LONG; LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); - _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!"); - *out = service->GetHandle(); + auto it = Service::g_kernel_named_ports.find(port_name); + if (it == Service::g_kernel_named_ports.end()) { + LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name); + return ERR_NOT_FOUND; + } + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(it->second)); return RESULT_SUCCESS; } @@ -119,9 +131,8 @@ static ResultCode SendSyncRequest(Handle handle) { /// Close a handle static ResultCode CloseHandle(Handle handle) { - // ImplementMe - LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); - return RESULT_SUCCESS; + LOG_TRACE(Kernel_SVC, "Closing handle 0x%08X", handle); + return Kernel::g_handle_table.Close(handle); } /// Wait for a handle to synchronize, timeout after the specified nanoseconds @@ -140,7 +151,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { Kernel::WaitCurrentThread_WaitSynchronization(object, false, false); // Create an event to wake the thread up after the specified nanosecond delay has passed - Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds); + Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds); HLE::Reschedule(__func__); @@ -216,7 +227,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou } // Create an event to wake the thread up after the specified nanosecond delay has passed - Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds); + Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds); HLE::Reschedule(__func__); @@ -250,7 +261,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou static ResultCode CreateAddressArbiter(Handle* out_handle) { using Kernel::AddressArbiter; - CASCADE_RESULT(SharedPtr<AddressArbiter> arbiter, AddressArbiter::Create()); + SharedPtr<AddressArbiter> arbiter = AddressArbiter::Create(); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(arbiter))); LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *out_handle); return RESULT_SUCCESS; @@ -355,7 +366,7 @@ static ResultCode SetThreadPriority(Handle handle, s32 priority) { static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { using Kernel::Mutex; - CASCADE_RESULT(SharedPtr<Mutex> mutex, Mutex::Create(initial_locked != 0)); + SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", @@ -423,7 +434,9 @@ static ResultCode QueryMemory(void* info, void* out, u32 addr) { /// Create an event static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { - CASCADE_RESULT(auto evt, Kernel::Event::Create(static_cast<ResetType>(reset_type))); + using Kernel::Event; + + SharedPtr<Event> evt = Kernel::Event::Create(static_cast<ResetType>(reset_type)); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", @@ -433,19 +446,17 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { /// Duplicates a kernel handle static ResultCode DuplicateHandle(Handle* out, Handle handle) { - ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle); - if (out_h.Succeeded()) { - *out = *out_h; - LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out); - } - return out_h.Code(); + CASCADE_RESULT(*out, Kernel::g_handle_table.Duplicate(handle)); + LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out); + return RESULT_SUCCESS; } /// Signals an event static ResultCode SignalEvent(Handle handle) { + using Kernel::Event; LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); - auto evt = Kernel::g_handle_table.Get<Kernel::Event>(handle); + SharedPtr<Event> evt = Kernel::g_handle_table.Get<Kernel::Event>(handle); if (evt == nullptr) return ERR_INVALID_HANDLE; @@ -456,9 +467,10 @@ static ResultCode SignalEvent(Handle handle) { /// Clears an event static ResultCode ClearEvent(Handle handle) { + using Kernel::Event; LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); - auto evt = Kernel::g_handle_table.Get<Kernel::Event>(handle); + SharedPtr<Event> evt = Kernel::g_handle_table.Get<Kernel::Event>(handle); if (evt == nullptr) return ERR_INVALID_HANDLE; @@ -470,7 +482,7 @@ static ResultCode ClearEvent(Handle handle) { static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { using Kernel::Timer; - CASCADE_RESULT(auto timer, Timer::Create(static_cast<ResetType>(reset_type))); + SharedPtr<Timer> timer = Timer::Create(static_cast<ResetType>(reset_type)); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", @@ -528,7 +540,7 @@ static void SleepThread(s64 nanoseconds) { Kernel::WaitCurrentThread_Sleep(); // Create an event to wake the thread up after the specified nanosecond delay has passed - Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nanoseconds); + Kernel::GetCurrentThread()->WakeAfterDelay(nanoseconds); HLE::Reschedule(__func__); } @@ -544,7 +556,7 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 using Kernel::SharedMemory; // TODO(Subv): Implement this function - CASCADE_RESULT(auto shared_memory, SharedMemory::Create()); + SharedPtr<SharedMemory> shared_memory = SharedMemory::Create(); CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr); |