summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Tony Wasserka2015-01-30 15:00:17 +0100
committerGravatar Tony Wasserka2015-01-30 15:00:17 +0100
commit28702cbfeb1fe21109f8b1efa189785594319b78 (patch)
tree64e4b1ec43b7699fe1a6ab1be1c688b6d63c0d75 /src/core/hle/kernel
parentMerge pull request #412 from purpasmart96/svc_table_cleanup (diff)
parentKernel: Mark all appropriate kernel objects as "final" (diff)
downloadyuzu-28702cbfeb1fe21109f8b1efa189785594319b78.tar.gz
yuzu-28702cbfeb1fe21109f8b1efa189785594319b78.tar.xz
yuzu-28702cbfeb1fe21109f8b1efa189785594319b78.zip
Merge pull request #503 from yuriks/kernel-lifetime4
Kernel Lifetime Reform Pt. 4
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 @@
15 15
16namespace Kernel { 16namespace Kernel {
17 17
18class AddressArbiter : public Object { 18ResultVal<SharedPtr<AddressArbiter>> AddressArbiter::Create(std::string name) {
19public: 19 SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter);
20 std::string GetTypeName() const override { return "Arbiter"; } 20 // TOOD(yuriks): Don't create Handle (see Thread::Create())
21 std::string GetName() const override { return name; } 21 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(address_arbiter));
22 22
23 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter; 23 address_arbiter->name = std::move(name);
24 HandleType GetHandleType() const override { return HANDLE_TYPE; }
25 24
26 std::string name; ///< Name of address arbiter object (optional) 25 return MakeResult<SharedPtr<AddressArbiter>>(std::move(address_arbiter));
27}; 26}
28
29////////////////////////////////////////////////////////////////////////////////////////////////////
30
31/// Arbitrate an address
32ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds) {
33 AddressArbiter* object = Kernel::g_handle_table.Get<AddressArbiter>(handle).get();
34
35 if (object == nullptr)
36 return InvalidHandle(ErrorModule::Kernel);
37 27
28ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value,
29 u64 nanoseconds) {
38 switch (type) { 30 switch (type) {
39 31
40 // Signal thread(s) waiting for arbitrate address... 32 // Signal thread(s) waiting for arbitrate address...
@@ -92,20 +84,4 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3
92 return RESULT_SUCCESS; 84 return RESULT_SUCCESS;
93} 85}
94 86
95/// Create an address arbiter
96AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) {
97 AddressArbiter* address_arbiter = new AddressArbiter;
98 // TOOD(yuriks): Fix error reporting
99 handle = Kernel::g_handle_table.Create(address_arbiter).ValueOr(INVALID_HANDLE);
100 address_arbiter->name = name;
101 return address_arbiter;
102}
103
104/// Create an address arbiter
105Handle CreateAddressArbiter(const std::string& name) {
106 Handle handle;
107 CreateAddressArbiter(handle, name);
108 return handle;
109}
110
111} // namespace Kernel 87} // 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 @@
18 18
19namespace Kernel { 19namespace Kernel {
20 20
21/// Address arbitration types
22enum class ArbitrationType : u32 { 21enum class ArbitrationType : u32 {
23 Signal, 22 Signal,
24 WaitIfLessThan, 23 WaitIfLessThan,
@@ -27,10 +26,28 @@ enum class ArbitrationType : u32 {
27 DecrementAndWaitIfLessThanWithTimeout, 26 DecrementAndWaitIfLessThanWithTimeout,
28}; 27};
29 28
30/// Arbitrate an address 29class AddressArbiter final : public Object {
31ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds); 30public:
31 /**
32 * Creates an address arbiter.
33 *
34 * @param name Optional name used for debugging.
35 * @returns The created AddressArbiter.
36 */
37 static ResultVal<SharedPtr<AddressArbiter>> Create(std::string name = "Unknown");
32 38
33/// Create an address arbiter 39 std::string GetTypeName() const override { return "Arbiter"; }
34Handle CreateAddressArbiter(const std::string& name = "Unknown"); 40 std::string GetName() const override { return name; }
41
42 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter;
43 HandleType GetHandleType() const override { return HANDLE_TYPE; }
44
45 std::string name; ///< Name of address arbiter object (optional)
46
47 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds);
48
49private:
50 AddressArbiter() = default;
51};
35 52
36} // namespace FileSys 53} // 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 @@
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17class Event : public WaitObject { 17ResultVal<SharedPtr<Event>> Event::Create(ResetType reset_type, std::string name) {
18public: 18 SharedPtr<Event> evt(new Event);
19 std::string GetTypeName() const override { return "Event"; } 19 // TOOD(yuriks): Don't create Handle (see Thread::Create())
20 std::string GetName() const override { return name; } 20 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(evt));
21
22 static const HandleType HANDLE_TYPE = HandleType::Event;
23 HandleType GetHandleType() const override { return HANDLE_TYPE; }
24
25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization
26 ResetType reset_type; ///< Current ResetType
27
28 bool signaled; ///< Whether the event has already been signaled
29 std::string name; ///< Name of event (optional)
30
31 bool ShouldWait() override {
32 return !signaled;
33 }
34
35 void Acquire() override {
36 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
37
38 // Release the event if it's not sticky...
39 if (reset_type != RESETTYPE_STICKY)
40 signaled = false;
41 }
42};
43
44ResultCode SignalEvent(const Handle handle) {
45 Event* evt = g_handle_table.Get<Event>(handle).get();
46 if (evt == nullptr)
47 return InvalidHandle(ErrorModule::Kernel);
48
49 evt->signaled = true;
50 evt->WakeupAllWaitingThreads();
51
52 return RESULT_SUCCESS;
53}
54
55ResultCode ClearEvent(Handle handle) {
56 Event* evt = g_handle_table.Get<Event>(handle).get();
57 if (evt == nullptr)
58 return InvalidHandle(ErrorModule::Kernel);
59 21
60 evt->signaled = false; 22 evt->signaled = false;
23 evt->reset_type = evt->intitial_reset_type = reset_type;
24 evt->name = std::move(name);
61 25
62 return RESULT_SUCCESS; 26 return MakeResult<SharedPtr<Event>>(evt);
63} 27}
64 28
65/** 29bool Event::ShouldWait() {
66 * Creates an event 30 return !signaled;
67 * @param handle Reference to handle for the newly created mutex 31}
68 * @param reset_type ResetType describing how to create event
69 * @param name Optional name of event
70 * @return Newly created Event object
71 */
72Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) {
73 Event* evt = new Event;
74 32
75 // TOOD(yuriks): Fix error reporting 33void Event::Acquire() {
76 handle = Kernel::g_handle_table.Create(evt).ValueOr(INVALID_HANDLE); 34 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
77 35
78 evt->signaled = false; 36 // Release the event if it's not sticky...
79 evt->reset_type = evt->intitial_reset_type = reset_type; 37 if (reset_type != RESETTYPE_STICKY)
80 evt->name = name; 38 signaled = false;
39}
81 40
82 return evt; 41void Event::Signal() {
42 signaled = true;
43 WakeupAllWaitingThreads();
83} 44}
84 45
85Handle CreateEvent(const ResetType reset_type, const std::string& name) { 46void Event::Clear() {
86 Handle handle; 47 signaled = false;
87 Event* evt = CreateEvent(handle, reset_type, name);
88 return handle;
89} 48}
90 49
91} // namespace 50} // 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 @@
11 11
12namespace Kernel { 12namespace Kernel {
13 13
14/** 14class Event final : public WaitObject {
15 * Signals an event 15public:
16 * @param handle Handle to event to signal 16 /**
17 * @return Result of operation, 0 on success, otherwise error code 17 * Creates an event
18 */ 18 * @param reset_type ResetType describing how to create event
19ResultCode SignalEvent(const Handle handle); 19 * @param name Optional name of event
20 20 */
21/** 21 static ResultVal<SharedPtr<Event>> Create(ResetType reset_type, std::string name = "Unknown");
22 * Clears an event 22
23 * @param handle Handle to event to clear 23 std::string GetTypeName() const override { return "Event"; }
24 * @return Result of operation, 0 on success, otherwise error code 24 std::string GetName() const override { return name; }
25 */ 25
26ResultCode ClearEvent(Handle handle); 26 static const HandleType HANDLE_TYPE = HandleType::Event;
27 27 HandleType GetHandleType() const override { return HANDLE_TYPE; }
28/** 28
29 * Creates an event 29 ResetType intitial_reset_type; ///< ResetType specified at Event initialization
30 * @param reset_type ResetType describing how to create event 30 ResetType reset_type; ///< Current ResetType
31 * @param name Optional name of event 31
32 * @return Handle to newly created Event object 32 bool signaled; ///< Whether the event has already been signaled
33 */ 33 std::string name; ///< Name of event (optional)
34Handle CreateEvent(const ResetType reset_type, const std::string& name="Unknown"); 34
35 bool ShouldWait() override;
36 void Acquire() override;
37
38 void Signal();
39 void Clear();
40
41private:
42 Event() = default;
43};
35 44
36} // namespace 45} // 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 @@
16typedef u32 Handle; 16typedef u32 Handle;
17typedef s32 Result; 17typedef s32 Result;
18 18
19// TODO: It would be nice to eventually replace these with strong types that prevent accidental
20// conversion between each other.
21typedef u32 VAddr; ///< Represents a pointer in the userspace virtual address space.
22typedef u32 PAddr; ///< Represents a pointer in the ARM11 physical address space.
23
19const Handle INVALID_HANDLE = 0; 24const Handle INVALID_HANDLE = 0;
20 25
21namespace Kernel { 26namespace Kernel {
@@ -26,7 +31,8 @@ class Thread;
26const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel, 31const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
27 ErrorSummary::OutOfResource, ErrorLevel::Temporary); 32 ErrorSummary::OutOfResource, ErrorLevel::Temporary);
28// TOOD: Verify code 33// TOOD: Verify code
29const ResultCode ERR_INVALID_HANDLE = InvalidHandle(ErrorModule::Kernel); 34const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel,
35 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
30 36
31enum KernelHandle : Handle { 37enum KernelHandle : Handle {
32 CurrentThread = 0xFFFF8000, 38 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 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16class Mutex : public WaitObject {
17public:
18 std::string GetTypeName() const override { return "Mutex"; }
19 std::string GetName() const override { return name; }
20
21 static const HandleType HANDLE_TYPE = HandleType::Mutex;
22 HandleType GetHandleType() const override { return HANDLE_TYPE; }
23
24 bool initial_locked; ///< Initial lock state when mutex was created
25 bool locked; ///< Current locked state
26 std::string name; ///< Name of mutex (optional)
27 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
28
29 bool ShouldWait() override;
30 void Acquire() override;
31};
32
33////////////////////////////////////////////////////////////////////////////////////////////////////
34
35typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap; 16typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap;
36static MutexMap g_mutex_held_locks; 17static MutexMap g_mutex_held_locks;
37 18
38/** 19/**
39 * Acquires the specified mutex for the specified thread
40 * @param mutex Mutex that is to be acquired
41 * @param thread Thread that will acquire the mutex
42 */
43void MutexAcquireLock(Mutex* mutex, Thread* thread) {
44 g_mutex_held_locks.insert(std::make_pair(thread, mutex));
45 mutex->holding_thread = thread;
46}
47
48/**
49 * Resumes a thread waiting for the specified mutex 20 * Resumes a thread waiting for the specified mutex
50 * @param mutex The mutex that some thread is waiting on 21 * @param mutex The mutex that some thread is waiting on
51 */ 22 */
52void ResumeWaitingThread(Mutex* mutex) { 23static void ResumeWaitingThread(Mutex* mutex) {
24 // Reset mutex lock thread handle, nothing is waiting
25 mutex->locked = false;
26 mutex->holding_thread = nullptr;
27
53 // Find the next waiting thread for the mutex... 28 // Find the next waiting thread for the mutex...
54 auto next_thread = mutex->WakeupNextThread(); 29 auto next_thread = mutex->WakeupNextThread();
55 if (next_thread != nullptr) { 30 if (next_thread != nullptr) {
56 MutexAcquireLock(mutex, next_thread); 31 mutex->Acquire(next_thread);
57 } else {
58 // Reset mutex lock thread handle, nothing is waiting
59 mutex->locked = false;
60 mutex->holding_thread = nullptr;
61 } 32 }
62} 33}
63 34
64void ReleaseThreadMutexes(Thread* thread) { 35void ReleaseThreadMutexes(Thread* thread) {
65 auto locked = g_mutex_held_locks.equal_range(thread); 36 auto locked_range = g_mutex_held_locks.equal_range(thread);
66 37
67 // Release every mutex that the thread holds, and resume execution on the waiting threads 38 // Release every mutex that the thread holds, and resume execution on the waiting threads
68 for (auto iter = locked.first; iter != locked.second; ++iter) { 39 for (auto iter = locked_range.first; iter != locked_range.second; ++iter) {
69 ResumeWaitingThread(iter->second.get()); 40 ResumeWaitingThread(iter->second.get());
70 } 41 }
71 42
@@ -73,72 +44,21 @@ void ReleaseThreadMutexes(Thread* thread) {
73 g_mutex_held_locks.erase(thread); 44 g_mutex_held_locks.erase(thread);
74} 45}
75 46
76bool ReleaseMutex(Mutex* mutex) { 47ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) {
77 if (mutex->locked) { 48 SharedPtr<Mutex> mutex(new Mutex);
78 auto locked = g_mutex_held_locks.equal_range(mutex->holding_thread); 49 // TOOD(yuriks): Don't create Handle (see Thread::Create())
79 50 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(mutex));
80 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
81 if (iter->second == mutex) {
82 g_mutex_held_locks.erase(iter);
83 break;
84 }
85 }
86
87 ResumeWaitingThread(mutex);
88 }
89 return true;
90}
91 51
92/** 52 mutex->initial_locked = initial_locked;
93 * Releases a mutex 53 mutex->locked = false;
94 * @param handle Handle to mutex to release 54 mutex->name = std::move(name);
95 */
96ResultCode ReleaseMutex(Handle handle) {
97 Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle).get();
98 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel);
99
100 if (!ReleaseMutex(mutex)) {
101 // TODO(yuriks): Verify error code, this one was pulled out of thin air. I'm not even sure
102 // what error condition this is supposed to be signaling.
103 return ResultCode(ErrorDescription::AlreadyDone, ErrorModule::Kernel,
104 ErrorSummary::NothingHappened, ErrorLevel::Temporary);
105 }
106 return RESULT_SUCCESS;
107}
108
109/**
110 * Creates a mutex
111 * @param handle Reference to handle for the newly created mutex
112 * @param initial_locked Specifies if the mutex should be locked initially
113 * @param name Optional name of mutex
114 * @return Pointer to new Mutex object
115 */
116Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) {
117 Mutex* mutex = new Mutex;
118 // TODO(yuriks): Fix error reporting
119 handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE);
120
121 mutex->locked = mutex->initial_locked = initial_locked;
122 mutex->name = name;
123 mutex->holding_thread = nullptr; 55 mutex->holding_thread = nullptr;
124 56
125 // Acquire mutex with current thread if initialized as locked... 57 // Acquire mutex with current thread if initialized as locked...
126 if (mutex->locked) 58 if (initial_locked)
127 MutexAcquireLock(mutex, GetCurrentThread()); 59 mutex->Acquire();
128
129 return mutex;
130}
131 60
132/** 61 return MakeResult<SharedPtr<Mutex>>(mutex);
133 * Creates a mutex
134 * @param initial_locked Specifies if the mutex should be locked initially
135 * @param name Optional name of mutex
136 * @return Handle to newly created object
137 */
138Handle CreateMutex(bool initial_locked, const std::string& name) {
139 Handle handle;
140 Mutex* mutex = CreateMutex(handle, initial_locked, name);
141 return handle;
142} 62}
143 63
144bool Mutex::ShouldWait() { 64bool Mutex::ShouldWait() {
@@ -146,9 +66,34 @@ bool Mutex::ShouldWait() {
146} 66}
147 67
148void Mutex::Acquire() { 68void Mutex::Acquire() {
69 Acquire(GetCurrentThread());
70}
71
72void Mutex::Acquire(Thread* thread) {
149 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); 73 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
74 if (locked)
75 return;
76
150 locked = true; 77 locked = true;
151 MutexAcquireLock(this, GetCurrentThread()); 78
79 g_mutex_held_locks.insert(std::make_pair(thread, this));
80 holding_thread = thread;
81}
82
83void Mutex::Release() {
84 if (!locked)
85 return;
86
87 auto locked_range = g_mutex_held_locks.equal_range(holding_thread);
88
89 for (MutexMap::iterator iter = locked_range.first; iter != locked_range.second; ++iter) {
90 if (iter->second == this) {
91 g_mutex_held_locks.erase(iter);
92 break;
93 }
94 }
95
96 ResumeWaitingThread(this);
152} 97}
153 98
154} // namespace 99} // 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 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <string>
8
7#include "common/common_types.h" 9#include "common/common_types.h"
8 10
9#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
10 12
11namespace Kernel { 13namespace Kernel {
12 14
13/** 15class Thread;
14 * Releases a mutex 16
15 * @param handle Handle to mutex to release 17class Mutex final : public WaitObject {
16 */ 18public:
17ResultCode ReleaseMutex(Handle handle); 19 /**
18 20 * Creates a mutex.
19/** 21 * @param initial_locked Specifies if the mutex should be locked initially
20 * Creates a mutex 22 * @param name Optional name of mutex
21 * @param initial_locked Specifies if the mutex should be locked initially 23 * @return Pointer to new Mutex object
22 * @param name Optional name of mutex 24 */
23 * @return Handle to newly created object 25 static ResultVal<SharedPtr<Mutex>> Create(bool initial_locked, std::string name = "Unknown");
24 */ 26
25Handle CreateMutex(bool initial_locked, const std::string& name="Unknown"); 27 std::string GetTypeName() const override { return "Mutex"; }
28 std::string GetName() const override { return name; }
29
30 static const HandleType HANDLE_TYPE = HandleType::Mutex;
31 HandleType GetHandleType() const override { return HANDLE_TYPE; }
32
33 bool initial_locked; ///< Initial lock state when mutex was created
34 bool locked; ///< Current locked state
35 std::string name; ///< Name of mutex (optional)
36 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
37
38 bool ShouldWait() override;
39 void Acquire() override;
40
41 /**
42 * Acquires the specified mutex for the specified thread
43 * @param mutex Mutex that is to be acquired
44 * @param thread Thread that will acquire the mutex
45 */
46 void Acquire(Thread* thread);
47 void Release();
48
49private:
50 Mutex() = default;
51};
26 52
27/** 53/**
28 * Releases all the mutexes held by the specified thread 54 * 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 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <queue>
6
7#include "common/common.h" 5#include "common/common.h"
8 6
9#include "core/hle/kernel/kernel.h" 7#include "core/hle/kernel/kernel.h"
@@ -12,69 +10,50 @@
12 10
13namespace Kernel { 11namespace Kernel {
14 12
15class Semaphore : public WaitObject { 13ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
16public: 14 std::string name) {
17 std::string GetTypeName() const override { return "Semaphore"; }
18 std::string GetName() const override { return name; }
19
20 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
21 HandleType GetHandleType() const override { return HANDLE_TYPE; }
22
23 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
24 s32 available_count; ///< Number of free slots left in the semaphore
25 std::string name; ///< Name of semaphore (optional)
26
27 bool ShouldWait() override {
28 return available_count <= 0;
29 }
30
31 void Acquire() override {
32 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
33 --available_count;
34 }
35};
36
37////////////////////////////////////////////////////////////////////////////////////////////////////
38
39ResultCode CreateSemaphore(Handle* handle, s32 initial_count,
40 s32 max_count, const std::string& name) {
41 15
42 if (initial_count > max_count) 16 if (initial_count > max_count)
43 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, 17 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
44 ErrorSummary::WrongArgument, ErrorLevel::Permanent); 18 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
45 19
46 Semaphore* semaphore = new Semaphore; 20 SharedPtr<Semaphore> semaphore(new Semaphore);
47 // TOOD(yuriks): Fix error reporting 21 // TOOD(yuriks): Don't create Handle (see Thread::Create())
48 *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE); 22 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore));
49 23
50 // When the semaphore is created, some slots are reserved for other threads, 24 // When the semaphore is created, some slots are reserved for other threads,
51 // and the rest is reserved for the caller thread 25 // and the rest is reserved for the caller thread
52 semaphore->max_count = max_count; 26 semaphore->max_count = max_count;
53 semaphore->available_count = initial_count; 27 semaphore->available_count = initial_count;
54 semaphore->name = name; 28 semaphore->name = std::move(name);
55 29
56 return RESULT_SUCCESS; 30 return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore));
57} 31}
58 32
59ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { 33bool Semaphore::ShouldWait() {
60 Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle).get(); 34 return available_count <= 0;
61 if (semaphore == nullptr) 35}
62 return InvalidHandle(ErrorModule::Kernel); 36
37void Semaphore::Acquire() {
38 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
39 --available_count;
40}
63 41
64 if (semaphore->max_count - semaphore->available_count < release_count) 42ResultVal<s32> Semaphore::Release(s32 release_count) {
43 if (max_count - available_count < release_count)
65 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, 44 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,
66 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 45 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
67 46
68 *count = semaphore->available_count; 47 s32 previous_count = available_count;
69 semaphore->available_count += release_count; 48 available_count += release_count;
70 49
71 // Notify some of the threads that the semaphore has been released 50 // Notify some of the threads that the semaphore has been released
72 // stop once the semaphore is full again or there are no more waiting threads 51 // stop once the semaphore is full again or there are no more waiting threads
73 while (!semaphore->ShouldWait() && semaphore->WakeupNextThread() != nullptr) { 52 while (!ShouldWait() && WakeupNextThread() != nullptr) {
74 semaphore->Acquire(); 53 Acquire();
75 } 54 }
76 55
77 return RESULT_SUCCESS; 56 return MakeResult<s32>(previous_count);
78} 57}
79 58
80} // namespace 59} // 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 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <queue>
8#include <string>
9
7#include "common/common_types.h" 10#include "common/common_types.h"
8 11
9#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
10 13
11namespace Kernel { 14namespace Kernel {
12 15
13/** 16class Semaphore final : public WaitObject {
14 * Creates a semaphore. 17public:
15 * @param handle Pointer to the handle of the newly created object 18 /**
16 * @param initial_count Number of slots reserved for other threads 19 * Creates a semaphore.
17 * @param max_count Maximum number of slots the semaphore can have 20 * @param handle Pointer to the handle of the newly created object
18 * @param name Optional name of semaphore 21 * @param initial_count Number of slots reserved for other threads
19 * @return ResultCode of the error 22 * @param max_count Maximum number of slots the semaphore can have
20 */ 23 * @param name Optional name of semaphore
21ResultCode CreateSemaphore(Handle* handle, s32 initial_count, s32 max_count, const std::string& name = "Unknown"); 24 * @return The created semaphore
22 25 */
23/** 26 static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count,
24 * Releases a certain number of slots from a semaphore. 27 std::string name = "Unknown");
25 * @param count The number of free slots the semaphore had before this call 28
26 * @param handle The handle of the semaphore to release 29 std::string GetTypeName() const override { return "Semaphore"; }
27 * @param release_count The number of slots to release 30 std::string GetName() const override { return name; }
28 * @return ResultCode of the error 31
29 */ 32 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
30ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count); 33 HandleType GetHandleType() const override { return HANDLE_TYPE; }
34
35 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
36 s32 available_count; ///< Number of free slots left in the semaphore
37 std::string name; ///< Name of semaphore (optional)
38
39 bool ShouldWait() override;
40 void Acquire() override;
41
42 /**
43 * Releases a certain number of slots from a semaphore.
44 * @param release_count The number of slots to release
45 * @return The number of free slots the semaphore had before this call
46 */
47 ResultVal<s32> Release(s32 release_count);
48
49private:
50 Semaphore() = default;
51};
31 52
32} // namespace 53} // 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 @@
9 9
10namespace Kernel { 10namespace Kernel {
11 11
12class SharedMemory : public Object { 12ResultVal<SharedPtr<SharedMemory>> SharedMemory::Create(std::string name) {
13public: 13 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
14 std::string GetTypeName() const override { return "SharedMemory"; }
15 14
16 static const HandleType HANDLE_TYPE = HandleType::SharedMemory; 15 // TOOD(yuriks): Don't create Handle (see Thread::Create())
17 HandleType GetHandleType() const override { return HANDLE_TYPE; } 16 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(shared_memory));
18 17
19 u32 base_address; ///< Address of shared memory block in RAM 18 shared_memory->name = std::move(name);
20 MemoryPermission permissions; ///< Permissions of shared memory block (SVC field) 19 return MakeResult<SharedPtr<SharedMemory>>(std::move(shared_memory));
21 MemoryPermission other_permissions; ///< Other permissions of shared memory block (SVC field)
22 std::string name; ///< Name of shared memory object (optional)
23};
24
25////////////////////////////////////////////////////////////////////////////////////////////////////
26
27/**
28 * Creates a shared memory object
29 * @param handle Handle of newly created shared memory object
30 * @param name Name of shared memory object
31 * @return Pointer to newly created shared memory object
32 */
33SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) {
34 SharedMemory* shared_memory = new SharedMemory;
35 // TOOD(yuriks): Fix error reporting
36 handle = Kernel::g_handle_table.Create(shared_memory).ValueOr(INVALID_HANDLE);
37 shared_memory->name = name;
38 return shared_memory;
39} 20}
40 21
41Handle CreateSharedMemory(const std::string& name) { 22ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions,
42 Handle handle; 23 MemoryPermission other_permissions) {
43 CreateSharedMemory(handle, name);
44 return handle;
45}
46
47/**
48 * Maps a shared memory block to an address in system memory
49 * @param handle Shared memory block handle
50 * @param address Address in system memory to map shared memory block to
51 * @param permissions Memory block map permissions (specified by SVC field)
52 * @param other_permissions Memory block map other permissions (specified by SVC field)
53 * @return Result of operation, 0 on success, otherwise error code
54 */
55ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
56 MemoryPermission other_permissions) {
57 24
58 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { 25 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) {
59 LOG_ERROR(Kernel_SVC, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", 26 LOG_ERROR(Kernel, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!",
60 handle, address); 27 GetHandle(), address);
28 // TODO: Verify error code with hardware
61 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 29 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
62 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 30 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
63 } 31 }
64 SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle).get();
65 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
66 32
67 shared_memory->base_address = address; 33 base_address = address;
68 shared_memory->permissions = permissions; 34 permissions = permissions;
69 shared_memory->other_permissions = other_permissions; 35 other_permissions = other_permissions;
70 36
71 return RESULT_SUCCESS; 37 return RESULT_SUCCESS;
72} 38}
73 39
74ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) { 40ResultVal<u8*> SharedMemory::GetPointer(u32 offset) {
75 SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle).get(); 41 if (base_address != 0)
76 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); 42 return MakeResult<u8*>(Memory::GetPointer(base_address + offset));
77
78 if (0 != shared_memory->base_address)
79 return MakeResult<u8*>(Memory::GetPointer(shared_memory->base_address + offset));
80 43
81 LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", handle); 44 LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", GetHandle());
82 // TODO(yuriks): Verify error code. 45 // TODO(yuriks): Verify error code.
83 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 46 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
84 ErrorSummary::InvalidState, ErrorLevel::Permanent); 47 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 {
23 DontCare = (1u << 28) 23 DontCare = (1u << 28)
24}; 24};
25 25
26/** 26class SharedMemory final : public Object {
27 * Creates a shared memory object 27public:
28 * @param name Optional name of shared memory object 28 /**
29 * @return Handle of newly created shared memory object 29 * Creates a shared memory object
30 */ 30 * @param name Optional object name, used only for debugging purposes.
31Handle CreateSharedMemory(const std::string& name="Unknown"); 31 */
32 32 static ResultVal<SharedPtr<SharedMemory>> Create(std::string name = "Unknown");
33/** 33
34 * Maps a shared memory block to an address in system memory 34 std::string GetTypeName() const override { return "SharedMemory"; }
35 * @param handle Shared memory block handle 35
36 * @param address Address in system memory to map shared memory block to 36 static const HandleType HANDLE_TYPE = HandleType::SharedMemory;
37 * @param permissions Memory block map permissions (specified by SVC field) 37 HandleType GetHandleType() const override { return HANDLE_TYPE; }
38 * @param other_permissions Memory block map other permissions (specified by SVC field) 38
39 */ 39 /**
40ResultCode MapSharedMemory(Handle handle, u32 address, MemoryPermission permissions, 40 * Maps a shared memory block to an address in system memory
41 MemoryPermission other_permissions); 41 * @param address Address in system memory to map shared memory block to
42 42 * @param permissions Memory block map permissions (specified by SVC field)
43/** 43 * @param other_permissions Memory block map other permissions (specified by SVC field)
44 * Gets a pointer to the shared memory block 44 */
45 * @param handle Shared memory block handle 45 ResultCode Map(VAddr address, MemoryPermission permissions, MemoryPermission other_permissions);
46 * @param offset Offset from the start of the shared memory block to get pointer 46
47 * @return Pointer to the shared memory block from the specified offset 47 /**
48 */ 48 * Gets a pointer to the shared memory block
49ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset); 49 * @param offset Offset from the start of the shared memory block to get pointer
50 * @return Pointer to the shared memory block from the specified offset
51 */
52 ResultVal<u8*> GetPointer(u32 offset = 0);
53
54 VAddr base_address; ///< Address of shared memory block in RAM
55 MemoryPermission permissions; ///< Permissions of shared memory block (SVC field)
56 MemoryPermission other_permissions; ///< Other permissions of shared memory block (SVC field)
57 std::string name; ///< Name of shared memory object (optional)
58
59private:
60 SharedMemory() = default;
61};
50 62
51} // namespace 63} // 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 {
40 40
41namespace Kernel { 41namespace Kernel {
42 42
43class Thread : public WaitObject { 43class Thread final : public WaitObject {
44public: 44public:
45 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, 45 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
46 u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size); 46 u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size);
@@ -115,7 +115,6 @@ public:
115 bool idle = false; 115 bool idle = false;
116 116
117private: 117private:
118
119 Thread() = default; 118 Thread() = default;
120}; 119};
121 120
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 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16class Timer : public WaitObject { 16/// The event type of the generic timer callback event
17public: 17static int timer_callback_event_type = -1;
18 std::string GetTypeName() const override { return "Timer"; }
19 std::string GetName() const override { return name; }
20
21 static const HandleType HANDLE_TYPE = HandleType::Timer;
22 HandleType GetHandleType() const override { return HANDLE_TYPE; }
23
24 ResetType reset_type; ///< The ResetType of this timer
25
26 bool signaled; ///< Whether the timer has been signaled or not
27 std::string name; ///< Name of timer (optional)
28
29 u64 initial_delay; ///< The delay until the timer fires for the first time
30 u64 interval_delay; ///< The delay until the timer fires after the first time
31
32 bool ShouldWait() override {
33 return !signaled;
34 }
35
36 void Acquire() override {
37 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
38 }
39};
40
41/**
42 * Creates a timer.
43 * @param handle Reference to handle for the newly created timer
44 * @param reset_type ResetType describing how to create timer
45 * @param name Optional name of timer
46 * @return Newly created Timer object
47 */
48Timer* CreateTimer(Handle& handle, const ResetType reset_type, const std::string& name) {
49 Timer* timer = new Timer;
50 18
51 handle = Kernel::g_handle_table.Create(timer).ValueOr(INVALID_HANDLE); 19ResultVal<SharedPtr<Timer>> Timer::Create(ResetType reset_type, std::string name) {
20 SharedPtr<Timer> timer(new Timer);
21 // TOOD(yuriks): Don't create Handle (see Thread::Create())
22 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(timer));
52 23
53 timer->reset_type = reset_type; 24 timer->reset_type = reset_type;
54 timer->signaled = false; 25 timer->signaled = false;
55 timer->name = name; 26 timer->name = std::move(name);
56 timer->initial_delay = 0; 27 timer->initial_delay = 0;
57 timer->interval_delay = 0; 28 timer->interval_delay = 0;
58 return timer; 29 return MakeResult<SharedPtr<Timer>>(timer);
59} 30}
60 31
61ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name) { 32bool Timer::ShouldWait() {
62 CreateTimer(*handle, reset_type, name); 33 return !signaled;
63 return RESULT_SUCCESS;
64} 34}
65 35
66ResultCode ClearTimer(Handle handle) { 36void Timer::Acquire() {
67 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle); 37 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
68 38}
69 if (timer == nullptr)
70 return InvalidHandle(ErrorModule::Kernel);
71 39
72 timer->signaled = false; 40void Timer::Set(s64 initial, s64 interval) {
73 return RESULT_SUCCESS; 41 initial_delay = initial;
42 interval_delay = interval;
43
44 u64 initial_microseconds = initial / 1000;
45 // TODO(yuriks): Figure out a replacement for GetHandle here
46 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type,
47 GetHandle());
74} 48}
75 49
76/// The event type of the generic timer callback event 50void Timer::Cancel() {
77static int TimerCallbackEventType = -1; 51 CoreTiming::UnscheduleEvent(timer_callback_event_type, GetHandle());
52}
53
54void Timer::Clear() {
55 signaled = false;
56}
78 57
79/// The timer callback event, called when a timer is fired 58/// The timer callback event, called when a timer is fired
80static void TimerCallback(u64 timer_handle, int cycles_late) { 59static void TimerCallback(u64 timer_handle, int cycles_late) {
81 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle); 60 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle);
82 61
83 if (timer == nullptr) { 62 if (timer == nullptr) {
84 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %u", timer_handle); 63 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle);
85 return; 64 return;
86 } 65 }
87 66
@@ -99,36 +78,12 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
99 // Reschedule the timer with the interval delay 78 // Reschedule the timer with the interval delay
100 u64 interval_microseconds = timer->interval_delay / 1000; 79 u64 interval_microseconds = timer->interval_delay / 1000;
101 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, 80 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
102 TimerCallbackEventType, timer_handle); 81 timer_callback_event_type, timer_handle);
103 } 82 }
104} 83}
105 84
106ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
107 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
108
109 if (timer == nullptr)
110 return InvalidHandle(ErrorModule::Kernel);
111
112 timer->initial_delay = initial;
113 timer->interval_delay = interval;
114
115 u64 initial_microseconds = initial / 1000;
116 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), TimerCallbackEventType, handle);
117 return RESULT_SUCCESS;
118}
119
120ResultCode CancelTimer(Handle handle) {
121 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
122
123 if (timer == nullptr)
124 return InvalidHandle(ErrorModule::Kernel);
125
126 CoreTiming::UnscheduleEvent(TimerCallbackEventType, handle);
127 return RESULT_SUCCESS;
128}
129
130void TimersInit() { 85void TimersInit() {
131 TimerCallbackEventType = CoreTiming::RegisterEvent("TimerCallback", TimerCallback); 86 timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
132} 87}
133 88
134void TimersShutdown() { 89void 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 @@
11 11
12namespace Kernel { 12namespace Kernel {
13 13
14/** 14class Timer final : public WaitObject {
15 * Cancels a timer 15public:
16 * @param handle Handle of the timer to cancel 16 /**
17 */ 17 * Creates a timer
18ResultCode CancelTimer(Handle handle); 18 * @param reset_type ResetType describing how to create the timer
19 19 * @param name Optional name of timer
20/** 20 * @return The created Timer
21 * Starts a timer with the specified initial delay and interval 21 */
22 * @param handle Handle of the timer to start 22 static ResultVal<SharedPtr<Timer>> Create(ResetType reset_type, std::string name = "Unknown");
23 * @param initial Delay until the timer is first fired 23
24 * @param interval Delay until the timer is fired after the first time 24 std::string GetTypeName() const override { return "Timer"; }
25 */ 25 std::string GetName() const override { return name; }
26ResultCode SetTimer(Handle handle, s64 initial, s64 interval); 26
27 27 static const HandleType HANDLE_TYPE = HandleType::Timer;
28/** 28 HandleType GetHandleType() const override { return HANDLE_TYPE; }
29 * Clears a timer 29
30 * @param handle Handle of the timer to clear 30 ResetType reset_type; ///< The ResetType of this timer
31 */ 31
32ResultCode ClearTimer(Handle handle); 32 bool signaled; ///< Whether the timer has been signaled or not
33 33 std::string name; ///< Name of timer (optional)
34/** 34
35 * Creates a timer 35 u64 initial_delay; ///< The delay until the timer fires for the first time
36 * @param handle Handle to the newly created Timer object 36 u64 interval_delay; ///< The delay until the timer fires after the first time
37 * @param reset_type ResetType describing how to create the timer 37
38 * @param name Optional name of timer 38 bool ShouldWait() override;
39 * @return ResultCode of the error 39 void Acquire() override;
40 */ 40
41ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name="Unknown"); 41 /**
42 * Starts the timer, with the specified initial delay and interval.
43 * @param initial Delay until the timer is first fired
44 * @param interval Delay until the timer is fired after the first time
45 */
46 void Set(s64 initial, s64 interval);
47
48 void Cancel();
49 void Clear();
50
51private:
52 Timer() = default;
53};
42 54
43/// Initializes the required variables for timers 55/// Initializes the required variables for timers
44void TimersInit(); 56void TimersInit();
45/// Tears down the timer variables 57/// Tears down the timer variables
46void TimersShutdown(); 58void TimersShutdown();
59
47} // namespace 60} // namespace