summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp42
-rw-r--r--src/core/hle/kernel/address_arbiter.h27
-rw-r--r--src/core/hle/kernel/event.cpp83
-rw-r--r--src/core/hle/kernel/event.h51
-rw-r--r--src/core/hle/kernel/kernel.h8
-rw-r--r--src/core/hle/kernel/mutex.cpp143
-rw-r--r--src/core/hle/kernel/mutex.h52
-rw-r--r--src/core/hle/kernel/semaphore.cpp65
-rw-r--r--src/core/hle/kernel/semaphore.h57
-rw-r--r--src/core/hle/kernel/shared_memory.cpp73
-rw-r--r--src/core/hle/kernel/shared_memory.h60
-rw-r--r--src/core/hle/kernel/thread.h3
-rw-r--r--src/core/hle/kernel/timer.cpp107
-rw-r--r--src/core/hle/kernel/timer.h69
14 files changed, 360 insertions, 480 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 9e855b0bf..2d01e2ef5 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -15,26 +15,18 @@
namespace Kernel {
-class AddressArbiter : public Object {
-public:
- std::string GetTypeName() const override { return "Arbiter"; }
- std::string GetName() const override { return name; }
+ResultVal<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));
- static const HandleType HANDLE_TYPE = HandleType::AddressArbiter;
- HandleType GetHandleType() const override { return HANDLE_TYPE; }
+ address_arbiter->name = std::move(name);
- std::string name; ///< Name of address arbiter object (optional)
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/// Arbitrate an address
-ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds) {
- AddressArbiter* object = Kernel::g_handle_table.Get<AddressArbiter>(handle).get();
-
- if (object == nullptr)
- return InvalidHandle(ErrorModule::Kernel);
+ return MakeResult<SharedPtr<AddressArbiter>>(std::move(address_arbiter));
+}
+ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value,
+ u64 nanoseconds) {
switch (type) {
// Signal thread(s) waiting for arbitrate address...
@@ -92,20 +84,4 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3
return RESULT_SUCCESS;
}
-/// Create an address arbiter
-AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) {
- AddressArbiter* address_arbiter = new AddressArbiter;
- // TOOD(yuriks): Fix error reporting
- handle = Kernel::g_handle_table.Create(address_arbiter).ValueOr(INVALID_HANDLE);
- address_arbiter->name = name;
- return address_arbiter;
-}
-
-/// Create an address arbiter
-Handle CreateAddressArbiter(const std::string& name) {
- Handle handle;
- CreateAddressArbiter(handle, name);
- return handle;
-}
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 3ffd465a2..638afff9e 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -18,7 +18,6 @@
namespace Kernel {
-/// Address arbitration types
enum class ArbitrationType : u32 {
Signal,
WaitIfLessThan,
@@ -27,10 +26,28 @@ enum class ArbitrationType : u32 {
DecrementAndWaitIfLessThanWithTimeout,
};
-/// Arbitrate an address
-ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds);
+class AddressArbiter final : public Object {
+public:
+ /**
+ * Creates an address arbiter.
+ *
+ * @param name Optional name used for debugging.
+ * @returns The created AddressArbiter.
+ */
+ static ResultVal<SharedPtr<AddressArbiter>> Create(std::string name = "Unknown");
-/// Create an address arbiter
-Handle CreateAddressArbiter(const std::string& name = "Unknown");
+ std::string GetTypeName() const override { return "Arbiter"; }
+ std::string GetName() const override { return name; }
+
+ static const HandleType HANDLE_TYPE = HandleType::AddressArbiter;
+ HandleType GetHandleType() const override { return HANDLE_TYPE; }
+
+ std::string name; ///< Name of address arbiter object (optional)
+
+ ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds);
+
+private:
+ AddressArbiter() = default;
+};
} // namespace FileSys
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index a48125965..d9ad40c6a 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -14,78 +14,37 @@
namespace Kernel {
-class Event : public WaitObject {
-public:
- std::string GetTypeName() const override { return "Event"; }
- std::string GetName() const override { return name; }
-
- static const HandleType HANDLE_TYPE = HandleType::Event;
- HandleType GetHandleType() const override { return HANDLE_TYPE; }
-
- ResetType intitial_reset_type; ///< ResetType specified at Event initialization
- ResetType reset_type; ///< Current ResetType
-
- bool signaled; ///< Whether the event has already been signaled
- std::string name; ///< Name of event (optional)
-
- bool ShouldWait() override {
- return !signaled;
- }
-
- void Acquire() override {
- _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
-
- // Release the event if it's not sticky...
- if (reset_type != RESETTYPE_STICKY)
- signaled = false;
- }
-};
-
-ResultCode SignalEvent(const Handle handle) {
- Event* evt = g_handle_table.Get<Event>(handle).get();
- if (evt == nullptr)
- return InvalidHandle(ErrorModule::Kernel);
-
- evt->signaled = true;
- evt->WakeupAllWaitingThreads();
-
- return RESULT_SUCCESS;
-}
-
-ResultCode ClearEvent(Handle handle) {
- Event* evt = g_handle_table.Get<Event>(handle).get();
- if (evt == nullptr)
- return InvalidHandle(ErrorModule::Kernel);
+ResultVal<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 RESULT_SUCCESS;
+ return MakeResult<SharedPtr<Event>>(evt);
}
-/**
- * Creates an event
- * @param handle Reference to handle for the newly created mutex
- * @param reset_type ResetType describing how to create event
- * @param name Optional name of event
- * @return Newly created Event object
- */
-Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) {
- Event* evt = new Event;
+bool Event::ShouldWait() {
+ return !signaled;
+}
- // TOOD(yuriks): Fix error reporting
- handle = Kernel::g_handle_table.Create(evt).ValueOr(INVALID_HANDLE);
+void Event::Acquire() {
+ _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
- evt->signaled = false;
- evt->reset_type = evt->intitial_reset_type = reset_type;
- evt->name = name;
+ // Release the event if it's not sticky...
+ if (reset_type != RESETTYPE_STICKY)
+ signaled = false;
+}
- return evt;
+void Event::Signal() {
+ signaled = true;
+ WakeupAllWaitingThreads();
}
-Handle CreateEvent(const ResetType reset_type, const std::string& name) {
- Handle handle;
- Event* evt = CreateEvent(handle, reset_type, name);
- return handle;
+void Event::Clear() {
+ signaled = false;
}
} // namespace
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index c08b12ee1..2c3e6b14e 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -11,26 +11,35 @@
namespace Kernel {
-/**
- * Signals an event
- * @param handle Handle to event to signal
- * @return Result of operation, 0 on success, otherwise error code
- */
-ResultCode SignalEvent(const Handle handle);
-
-/**
- * Clears an event
- * @param handle Handle to event to clear
- * @return Result of operation, 0 on success, otherwise error code
- */
-ResultCode ClearEvent(Handle handle);
-
-/**
- * Creates an event
- * @param reset_type ResetType describing how to create event
- * @param name Optional name of event
- * @return Handle to newly created Event object
- */
-Handle CreateEvent(const ResetType reset_type, const std::string& name="Unknown");
+class Event final : public WaitObject {
+public:
+ /**
+ * Creates an event
+ * @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");
+
+ std::string GetTypeName() const override { return "Event"; }
+ std::string GetName() const override { return name; }
+
+ static const HandleType HANDLE_TYPE = HandleType::Event;
+ HandleType GetHandleType() const override { return HANDLE_TYPE; }
+
+ ResetType intitial_reset_type; ///< ResetType specified at Event initialization
+ ResetType reset_type; ///< Current ResetType
+
+ bool signaled; ///< Whether the event has already been signaled
+ std::string name; ///< Name of event (optional)
+
+ bool ShouldWait() override;
+ void Acquire() override;
+
+ void Signal();
+ void Clear();
+
+private:
+ Event() = default;
+};
} // namespace
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 3828efbea..9860479ac 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -16,6 +16,11 @@
typedef u32 Handle;
typedef s32 Result;
+// TODO: It would be nice to eventually replace these with strong types that prevent accidental
+// conversion between each other.
+typedef u32 VAddr; ///< Represents a pointer in the userspace virtual address space.
+typedef u32 PAddr; ///< Represents a pointer in the ARM11 physical address space.
+
const Handle INVALID_HANDLE = 0;
namespace Kernel {
@@ -26,7 +31,8 @@ class Thread;
const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
ErrorSummary::OutOfResource, ErrorLevel::Temporary);
// TOOD: Verify code
-const ResultCode ERR_INVALID_HANDLE = InvalidHandle(ErrorModule::Kernel);
+const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel,
+ ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
enum KernelHandle : Handle {
CurrentThread = 0xFFFF8000,
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index cd05a1397..acf484659 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -13,59 +13,30 @@
namespace Kernel {
-class Mutex : public WaitObject {
-public:
- std::string GetTypeName() const override { return "Mutex"; }
- std::string GetName() const override { return name; }
-
- static const HandleType HANDLE_TYPE = HandleType::Mutex;
- HandleType GetHandleType() const override { return HANDLE_TYPE; }
-
- bool initial_locked; ///< Initial lock state when mutex was created
- bool locked; ///< Current locked state
- std::string name; ///< Name of mutex (optional)
- SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
-
- bool ShouldWait() override;
- void Acquire() override;
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap;
static MutexMap g_mutex_held_locks;
/**
- * Acquires the specified mutex for the specified thread
- * @param mutex Mutex that is to be acquired
- * @param thread Thread that will acquire the mutex
- */
-void MutexAcquireLock(Mutex* mutex, Thread* thread) {
- g_mutex_held_locks.insert(std::make_pair(thread, mutex));
- mutex->holding_thread = thread;
-}
-
-/**
* Resumes a thread waiting for the specified mutex
* @param mutex The mutex that some thread is waiting on
*/
-void ResumeWaitingThread(Mutex* mutex) {
+static void ResumeWaitingThread(Mutex* mutex) {
+ // Reset mutex lock thread handle, nothing is waiting
+ mutex->locked = false;
+ mutex->holding_thread = nullptr;
+
// Find the next waiting thread for the mutex...
auto next_thread = mutex->WakeupNextThread();
if (next_thread != nullptr) {
- MutexAcquireLock(mutex, next_thread);
- } else {
- // Reset mutex lock thread handle, nothing is waiting
- mutex->locked = false;
- mutex->holding_thread = nullptr;
+ mutex->Acquire(next_thread);
}
}
void ReleaseThreadMutexes(Thread* thread) {
- auto locked = g_mutex_held_locks.equal_range(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.first; iter != locked.second; ++iter) {
+ for (auto iter = locked_range.first; iter != locked_range.second; ++iter) {
ResumeWaitingThread(iter->second.get());
}
@@ -73,72 +44,21 @@ void ReleaseThreadMutexes(Thread* thread) {
g_mutex_held_locks.erase(thread);
}
-bool ReleaseMutex(Mutex* mutex) {
- if (mutex->locked) {
- auto locked = g_mutex_held_locks.equal_range(mutex->holding_thread);
-
- for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
- if (iter->second == mutex) {
- g_mutex_held_locks.erase(iter);
- break;
- }
- }
-
- ResumeWaitingThread(mutex);
- }
- return true;
-}
+ResultVal<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));
-/**
- * Releases a mutex
- * @param handle Handle to mutex to release
- */
-ResultCode ReleaseMutex(Handle handle) {
- Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle).get();
- if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel);
-
- if (!ReleaseMutex(mutex)) {
- // TODO(yuriks): Verify error code, this one was pulled out of thin air. I'm not even sure
- // what error condition this is supposed to be signaling.
- return ResultCode(ErrorDescription::AlreadyDone, ErrorModule::Kernel,
- ErrorSummary::NothingHappened, ErrorLevel::Temporary);
- }
- return RESULT_SUCCESS;
-}
-
-/**
- * Creates a mutex
- * @param handle Reference to handle for the newly created mutex
- * @param initial_locked Specifies if the mutex should be locked initially
- * @param name Optional name of mutex
- * @return Pointer to new Mutex object
- */
-Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) {
- Mutex* mutex = new Mutex;
- // TODO(yuriks): Fix error reporting
- handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE);
-
- mutex->locked = mutex->initial_locked = initial_locked;
- mutex->name = name;
+ mutex->initial_locked = initial_locked;
+ mutex->locked = false;
+ mutex->name = std::move(name);
mutex->holding_thread = nullptr;
// Acquire mutex with current thread if initialized as locked...
- if (mutex->locked)
- MutexAcquireLock(mutex, GetCurrentThread());
-
- return mutex;
-}
+ if (initial_locked)
+ mutex->Acquire();
-/**
- * Creates a mutex
- * @param initial_locked Specifies if the mutex should be locked initially
- * @param name Optional name of mutex
- * @return Handle to newly created object
- */
-Handle CreateMutex(bool initial_locked, const std::string& name) {
- Handle handle;
- Mutex* mutex = CreateMutex(handle, initial_locked, name);
- return handle;
+ return MakeResult<SharedPtr<Mutex>>(mutex);
}
bool Mutex::ShouldWait() {
@@ -146,9 +66,34 @@ bool Mutex::ShouldWait() {
}
void Mutex::Acquire() {
+ Acquire(GetCurrentThread());
+}
+
+void Mutex::Acquire(Thread* thread) {
_assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
+ if (locked)
+ return;
+
locked = true;
- MutexAcquireLock(this, GetCurrentThread());
+
+ g_mutex_held_locks.insert(std::make_pair(thread, this));
+ holding_thread = 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;
+ }
+ }
+
+ ResumeWaitingThread(this);
}
} // namespace
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index bb8778c98..1e69528f1 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -4,25 +4,51 @@
#pragma once
+#include <string>
+
#include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
namespace Kernel {
-/**
- * Releases a mutex
- * @param handle Handle to mutex to release
- */
-ResultCode ReleaseMutex(Handle handle);
-
-/**
- * Creates a mutex
- * @param initial_locked Specifies if the mutex should be locked initially
- * @param name Optional name of mutex
- * @return Handle to newly created object
- */
-Handle CreateMutex(bool initial_locked, const std::string& name="Unknown");
+class Thread;
+
+class Mutex final : public WaitObject {
+public:
+ /**
+ * Creates a mutex.
+ * @param initial_locked Specifies if the mutex should be locked initially
+ * @param name Optional name of mutex
+ * @return Pointer to new Mutex object
+ */
+ static ResultVal<SharedPtr<Mutex>> Create(bool initial_locked, std::string name = "Unknown");
+
+ std::string GetTypeName() const override { return "Mutex"; }
+ std::string GetName() const override { return name; }
+
+ static const HandleType HANDLE_TYPE = HandleType::Mutex;
+ HandleType GetHandleType() const override { return HANDLE_TYPE; }
+
+ bool initial_locked; ///< Initial lock state when mutex was created
+ bool locked; ///< Current locked state
+ std::string name; ///< Name of mutex (optional)
+ SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
+
+ bool ShouldWait() override;
+ void Acquire() override;
+
+ /**
+ * Acquires the specified mutex for the specified thread
+ * @param mutex Mutex that is to be acquired
+ * @param thread Thread that will acquire the mutex
+ */
+ void Acquire(Thread* thread);
+ void Release();
+
+private:
+ Mutex() = default;
+};
/**
* Releases all the mutexes held by the specified thread
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 135d8fb2a..a9e406ef4 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <queue>
-
#include "common/common.h"
#include "core/hle/kernel/kernel.h"
@@ -12,69 +10,50 @@
namespace Kernel {
-class Semaphore : public WaitObject {
-public:
- std::string GetTypeName() const override { return "Semaphore"; }
- std::string GetName() const override { return name; }
-
- static const HandleType HANDLE_TYPE = HandleType::Semaphore;
- HandleType GetHandleType() const override { return HANDLE_TYPE; }
-
- s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
- s32 available_count; ///< Number of free slots left in the semaphore
- std::string name; ///< Name of semaphore (optional)
-
- bool ShouldWait() override {
- return available_count <= 0;
- }
-
- void Acquire() override {
- _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
- --available_count;
- }
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-ResultCode CreateSemaphore(Handle* handle, s32 initial_count,
- s32 max_count, const std::string& name) {
+ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
+ std::string name) {
if (initial_count > max_count)
return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
ErrorSummary::WrongArgument, ErrorLevel::Permanent);
- Semaphore* semaphore = new Semaphore;
- // TOOD(yuriks): Fix error reporting
- *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE);
+ 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
semaphore->max_count = max_count;
semaphore->available_count = initial_count;
- semaphore->name = name;
+ semaphore->name = std::move(name);
- return RESULT_SUCCESS;
+ return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore));
}
-ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
- Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle).get();
- if (semaphore == nullptr)
- return InvalidHandle(ErrorModule::Kernel);
+bool Semaphore::ShouldWait() {
+ return available_count <= 0;
+}
+
+void Semaphore::Acquire() {
+ _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
+ --available_count;
+}
- if (semaphore->max_count - semaphore->available_count < release_count)
+ResultVal<s32> Semaphore::Release(s32 release_count) {
+ if (max_count - available_count < release_count)
return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,
ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
- *count = semaphore->available_count;
- semaphore->available_count += release_count;
+ s32 previous_count = available_count;
+ available_count += release_count;
// Notify some of the threads that the semaphore has been released
// stop once the semaphore is full again or there are no more waiting threads
- while (!semaphore->ShouldWait() && semaphore->WakeupNextThread() != nullptr) {
- semaphore->Acquire();
+ while (!ShouldWait() && WakeupNextThread() != nullptr) {
+ Acquire();
}
- return RESULT_SUCCESS;
+ return MakeResult<s32>(previous_count);
}
} // namespace
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index 8644ecf0c..9bb404ab6 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -4,29 +4,50 @@
#pragma once
+#include <queue>
+#include <string>
+
#include "common/common_types.h"
#include "core/hle/kernel/kernel.h"
namespace Kernel {
-/**
- * Creates a semaphore.
- * @param handle Pointer to the handle of the newly created object
- * @param initial_count Number of slots reserved for other threads
- * @param max_count Maximum number of slots the semaphore can have
- * @param name Optional name of semaphore
- * @return ResultCode of the error
- */
-ResultCode CreateSemaphore(Handle* handle, s32 initial_count, s32 max_count, const std::string& name = "Unknown");
-
-/**
- * Releases a certain number of slots from a semaphore.
- * @param count The number of free slots the semaphore had before this call
- * @param handle The handle of the semaphore to release
- * @param release_count The number of slots to release
- * @return ResultCode of the error
- */
-ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count);
+class Semaphore final : public WaitObject {
+public:
+ /**
+ * Creates a semaphore.
+ * @param handle Pointer to the handle of the newly created object
+ * @param initial_count Number of slots reserved for other threads
+ * @param max_count Maximum number of slots the semaphore can have
+ * @param name Optional name of semaphore
+ * @return The created semaphore
+ */
+ static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count,
+ std::string name = "Unknown");
+
+ std::string GetTypeName() const override { return "Semaphore"; }
+ std::string GetName() const override { return name; }
+
+ static const HandleType HANDLE_TYPE = HandleType::Semaphore;
+ HandleType GetHandleType() const override { return HANDLE_TYPE; }
+
+ s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
+ s32 available_count; ///< Number of free slots left in the semaphore
+ std::string name; ///< Name of semaphore (optional)
+
+ bool ShouldWait() override;
+ void Acquire() override;
+
+ /**
+ * Releases a certain number of slots from a semaphore.
+ * @param release_count The number of slots to release
+ * @return The number of free slots the semaphore had before this call
+ */
+ ResultVal<s32> Release(s32 release_count);
+
+private:
+ Semaphore() = default;
+};
} // namespace
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 5368e4728..536d134b0 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -9,76 +9,39 @@
namespace Kernel {
-class SharedMemory : public Object {
-public:
- std::string GetTypeName() const override { return "SharedMemory"; }
+ResultVal<SharedPtr<SharedMemory>> SharedMemory::Create(std::string name) {
+ SharedPtr<SharedMemory> shared_memory(new SharedMemory);
- static const HandleType HANDLE_TYPE = HandleType::SharedMemory;
- HandleType GetHandleType() const override { return HANDLE_TYPE; }
+ // TOOD(yuriks): Don't create Handle (see Thread::Create())
+ CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(shared_memory));
- u32 base_address; ///< Address of shared memory block in RAM
- MemoryPermission permissions; ///< Permissions of shared memory block (SVC field)
- MemoryPermission other_permissions; ///< Other permissions of shared memory block (SVC field)
- std::string name; ///< Name of shared memory object (optional)
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Creates a shared memory object
- * @param handle Handle of newly created shared memory object
- * @param name Name of shared memory object
- * @return Pointer to newly created shared memory object
- */
-SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) {
- SharedMemory* shared_memory = new SharedMemory;
- // TOOD(yuriks): Fix error reporting
- handle = Kernel::g_handle_table.Create(shared_memory).ValueOr(INVALID_HANDLE);
- shared_memory->name = name;
- return shared_memory;
+ shared_memory->name = std::move(name);
+ return MakeResult<SharedPtr<SharedMemory>>(std::move(shared_memory));
}
-Handle CreateSharedMemory(const std::string& name) {
- Handle handle;
- CreateSharedMemory(handle, name);
- return handle;
-}
-
-/**
- * Maps a shared memory block to an address in system memory
- * @param handle Shared memory block handle
- * @param address Address in system memory to map shared memory block to
- * @param permissions Memory block map permissions (specified by SVC field)
- * @param other_permissions Memory block map other permissions (specified by SVC field)
- * @return Result of operation, 0 on success, otherwise error code
- */
-ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
- MemoryPermission other_permissions) {
+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_SVC, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!",
- handle, address);
+ LOG_ERROR(Kernel, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!",
+ GetHandle(), address);
+ // TODO: Verify error code with hardware
return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
}
- SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle).get();
- if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
- shared_memory->base_address = address;
- shared_memory->permissions = permissions;
- shared_memory->other_permissions = other_permissions;
+ base_address = address;
+ permissions = permissions;
+ other_permissions = other_permissions;
return RESULT_SUCCESS;
}
-ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) {
- SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle).get();
- if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
-
- if (0 != shared_memory->base_address)
- return MakeResult<u8*>(Memory::GetPointer(shared_memory->base_address + offset));
+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!", handle);
+ LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", GetHandle());
// 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 bb65c7ccd..f9ae23e93 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -23,29 +23,41 @@ enum class MemoryPermission : u32 {
DontCare = (1u << 28)
};
-/**
- * Creates a shared memory object
- * @param name Optional name of shared memory object
- * @return Handle of newly created shared memory object
- */
-Handle CreateSharedMemory(const std::string& name="Unknown");
-
-/**
- * Maps a shared memory block to an address in system memory
- * @param handle Shared memory block handle
- * @param address Address in system memory to map shared memory block to
- * @param permissions Memory block map permissions (specified by SVC field)
- * @param other_permissions Memory block map other permissions (specified by SVC field)
- */
-ResultCode MapSharedMemory(Handle handle, u32 address, MemoryPermission permissions,
- MemoryPermission other_permissions);
-
-/**
- * Gets a pointer to the shared memory block
- * @param handle Shared memory block handle
- * @param offset Offset from the start of the shared memory block to get pointer
- * @return Pointer to the shared memory block from the specified offset
- */
-ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset);
+class SharedMemory final : public Object {
+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");
+
+ std::string GetTypeName() const override { return "SharedMemory"; }
+
+ static const HandleType HANDLE_TYPE = HandleType::SharedMemory;
+ HandleType GetHandleType() const override { return HANDLE_TYPE; }
+
+ /**
+ * Maps a shared memory block to an address in system memory
+ * @param address Address in system memory to map shared memory block to
+ * @param permissions Memory block map permissions (specified by SVC field)
+ * @param other_permissions Memory block map other permissions (specified by SVC field)
+ */
+ ResultCode Map(VAddr address, MemoryPermission permissions, MemoryPermission other_permissions);
+
+ /**
+ * Gets a pointer to the shared memory block
+ * @param offset Offset from the start of the shared memory block to get pointer
+ * @return Pointer to the shared memory block from the specified offset
+ */
+ ResultVal<u8*> GetPointer(u32 offset = 0);
+
+ VAddr base_address; ///< Address of shared memory block in RAM
+ MemoryPermission permissions; ///< Permissions of shared memory block (SVC field)
+ MemoryPermission other_permissions; ///< Other permissions of shared memory block (SVC field)
+ std::string name; ///< Name of shared memory object (optional)
+
+private:
+ SharedMemory() = default;
+};
} // namespace
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 5fab1ab58..d6299364a 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -40,7 +40,7 @@ enum ThreadStatus {
namespace Kernel {
-class Thread : public WaitObject {
+class Thread final : public WaitObject {
public:
static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size);
@@ -115,7 +115,6 @@ public:
bool idle = false;
private:
-
Thread() = default;
};
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index ec0b2c323..503a5d2ce 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -13,75 +13,54 @@
namespace Kernel {
-class Timer : public WaitObject {
-public:
- std::string GetTypeName() const override { return "Timer"; }
- std::string GetName() const override { return name; }
-
- static const HandleType HANDLE_TYPE = HandleType::Timer;
- HandleType GetHandleType() const override { return HANDLE_TYPE; }
-
- ResetType reset_type; ///< The ResetType of this timer
-
- bool signaled; ///< Whether the timer has been signaled or not
- std::string name; ///< Name of timer (optional)
-
- u64 initial_delay; ///< The delay until the timer fires for the first time
- u64 interval_delay; ///< The delay until the timer fires after the first time
-
- bool ShouldWait() override {
- return !signaled;
- }
-
- void Acquire() override {
- _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
- }
-};
-
-/**
- * Creates a timer.
- * @param handle Reference to handle for the newly created timer
- * @param reset_type ResetType describing how to create timer
- * @param name Optional name of timer
- * @return Newly created Timer object
- */
-Timer* CreateTimer(Handle& handle, const ResetType reset_type, const std::string& name) {
- Timer* timer = new Timer;
+/// The event type of the generic timer callback event
+static int timer_callback_event_type = -1;
- handle = Kernel::g_handle_table.Create(timer).ValueOr(INVALID_HANDLE);
+ResultVal<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 = name;
+ timer->name = std::move(name);
timer->initial_delay = 0;
timer->interval_delay = 0;
- return timer;
+ return MakeResult<SharedPtr<Timer>>(timer);
}
-ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name) {
- CreateTimer(*handle, reset_type, name);
- return RESULT_SUCCESS;
+bool Timer::ShouldWait() {
+ return !signaled;
}
-ResultCode ClearTimer(Handle handle) {
- SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
-
- if (timer == nullptr)
- return InvalidHandle(ErrorModule::Kernel);
+void Timer::Acquire() {
+ _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
+}
- timer->signaled = false;
- return RESULT_SUCCESS;
+void Timer::Set(s64 initial, s64 interval) {
+ 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());
}
-/// The event type of the generic timer callback event
-static int TimerCallbackEventType = -1;
+void Timer::Cancel() {
+ CoreTiming::UnscheduleEvent(timer_callback_event_type, GetHandle());
+}
+
+void Timer::Clear() {
+ signaled = false;
+}
/// 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);
if (timer == nullptr) {
- LOG_CRITICAL(Kernel, "Callback fired for invalid timer %u", timer_handle);
+ LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle);
return;
}
@@ -99,36 +78,12 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
// Reschedule the timer with the interval delay
u64 interval_microseconds = timer->interval_delay / 1000;
CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
- TimerCallbackEventType, timer_handle);
+ timer_callback_event_type, timer_handle);
}
}
-ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
- SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
-
- if (timer == nullptr)
- return InvalidHandle(ErrorModule::Kernel);
-
- timer->initial_delay = initial;
- timer->interval_delay = interval;
-
- u64 initial_microseconds = initial / 1000;
- CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), TimerCallbackEventType, handle);
- return RESULT_SUCCESS;
-}
-
-ResultCode CancelTimer(Handle handle) {
- SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
-
- if (timer == nullptr)
- return InvalidHandle(ErrorModule::Kernel);
-
- CoreTiming::UnscheduleEvent(TimerCallbackEventType, handle);
- return RESULT_SUCCESS;
-}
-
void TimersInit() {
- TimerCallbackEventType = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
+ timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
}
void TimersShutdown() {
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index 8170e82d4..c45e79954 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -11,37 +11,50 @@
namespace Kernel {
-/**
- * Cancels a timer
- * @param handle Handle of the timer to cancel
- */
-ResultCode CancelTimer(Handle handle);
-
-/**
- * Starts a timer with the specified initial delay and interval
- * @param handle Handle of the timer to start
- * @param initial Delay until the timer is first fired
- * @param interval Delay until the timer is fired after the first time
- */
-ResultCode SetTimer(Handle handle, s64 initial, s64 interval);
-
-/**
- * Clears a timer
- * @param handle Handle of the timer to clear
- */
-ResultCode ClearTimer(Handle handle);
-
-/**
- * Creates a timer
- * @param handle Handle to the newly created Timer object
- * @param reset_type ResetType describing how to create the timer
- * @param name Optional name of timer
- * @return ResultCode of the error
- */
-ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name="Unknown");
+class Timer final : public WaitObject {
+public:
+ /**
+ * Creates a timer
+ * @param reset_type ResetType describing how to create the timer
+ * @param name Optional name of timer
+ * @return The created Timer
+ */
+ static ResultVal<SharedPtr<Timer>> Create(ResetType reset_type, std::string name = "Unknown");
+
+ std::string GetTypeName() const override { return "Timer"; }
+ std::string GetName() const override { return name; }
+
+ static const HandleType HANDLE_TYPE = HandleType::Timer;
+ HandleType GetHandleType() const override { return HANDLE_TYPE; }
+
+ ResetType reset_type; ///< The ResetType of this timer
+
+ bool signaled; ///< Whether the timer has been signaled or not
+ std::string name; ///< Name of timer (optional)
+
+ u64 initial_delay; ///< The delay until the timer fires for the first time
+ u64 interval_delay; ///< The delay until the timer fires after the first time
+
+ bool ShouldWait() override;
+ void Acquire() override;
+
+ /**
+ * Starts the timer, with the specified initial delay and interval.
+ * @param initial Delay until the timer is first fired
+ * @param interval Delay until the timer is fired after the first time
+ */
+ void Set(s64 initial, s64 interval);
+
+ void Cancel();
+ void Clear();
+
+private:
+ Timer() = default;
+};
/// Initializes the required variables for timers
void TimersInit();
/// Tears down the timer variables
void TimersShutdown();
+
} // namespace