summaryrefslogtreecommitdiff
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.cpp15
-rw-r--r--src/core/hle/kernel/address_arbiter.h2
-rw-r--r--src/core/hle/kernel/archive.cpp176
-rw-r--r--src/core/hle/kernel/archive.h23
-rw-r--r--src/core/hle/kernel/event.cpp43
-rw-r--r--src/core/hle/kernel/event.h12
-rw-r--r--src/core/hle/kernel/kernel.h44
-rw-r--r--src/core/hle/kernel/mutex.cpp35
-rw-r--r--src/core/hle/kernel/mutex.h3
-rw-r--r--src/core/hle/kernel/shared_memory.cpp43
-rw-r--r--src/core/hle/kernel/shared_memory.h5
-rw-r--r--src/core/hle/kernel/thread.cpp78
-rw-r--r--src/core/hle/kernel/thread.h7
13 files changed, 195 insertions, 291 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 2b21657da..db571b895 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -25,22 +25,17 @@ public:
25 25
26 std::string name; ///< Name of address arbiter object (optional) 26 std::string name; ///< Name of address arbiter object (optional)
27 27
28 /** 28 ResultVal<bool> WaitSynchronization() override {
29 * Wait for kernel object to synchronize
30 * @param wait Boolean wait set if current thread should wait as a result of sync operation
31 * @return Result of operation, 0 on success, otherwise error code
32 */
33 Result WaitSynchronization(bool* wait) override {
34 // TODO(bunnei): ImplementMe 29 // TODO(bunnei): ImplementMe
35 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 30 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
36 return 0; 31 return UnimplementedFunction(ErrorModule::OS);
37 } 32 }
38}; 33};
39 34
40//////////////////////////////////////////////////////////////////////////////////////////////////// 35////////////////////////////////////////////////////////////////////////////////////////////////////
41 36
42/// Arbitrate an address 37/// Arbitrate an address
43Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) { 38ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) {
44 switch (type) { 39 switch (type) {
45 40
46 // Signal thread(s) waiting for arbitrate address... 41 // Signal thread(s) waiting for arbitrate address...
@@ -65,9 +60,9 @@ Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 va
65 60
66 default: 61 default:
67 ERROR_LOG(KERNEL, "unknown type=%d", type); 62 ERROR_LOG(KERNEL, "unknown type=%d", type);
68 return -1; 63 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage);
69 } 64 }
70 return 0; 65 return RESULT_SUCCESS;
71} 66}
72 67
73/// Create an address arbiter 68/// Create an address arbiter
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 6886e479d..8a5fb10b4 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -28,7 +28,7 @@ enum class ArbitrationType : u32 {
28}; 28};
29 29
30/// Arbitrate an address 30/// Arbitrate an address
31Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value); 31ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value);
32 32
33/// Create an address arbiter 33/// Create an address arbiter
34Handle CreateAddressArbiter(const std::string& name = "Unknown"); 34Handle CreateAddressArbiter(const std::string& name = "Unknown");
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp
index 900f484c7..e273444c9 100644
--- a/src/core/hle/kernel/archive.cpp
+++ b/src/core/hle/kernel/archive.cpp
@@ -9,8 +9,9 @@
9#include "core/file_sys/archive.h" 9#include "core/file_sys/archive.h"
10#include "core/file_sys/archive_sdmc.h" 10#include "core/file_sys/archive_sdmc.h"
11#include "core/file_sys/directory.h" 11#include "core/file_sys/directory.h"
12#include "core/hle/service/service.h"
13#include "core/hle/kernel/archive.h" 12#include "core/hle/kernel/archive.h"
13#include "core/hle/result.h"
14#include "core/hle/service/service.h"
14 15
15//////////////////////////////////////////////////////////////////////////////////////////////////// 16////////////////////////////////////////////////////////////////////////////////////////////////////
16// Kernel namespace 17// Kernel namespace
@@ -51,12 +52,7 @@ public:
51 std::string name; ///< Name of archive (optional) 52 std::string name; ///< Name of archive (optional)
52 FileSys::Archive* backend; ///< Archive backend interface 53 FileSys::Archive* backend; ///< Archive backend interface
53 54
54 /** 55 ResultVal<bool> SyncRequest() override {
55 * Synchronize kernel object
56 * @param wait Boolean wait set if current thread should wait as a result of sync operation
57 * @return Result of operation, 0 on success, otherwise error code
58 */
59 Result SyncRequest(bool* wait) override {
60 u32* cmd_buff = Service::GetCommandBuffer(); 56 u32* cmd_buff = Service::GetCommandBuffer();
61 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 57 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
62 58
@@ -106,22 +102,17 @@ public:
106 default: 102 default:
107 { 103 {
108 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); 104 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
109 return -1; 105 return UnimplementedFunction(ErrorModule::FS);
110 } 106 }
111 } 107 }
112 cmd_buff[1] = 0; // No error 108 cmd_buff[1] = 0; // No error
113 return 0; 109 return MakeResult<bool>(false);
114 } 110 }
115 111
116 /** 112 ResultVal<bool> WaitSynchronization() override {
117 * Wait for kernel object to synchronize
118 * @param wait Boolean wait set if current thread should wait as a result of sync operation
119 * @return Result of operation, 0 on success, otherwise error code
120 */
121 Result WaitSynchronization(bool* wait) override {
122 // TODO(bunnei): ImplementMe 113 // TODO(bunnei): ImplementMe
123 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 114 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
124 return 0; 115 return UnimplementedFunction(ErrorModule::FS);
125 } 116 }
126}; 117};
127 118
@@ -136,12 +127,7 @@ public:
136 FileSys::Path path; ///< Path of the file 127 FileSys::Path path; ///< Path of the file
137 std::unique_ptr<FileSys::File> backend; ///< File backend interface 128 std::unique_ptr<FileSys::File> backend; ///< File backend interface
138 129
139 /** 130 ResultVal<bool> SyncRequest() override {
140 * Synchronize kernel object
141 * @param wait Boolean wait set if current thread should wait as a result of sync operation
142 * @return Result of operation, 0 on success, otherwise error code
143 */
144 Result SyncRequest(bool* wait) override {
145 u32* cmd_buff = Service::GetCommandBuffer(); 131 u32* cmd_buff = Service::GetCommandBuffer();
146 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 132 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
147 switch (cmd) { 133 switch (cmd) {
@@ -183,7 +169,8 @@ public:
183 case FileCommand::SetSize: 169 case FileCommand::SetSize:
184 { 170 {
185 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); 171 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
186 DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu", GetTypeName().c_str(), GetName().c_str(), size); 172 DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu",
173 GetTypeName().c_str(), GetName().c_str(), size);
187 backend->SetSize(size); 174 backend->SetSize(size);
188 break; 175 break;
189 } 176 }
@@ -198,22 +185,18 @@ public:
198 // Unknown command... 185 // Unknown command...
199 default: 186 default:
200 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); 187 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
201 cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. 188 ResultCode error = UnimplementedFunction(ErrorModule::FS);
202 return -1; 189 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
190 return error;
203 } 191 }
204 cmd_buff[1] = 0; // No error 192 cmd_buff[1] = 0; // No error
205 return 0; 193 return MakeResult<bool>(false);
206 } 194 }
207 195
208 /** 196 ResultVal<bool> WaitSynchronization() override {
209 * Wait for kernel object to synchronize
210 * @param wait Boolean wait set if current thread should wait as a result of sync operation
211 * @return Result of operation, 0 on success, otherwise error code
212 */
213 Result WaitSynchronization(bool* wait) override {
214 // TODO(bunnei): ImplementMe 197 // TODO(bunnei): ImplementMe
215 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 198 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
216 return 0; 199 return UnimplementedFunction(ErrorModule::FS);
217 } 200 }
218}; 201};
219 202
@@ -228,12 +211,7 @@ public:
228 FileSys::Path path; ///< Path of the directory 211 FileSys::Path path; ///< Path of the directory
229 std::unique_ptr<FileSys::Directory> backend; ///< File backend interface 212 std::unique_ptr<FileSys::Directory> backend; ///< File backend interface
230 213
231 /** 214 ResultVal<bool> SyncRequest() override {
232 * Synchronize kernel object
233 * @param wait Boolean wait set if current thread should wait as a result of sync operation
234 * @return Result of operation, 0 on success, otherwise error code
235 */
236 Result SyncRequest(bool* wait) override {
237 u32* cmd_buff = Service::GetCommandBuffer(); 215 u32* cmd_buff = Service::GetCommandBuffer();
238 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); 216 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
239 switch (cmd) { 217 switch (cmd) {
@@ -243,8 +221,9 @@ public:
243 { 221 {
244 u32 count = cmd_buff[1]; 222 u32 count = cmd_buff[1];
245 u32 address = cmd_buff[3]; 223 u32 address = cmd_buff[3];
246 FileSys::Entry* entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); 224 auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address));
247 DEBUG_LOG(KERNEL, "Read %s %s: count=%d", GetTypeName().c_str(), GetName().c_str(), count); 225 DEBUG_LOG(KERNEL, "Read %s %s: count=%d",
226 GetTypeName().c_str(), GetName().c_str(), count);
248 227
249 // Number of entries actually read 228 // Number of entries actually read
250 cmd_buff[2] = backend->Read(count, entries); 229 cmd_buff[2] = backend->Read(count, entries);
@@ -261,22 +240,18 @@ public:
261 // Unknown command... 240 // Unknown command...
262 default: 241 default:
263 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); 242 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
264 cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. 243 ResultCode error = UnimplementedFunction(ErrorModule::FS);
265 return -1; 244 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
245 return error;
266 } 246 }
267 cmd_buff[1] = 0; // No error 247 cmd_buff[1] = 0; // No error
268 return 0; 248 return MakeResult<bool>(false);
269 } 249 }
270 250
271 /** 251 ResultVal<bool> WaitSynchronization() override {
272 * Wait for kernel object to synchronize
273 * @param wait Boolean wait set if current thread should wait as a result of sync operation
274 * @return Result of operation, 0 on success, otherwise error code
275 */
276 Result WaitSynchronization(bool* wait) override {
277 // TODO(bunnei): ImplementMe 252 // TODO(bunnei): ImplementMe
278 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 253 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
279 return 0; 254 return UnimplementedFunction(ErrorModule::FS);
280 } 255 }
281}; 256};
282 257
@@ -284,89 +259,58 @@ public:
284 259
285std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode 260std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode
286 261
287/** 262ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code) {
288 * Opens an archive
289 * @param id_code IdCode of the archive to open
290 * @return Handle to archive if it exists, otherwise a null handle (0)
291 */
292Handle OpenArchive(FileSys::Archive::IdCode id_code) {
293 auto itr = g_archive_map.find(id_code); 263 auto itr = g_archive_map.find(id_code);
294 if (itr == g_archive_map.end()) { 264 if (itr == g_archive_map.end()) {
295 return 0; 265 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
266 ErrorSummary::NotFound, ErrorLevel::Permanent);
296 } 267 }
297 return itr->second; 268
269 return MakeResult<Handle>(itr->second);
298} 270}
299 271
300/** 272ResultCode CloseArchive(FileSys::Archive::IdCode id_code) {
301 * Closes an archive
302 * @param id_code IdCode of the archive to open
303 * @return Result of operation, 0 on success, otherwise error code
304 */
305Result CloseArchive(FileSys::Archive::IdCode id_code) {
306 auto itr = g_archive_map.find(id_code); 273 auto itr = g_archive_map.find(id_code);
307 if (itr == g_archive_map.end()) { 274 if (itr == g_archive_map.end()) {
308 ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code); 275 ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code);
309 return -1; 276 return InvalidHandle(ErrorModule::FS);
310 } 277 }
311 278
312 INFO_LOG(KERNEL, "Closed archive %d", (int) id_code); 279 INFO_LOG(KERNEL, "Closed archive %d", (int) id_code);
313 return 0; 280 return RESULT_SUCCESS;
314} 281}
315 282
316/** 283/**
317 * Mounts an archive 284 * Mounts an archive
318 * @param archive Pointer to the archive to mount 285 * @param archive Pointer to the archive to mount
319 * @return Result of operation, 0 on success, otherwise error code
320 */ 286 */
321Result MountArchive(Archive* archive) { 287ResultCode MountArchive(Archive* archive) {
322 FileSys::Archive::IdCode id_code = archive->backend->GetIdCode(); 288 FileSys::Archive::IdCode id_code = archive->backend->GetIdCode();
323 if (0 != OpenArchive(id_code)) { 289 ResultVal<Handle> archive_handle = OpenArchive(id_code);
290 if (archive_handle.Succeeded()) {
324 ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code); 291 ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code);
325 return -1; 292 return archive_handle.Code();
326 } 293 }
327 g_archive_map[id_code] = archive->GetHandle(); 294 g_archive_map[id_code] = archive->GetHandle();
328 INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str()); 295 INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str());
329 return 0; 296 return RESULT_SUCCESS;
330} 297}
331 298
332/** 299ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name) {
333 * Creates an Archive
334 * @param handle Handle to newly created archive object
335 * @param backend File system backend interface to the archive
336 * @param name Optional name of Archive
337 * @return Newly created Archive object
338 */
339Archive* CreateArchive(Handle& handle, FileSys::Archive* backend, const std::string& name) {
340 Archive* archive = new Archive; 300 Archive* archive = new Archive;
341 handle = Kernel::g_object_pool.Create(archive); 301 Handle handle = Kernel::g_object_pool.Create(archive);
342 archive->name = name; 302 archive->name = name;
343 archive->backend = backend; 303 archive->backend = backend;
344 304
345 MountArchive(archive); 305 ResultCode result = MountArchive(archive);
346 306 if (result.IsError()) {
347 return archive; 307 return result;
348} 308 }
349 309
350/** 310 return RESULT_SUCCESS;
351 * Creates an Archive
352 * @param backend File system backend interface to the archive
353 * @param name Optional name of Archive
354 * @return Handle to newly created Archive object
355 */
356Handle CreateArchive(FileSys::Archive* backend, const std::string& name) {
357 Handle handle;
358 CreateArchive(handle, backend, name);
359 return handle;
360} 311}
361 312
362/** 313ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) {
363 * Open a File from an Archive
364 * @param archive_handle Handle to an open Archive object
365 * @param path Path to the File inside of the Archive
366 * @param mode Mode under which to open the File
367 * @return Opened File object
368 */
369Handle OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) {
370 // TODO(bunnei): Binary type files get a raw file pointer to the archive. Currently, we create 314 // TODO(bunnei): Binary type files get a raw file pointer to the archive. Currently, we create
371 // the archive file handles at app loading, and then keep them persistent throughout execution. 315 // the archive file handles at app loading, and then keep them persistent throughout execution.
372 // Archives file handles are just reused and not actually freed until emulation shut down. 316 // Archives file handles are just reused and not actually freed until emulation shut down.
@@ -376,19 +320,24 @@ Handle OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, con
376 // design. While the functionally of this is OK, our implementation decision to separate 320 // design. While the functionally of this is OK, our implementation decision to separate
377 // normal files from archive file pointers is very likely wrong. 321 // normal files from archive file pointers is very likely wrong.
378 // See https://github.com/citra-emu/citra/issues/205 322 // See https://github.com/citra-emu/citra/issues/205
379 return archive_handle; 323 return MakeResult<Handle>(archive_handle);
380 324
381 File* file = new File; 325 File* file = new File;
382 Handle handle = Kernel::g_object_pool.Create(file); 326 Handle handle = Kernel::g_object_pool.Create(file);
383 327
384 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); 328 Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle);
329 if (archive == nullptr) {
330 return InvalidHandle(ErrorModule::FS);
331 }
385 file->path = path; 332 file->path = path;
386 file->backend = archive->backend->OpenFile(path, mode); 333 file->backend = archive->backend->OpenFile(path, mode);
387 334
388 if (!file->backend) 335 if (!file->backend) {
389 return 0; 336 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
337 ErrorSummary::NotFound, ErrorLevel::Permanent);
338 }
390 339
391 return handle; 340 return MakeResult<Handle>(handle);
392} 341}
393 342
394/** 343/**
@@ -442,15 +391,18 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa
442 * @param path Path to the Directory inside of the Archive 391 * @param path Path to the Directory inside of the Archive
443 * @return Opened Directory object 392 * @return Opened Directory object
444 */ 393 */
445Handle OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { 394ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
446 Directory* directory = new Directory; 395 Directory* directory = new Directory;
447 Handle handle = Kernel::g_object_pool.Create(directory); 396 Handle handle = Kernel::g_object_pool.Create(directory);
448 397
449 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); 398 Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle);
399 if (archive == nullptr) {
400 return InvalidHandle(ErrorModule::FS);
401 }
450 directory->path = path; 402 directory->path = path;
451 directory->backend = archive->backend->OpenDirectory(path); 403 directory->backend = archive->backend->OpenDirectory(path);
452 404
453 return handle; 405 return MakeResult<Handle>(handle);
454} 406}
455 407
456/// Initialize archives 408/// Initialize archives
diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/kernel/archive.h
index 95b3c6656..6fc4f0f25 100644
--- a/src/core/hle/kernel/archive.h
+++ b/src/core/hle/kernel/archive.h
@@ -6,8 +6,9 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9#include "core/hle/kernel/kernel.h"
10#include "core/file_sys/archive.h" 9#include "core/file_sys/archive.h"
10#include "core/hle/kernel/kernel.h"
11#include "core/hle/result.h"
11 12
12//////////////////////////////////////////////////////////////////////////////////////////////////// 13////////////////////////////////////////////////////////////////////////////////////////////////////
13// Kernel namespace 14// Kernel namespace
@@ -17,33 +18,31 @@ namespace Kernel {
17/** 18/**
18 * Opens an archive 19 * Opens an archive
19 * @param id_code IdCode of the archive to open 20 * @param id_code IdCode of the archive to open
20 * @return Handle to archive if it exists, otherwise a null handle (0) 21 * @return Handle to the opened archive
21 */ 22 */
22Handle OpenArchive(FileSys::Archive::IdCode id_code); 23ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code);
23 24
24/** 25/**
25 * Closes an archive 26 * Closes an archive
26 * @param id_code IdCode of the archive to open 27 * @param id_code IdCode of the archive to open
27 * @return true if it worked fine
28 */ 28 */
29Result CloseArchive(FileSys::Archive::IdCode id_code); 29ResultCode CloseArchive(FileSys::Archive::IdCode id_code);
30 30
31/** 31/**
32 * Creates an Archive 32 * Creates an Archive
33 * @param backend File system backend interface to the archive 33 * @param backend File system backend interface to the archive
34 * @param name Optional name of Archive 34 * @param name Name of Archive
35 * @return Handle to newly created Archive object
36 */ 35 */
37Handle CreateArchive(FileSys::Archive* backend, const std::string& name); 36ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name);
38 37
39/** 38/**
40 * Open a File from an Archive 39 * Open a File from an Archive
41 * @param archive_handle Handle to an open Archive object 40 * @param archive_handle Handle to an open Archive object
42 * @param path Path to the File inside of the Archive 41 * @param path Path to the File inside of the Archive
43 * @param mode Mode under which to open the File 42 * @param mode Mode under which to open the File
44 * @return Opened File object 43 * @return Handle to the opened File object
45 */ 44 */
46Handle OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); 45ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode);
47 46
48/** 47/**
49 * Delete a File from an Archive 48 * Delete a File from an Archive
@@ -73,9 +72,9 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa
73 * Open a Directory from an Archive 72 * Open a Directory from an Archive
74 * @param archive_handle Handle to an open Archive object 73 * @param archive_handle Handle to an open Archive object
75 * @param path Path to the Directory inside of the Archive 74 * @param path Path to the Directory inside of the Archive
76 * @return Opened Directory object 75 * @return Handle to the opened File object
77 */ 76 */
78Handle OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); 77ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path);
79 78
80/// Initialize archives 79/// Initialize archives
81void ArchiveInit(); 80void ArchiveInit();
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index e0117c0bc..288080209 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -30,13 +30,8 @@ public:
30 std::vector<Handle> waiting_threads; ///< Threads that are waiting for the event 30 std::vector<Handle> waiting_threads; ///< Threads that are waiting for the event
31 std::string name; ///< Name of event (optional) 31 std::string name; ///< Name of event (optional)
32 32
33 /** 33 ResultVal<bool> WaitSynchronization() override {
34 * Wait for kernel object to synchronize 34 bool wait = locked;
35 * @param wait Boolean wait set if current thread should wait as a result of sync operation
36 * @return Result of operation, 0 on success, otherwise error code
37 */
38 Result WaitSynchronization(bool* wait) override {
39 *wait = locked;
40 if (locked) { 35 if (locked) {
41 Handle thread = GetCurrentThreadHandle(); 36 Handle thread = GetCurrentThreadHandle();
42 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { 37 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
@@ -47,7 +42,7 @@ public:
47 if (reset_type != RESETTYPE_STICKY && !permanent_locked) { 42 if (reset_type != RESETTYPE_STICKY && !permanent_locked) {
48 locked = true; 43 locked = true;
49 } 44 }
50 return 0; 45 return MakeResult<bool>(wait);
51 } 46 }
52}; 47};
53 48
@@ -57,12 +52,12 @@ public:
57 * @param permanent_locked Boolean permanent locked value to set event 52 * @param permanent_locked Boolean permanent locked value to set event
58 * @return Result of operation, 0 on success, otherwise error code 53 * @return Result of operation, 0 on success, otherwise error code
59 */ 54 */
60Result SetPermanentLock(Handle handle, const bool permanent_locked) { 55ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) {
61 Event* evt = g_object_pool.GetFast<Event>(handle); 56 Event* evt = g_object_pool.Get<Event>(handle);
62 _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); 57 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
63 58
64 evt->permanent_locked = permanent_locked; 59 evt->permanent_locked = permanent_locked;
65 return 0; 60 return RESULT_SUCCESS;
66} 61}
67 62
68/** 63/**
@@ -71,14 +66,14 @@ Result SetPermanentLock(Handle handle, const bool permanent_locked) {
71 * @param locked Boolean locked value to set event 66 * @param locked Boolean locked value to set event
72 * @return Result of operation, 0 on success, otherwise error code 67 * @return Result of operation, 0 on success, otherwise error code
73 */ 68 */
74Result SetEventLocked(const Handle handle, const bool locked) { 69ResultCode SetEventLocked(const Handle handle, const bool locked) {
75 Event* evt = g_object_pool.GetFast<Event>(handle); 70 Event* evt = g_object_pool.Get<Event>(handle);
76 _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); 71 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
77 72
78 if (!evt->permanent_locked) { 73 if (!evt->permanent_locked) {
79 evt->locked = locked; 74 evt->locked = locked;
80 } 75 }
81 return 0; 76 return RESULT_SUCCESS;
82} 77}
83 78
84/** 79/**
@@ -86,9 +81,9 @@ Result SetEventLocked(const Handle handle, const bool locked) {
86 * @param handle Handle to event to signal 81 * @param handle Handle to event to signal
87 * @return Result of operation, 0 on success, otherwise error code 82 * @return Result of operation, 0 on success, otherwise error code
88 */ 83 */
89Result SignalEvent(const Handle handle) { 84ResultCode SignalEvent(const Handle handle) {
90 Event* evt = g_object_pool.GetFast<Event>(handle); 85 Event* evt = g_object_pool.Get<Event>(handle);
91 _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); 86 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
92 87
93 // Resume threads waiting for event to signal 88 // Resume threads waiting for event to signal
94 bool event_caught = false; 89 bool event_caught = false;
@@ -106,7 +101,7 @@ Result SignalEvent(const Handle handle) {
106 if (!evt->permanent_locked) { 101 if (!evt->permanent_locked) {
107 evt->locked = event_caught; 102 evt->locked = event_caught;
108 } 103 }
109 return 0; 104 return RESULT_SUCCESS;
110} 105}
111 106
112/** 107/**
@@ -114,14 +109,14 @@ Result SignalEvent(const Handle handle) {
114 * @param handle Handle to event to clear 109 * @param handle Handle to event to clear
115 * @return Result of operation, 0 on success, otherwise error code 110 * @return Result of operation, 0 on success, otherwise error code
116 */ 111 */
117Result ClearEvent(Handle handle) { 112ResultCode ClearEvent(Handle handle) {
118 Event* evt = g_object_pool.GetFast<Event>(handle); 113 Event* evt = g_object_pool.Get<Event>(handle);
119 _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); 114 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
120 115
121 if (!evt->permanent_locked) { 116 if (!evt->permanent_locked) {
122 evt->locked = true; 117 evt->locked = true;
123 } 118 }
124 return 0; 119 return RESULT_SUCCESS;
125} 120}
126 121
127/** 122/**
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 6add72897..73aec4e79 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -15,31 +15,27 @@ namespace Kernel {
15 * Changes whether an event is locked or not 15 * Changes whether an event is locked or not
16 * @param handle Handle to event to change 16 * @param handle Handle to event to change
17 * @param locked Boolean locked value to set event 17 * @param locked Boolean locked value to set event
18 * @return Result of operation, 0 on success, otherwise error code
19 */ 18 */
20Result SetEventLocked(const Handle handle, const bool locked); 19ResultCode SetEventLocked(const Handle handle, const bool locked);
21 20
22/** 21/**
23 * Hackish function to set an events permanent lock state, used to pass through synch blocks 22 * Hackish function to set an events permanent lock state, used to pass through synch blocks
24 * @param handle Handle to event to change 23 * @param handle Handle to event to change
25 * @param permanent_locked Boolean permanent locked value to set event 24 * @param permanent_locked Boolean permanent locked value to set event
26 * @return Result of operation, 0 on success, otherwise error code
27 */ 25 */
28Result SetPermanentLock(Handle handle, const bool permanent_locked); 26ResultCode SetPermanentLock(Handle handle, const bool permanent_locked);
29 27
30/** 28/**
31 * Signals an event 29 * Signals an event
32 * @param handle Handle to event to signal 30 * @param handle Handle to event to signal
33 * @return Result of operation, 0 on success, otherwise error code
34 */ 31 */
35Result SignalEvent(const Handle handle); 32ResultCode SignalEvent(const Handle handle);
36 33
37/** 34/**
38 * Clears an event 35 * Clears an event
39 * @param handle Handle to event to clear 36 * @param handle Handle to event to clear
40 * @return Result of operation, 0 on success, otherwise error code
41 */ 37 */
42Result ClearEvent(Handle handle); 38ResultCode ClearEvent(Handle handle);
43 39
44/** 40/**
45 * Creates an event 41 * Creates an event
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index e0c94f186..8d3937ce8 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -7,6 +7,7 @@
7#include <array> 7#include <array>
8#include <string> 8#include <string>
9#include "common/common.h" 9#include "common/common.h"
10#include "core/hle/result.h"
10 11
11typedef u32 Handle; 12typedef u32 Handle;
12typedef s32 Result; 13typedef s32 Result;
@@ -52,21 +53,19 @@ public:
52 virtual Kernel::HandleType GetHandleType() const = 0; 53 virtual Kernel::HandleType GetHandleType() const = 0;
53 54
54 /** 55 /**
55 * Synchronize kernel object 56 * Synchronize kernel object.
56 * @param wait Boolean wait set if current thread should wait as a result of sync operation 57 * @return True if the current thread should wait as a result of the sync
57 * @return Result of operation, 0 on success, otherwise error code
58 */ 58 */
59 virtual Result SyncRequest(bool* wait) { 59 virtual ResultVal<bool> SyncRequest() {
60 ERROR_LOG(KERNEL, "(UNIMPLEMENTED)"); 60 ERROR_LOG(KERNEL, "(UNIMPLEMENTED)");
61 return -1; 61 return UnimplementedFunction(ErrorModule::Kernel);
62 } 62 }
63 63
64 /** 64 /**
65 * Wait for kernel object to synchronize 65 * Wait for kernel object to synchronize.
66 * @param wait Boolean wait set if current thread should wait as a result of sync operation 66 * @return True if the current thread should wait as a result of the wait
67 * @return Result of operation, 0 on success, otherwise error code
68 */ 67 */
69 virtual Result WaitSynchronization(bool* wait) = 0; 68 virtual ResultVal<bool> WaitSynchronization() = 0;
70}; 69};
71 70
72class ObjectPool : NonCopyable { 71class ObjectPool : NonCopyable {
@@ -80,38 +79,29 @@ public:
80 static Object* CreateByIDType(int type); 79 static Object* CreateByIDType(int type);
81 80
82 template <class T> 81 template <class T>
83 u32 Destroy(Handle handle) { 82 void Destroy(Handle handle) {
84 u32 error; 83 if (Get<T>(handle)) {
85 if (Get<T>(handle, error)) {
86 occupied[handle - HANDLE_OFFSET] = false; 84 occupied[handle - HANDLE_OFFSET] = false;
87 delete pool[handle - HANDLE_OFFSET]; 85 delete pool[handle - HANDLE_OFFSET];
88 } 86 }
89 return error;
90 } 87 }
91 88
92 bool IsValid(Handle handle); 89 bool IsValid(Handle handle);
93 90
94 template <class T> 91 template <class T>
95 T* Get(Handle handle, u32& outError) { 92 T* Get(Handle handle) {
96 if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) { 93 if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) {
97 // Tekken 6 spams 0x80020001 gets wrong with no ill effects, also on the real PSP 94 if (handle != 0) {
98 if (handle != 0 && (u32)handle != 0x80020001) {
99 WARN_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle); 95 WARN_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle);
100 } 96 }
101 outError = 0;//T::GetMissingErrorCode(); 97 return nullptr;
102 return 0;
103 } else { 98 } else {
104 // Previously we had a dynamic_cast here, but since RTTI was disabled traditionally, 99 Object* t = pool[handle - HANDLE_OFFSET];
105 // it just acted as a static case and everything worked. This means that we will never 100 if (t->GetHandleType() != T::GetStaticHandleType()) {
106 // see the Wrong type object error below, but we'll just have to live with that danger.
107 T* t = static_cast<T*>(pool[handle - HANDLE_OFFSET]);
108 if (t == 0 || t->GetHandleType() != T::GetStaticHandleType()) {
109 WARN_LOG(KERNEL, "Kernel: Wrong object type for %i (%08x)", handle, handle); 101 WARN_LOG(KERNEL, "Kernel: Wrong object type for %i (%08x)", handle, handle);
110 outError = 0;//T::GetMissingErrorCode(); 102 return nullptr;
111 return 0;
112 } 103 }
113 outError = 0;//SCE_KERNEL_ERROR_OK; 104 return static_cast<T*>(t);
114 return t;
115 } 105 }
116 } 106 }
117 107
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 31129fd86..b303ba128 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -27,31 +27,20 @@ public:
27 std::vector<Handle> waiting_threads; ///< Threads that are waiting for the mutex 27 std::vector<Handle> waiting_threads; ///< Threads that are waiting for the mutex
28 std::string name; ///< Name of mutex (optional) 28 std::string name; ///< Name of mutex (optional)
29 29
30 /** 30 ResultVal<bool> SyncRequest() override {
31 * Synchronize kernel object
32 * @param wait Boolean wait set if current thread should wait as a result of sync operation
33 * @return Result of operation, 0 on success, otherwise error code
34 */
35 Result SyncRequest(bool* wait) override {
36 // TODO(bunnei): ImplementMe 31 // TODO(bunnei): ImplementMe
37 locked = true; 32 locked = true;
38 return 0; 33 return MakeResult<bool>(false);
39 } 34 }
40 35
41 /** 36 ResultVal<bool> WaitSynchronization() override {
42 * Wait for kernel object to synchronize
43 * @param wait Boolean wait set if current thread should wait as a result of sync operation
44 * @return Result of operation, 0 on success, otherwise error code
45 */
46 Result WaitSynchronization(bool* wait) override {
47 // TODO(bunnei): ImplementMe 37 // TODO(bunnei): ImplementMe
48 *wait = locked; 38 bool wait = locked;
49
50 if (locked) { 39 if (locked) {
51 Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle()); 40 Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle());
52 } 41 }
53 42
54 return 0; 43 return MakeResult<bool>(wait);
55 } 44 }
56}; 45};
57 46
@@ -119,15 +108,17 @@ bool ReleaseMutex(Mutex* mutex) {
119 * Releases a mutex 108 * Releases a mutex
120 * @param handle Handle to mutex to release 109 * @param handle Handle to mutex to release
121 */ 110 */
122Result ReleaseMutex(Handle handle) { 111ResultCode ReleaseMutex(Handle handle) {
123 Mutex* mutex = Kernel::g_object_pool.GetFast<Mutex>(handle); 112 Mutex* mutex = Kernel::g_object_pool.Get<Mutex>(handle);
124 113 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel);
125 _assert_msg_(KERNEL, (mutex != nullptr), "ReleaseMutex tried to release a nullptr mutex!");
126 114
127 if (!ReleaseMutex(mutex)) { 115 if (!ReleaseMutex(mutex)) {
128 return -1; 116 // TODO(yuriks): Verify error code, this one was pulled out of thin air. I'm not even sure
117 // what error condition this is supposed to be signaling.
118 return ResultCode(ErrorDescription::AlreadyDone, ErrorModule::Kernel,
119 ErrorSummary::NothingHappened, ErrorLevel::Temporary);
129 } 120 }
130 return 0; 121 return RESULT_SUCCESS;
131} 122}
132 123
133/** 124/**
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 313ba6fee..155449f95 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -13,9 +13,8 @@ namespace Kernel {
13/** 13/**
14 * Releases a mutex 14 * Releases a mutex
15 * @param handle Handle to mutex to release 15 * @param handle Handle to mutex to release
16 * @return Result of operation, 0 on success, otherwise error code
17 */ 16 */
18Result ReleaseMutex(Handle handle); 17ResultCode ReleaseMutex(Handle handle);
19 18
20/** 19/**
21 * Creates a mutex 20 * Creates a mutex
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 7ef3e54cc..cfcc0e0b7 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -16,15 +16,10 @@ public:
16 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; } 16 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; }
17 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::SharedMemory; } 17 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::SharedMemory; }
18 18
19 /** 19 ResultVal<bool> WaitSynchronization() override {
20 * Wait for kernel object to synchronize
21 * @param wait Boolean wait set if current thread should wait as a result of sync operation
22 * @return Result of operation, 0 on success, otherwise error code
23 */
24 Result WaitSynchronization(bool* wait) override {
25 // TODO(bunnei): ImplementMe 20 // TODO(bunnei): ImplementMe
26 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 21 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
27 return 0; 22 return UnimplementedFunction(ErrorModule::OS);
28 } 23 }
29 24
30 u32 base_address; ///< Address of shared memory block in RAM 25 u32 base_address; ///< Address of shared memory block in RAM
@@ -48,11 +43,6 @@ SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) {
48 return shared_memory; 43 return shared_memory;
49} 44}
50 45
51/**
52 * Creates a shared memory object
53 * @param name Optional name of shared memory object
54 * @return Handle of newly created shared memory object
55 */
56Handle CreateSharedMemory(const std::string& name) { 46Handle CreateSharedMemory(const std::string& name) {
57 Handle handle; 47 Handle handle;
58 CreateSharedMemory(handle, name); 48 CreateSharedMemory(handle, name);
@@ -67,39 +57,36 @@ Handle CreateSharedMemory(const std::string& name) {
67 * @param other_permissions Memory block map other permissions (specified by SVC field) 57 * @param other_permissions Memory block map other permissions (specified by SVC field)
68 * @return Result of operation, 0 on success, otherwise error code 58 * @return Result of operation, 0 on success, otherwise error code
69 */ 59 */
70Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, 60ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
71 MemoryPermission other_permissions) { 61 MemoryPermission other_permissions) {
72 62
73 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { 63 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) {
74 ERROR_LOG(KERNEL, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", 64 ERROR_LOG(KERNEL, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!",
75 handle, address); 65 handle, address);
76 return -1; 66 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
67 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
77 } 68 }
78 SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle); 69 SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle);
79 _assert_msg_(KERNEL, (shared_memory != nullptr), "handle 0x%08X is not valid!", handle); 70 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
80 71
81 shared_memory->base_address = address; 72 shared_memory->base_address = address;
82 shared_memory->permissions = permissions; 73 shared_memory->permissions = permissions;
83 shared_memory->other_permissions = other_permissions; 74 shared_memory->other_permissions = other_permissions;
84 75
85 return 0; 76 return RESULT_SUCCESS;
86} 77}
87 78
88/** 79ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) {
89 * Gets a pointer to the shared memory block 80 SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle);
90 * @param handle Shared memory block handle 81 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
91 * @param offset Offset from the start of the shared memory block to get pointer
92 * @return Pointer to the shared memory block from the specified offset
93 */
94u8* GetSharedMemoryPointer(Handle handle, u32 offset) {
95 SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle);
96 _assert_msg_(KERNEL, (shared_memory != nullptr), "handle 0x%08X is not valid!", handle);
97 82
98 if (0 != shared_memory->base_address) 83 if (0 != shared_memory->base_address)
99 return Memory::GetPointer(shared_memory->base_address + offset); 84 return MakeResult<u8*>(Memory::GetPointer(shared_memory->base_address + offset));
100 85
101 ERROR_LOG(KERNEL, "memory block handle=0x%08X not mapped!", handle); 86 ERROR_LOG(KERNEL, "memory block handle=0x%08X not mapped!", handle);
102 return nullptr; 87 // TODO(yuriks): Verify error code.
88 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
89 ErrorSummary::InvalidState, ErrorLevel::Permanent);
103} 90}
104 91
105} // namespace 92} // namespace
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 0aec03538..304cf5b67 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -32,9 +32,8 @@ Handle CreateSharedMemory(const std::string& name="Unknown");
32 * @param address Address in system memory to map shared memory block to 32 * @param address Address in system memory to map shared memory block to
33 * @param permissions Memory block map permissions (specified by SVC field) 33 * @param permissions Memory block map permissions (specified by SVC field)
34 * @param other_permissions Memory block map other permissions (specified by SVC field) 34 * @param other_permissions Memory block map other permissions (specified by SVC field)
35 * @return Result of operation, 0 on success, otherwise error code
36 */ 35 */
37Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, 36ResultCode MapSharedMemory(Handle handle, u32 address, MemoryPermission permissions,
38 MemoryPermission other_permissions); 37 MemoryPermission other_permissions);
39 38
40/** 39/**
@@ -43,6 +42,6 @@ Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
43 * @param offset Offset from the start of the shared memory block to get pointer 42 * @param offset Offset from the start of the shared memory block to get pointer
44 * @return Pointer to the shared memory block from the specified offset 43 * @return Pointer to the shared memory block from the specified offset
45 */ 44 */
46u8* GetSharedMemoryPointer(Handle handle, u32 offset); 45ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset);
47 46
48} // namespace 47} // namespace
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index cc70cbca7..f3f54a4e9 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -11,10 +11,11 @@
11#include "common/thread_queue_list.h" 11#include "common/thread_queue_list.h"
12 12
13#include "core/core.h" 13#include "core/core.h"
14#include "core/mem_map.h"
15#include "core/hle/hle.h" 14#include "core/hle/hle.h"
16#include "core/hle/kernel/kernel.h" 15#include "core/hle/kernel/kernel.h"
17#include "core/hle/kernel/thread.h" 16#include "core/hle/kernel/thread.h"
17#include "core/hle/result.h"
18#include "core/mem_map.h"
18 19
19namespace Kernel { 20namespace Kernel {
20 21
@@ -33,21 +34,17 @@ public:
33 inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } 34 inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; }
34 inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } 35 inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; }
35 36
36 /** 37 ResultVal<bool> WaitSynchronization() override {
37 * Wait for kernel object to synchronize 38 const bool wait = status != THREADSTATUS_DORMANT;
38 * @param wait Boolean wait set if current thread should wait as a result of sync operation 39 if (wait) {
39 * @return Result of operation, 0 on success, otherwise error code
40 */
41 Result WaitSynchronization(bool* wait) override {
42 if (status != THREADSTATUS_DORMANT) {
43 Handle thread = GetCurrentThreadHandle(); 40 Handle thread = GetCurrentThreadHandle();
44 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { 41 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
45 waiting_threads.push_back(thread); 42 waiting_threads.push_back(thread);
46 } 43 }
47 WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle()); 44 WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle());
48 *wait = true;
49 } 45 }
50 return 0; 46
47 return MakeResult<bool>(wait);
51 } 48 }
52 49
53 ThreadContext context; 50 ThreadContext context;
@@ -144,27 +141,22 @@ void ChangeReadyState(Thread* t, bool ready) {
144} 141}
145 142
146/// Verify that a thread has not been released from waiting 143/// Verify that a thread has not been released from waiting
147inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) { 144inline bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle) {
148 Thread* thread = g_object_pool.GetFast<Thread>(handle); 145 _dbg_assert_(KERNEL, thread != nullptr);
149 _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); 146 return type == thread->wait_type && wait_handle == thread->wait_handle;
150
151 if (type != thread->wait_type || wait_handle != thread->wait_handle)
152 return false;
153
154 return true;
155} 147}
156 148
157/// Stops the current thread 149/// Stops the current thread
158void StopThread(Handle handle, const char* reason) { 150ResultCode StopThread(Handle handle, const char* reason) {
159 Thread* thread = g_object_pool.GetFast<Thread>(handle); 151 Thread* thread = g_object_pool.Get<Thread>(handle);
160 _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); 152 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel);
161 153
162 ChangeReadyState(thread, false); 154 ChangeReadyState(thread, false);
163 thread->status = THREADSTATUS_DORMANT; 155 thread->status = THREADSTATUS_DORMANT;
164 for (size_t i = 0; i < thread->waiting_threads.size(); ++i) { 156 for (Handle waiting_handle : thread->waiting_threads) {
165 const Handle waiting_thread = thread->waiting_threads[i]; 157 Thread* waiting_thread = g_object_pool.Get<Thread>(waiting_handle);
166 if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) { 158 if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) {
167 ResumeThreadFromWait(waiting_thread); 159 ResumeThreadFromWait(waiting_handle);
168 } 160 }
169 } 161 }
170 thread->waiting_threads.clear(); 162 thread->waiting_threads.clear();
@@ -172,6 +164,8 @@ void StopThread(Handle handle, const char* reason) {
172 // Stopped threads are never waiting. 164 // Stopped threads are never waiting.
173 thread->wait_type = WAITTYPE_NONE; 165 thread->wait_type = WAITTYPE_NONE;
174 thread->wait_handle = 0; 166 thread->wait_handle = 0;
167
168 return RESULT_SUCCESS;
175} 169}
176 170
177/// Changes a threads state 171/// Changes a threads state
@@ -195,13 +189,15 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {
195 s32 priority = THREADPRIO_LOWEST; 189 s32 priority = THREADPRIO_LOWEST;
196 190
197 // Iterate through threads, find highest priority thread that is waiting to be arbitrated... 191 // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
198 for (const auto& handle : thread_queue) { 192 for (Handle handle : thread_queue) {
193 Thread* thread = g_object_pool.Get<Thread>(handle);
199 194
200 // TODO(bunnei): Verify arbiter address... 195 // TODO(bunnei): Verify arbiter address...
201 if (!VerifyWait(handle, WAITTYPE_ARB, arbiter)) 196 if (!VerifyWait(thread, WAITTYPE_ARB, arbiter))
202 continue; 197 continue;
203 198
204 Thread* thread = g_object_pool.GetFast<Thread>(handle); 199 if (thread == nullptr)
200 continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up.
205 if(thread->current_priority <= priority) { 201 if(thread->current_priority <= priority) {
206 highest_priority_thread = handle; 202 highest_priority_thread = handle;
207 priority = thread->current_priority; 203 priority = thread->current_priority;
@@ -218,10 +214,11 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {
218void ArbitrateAllThreads(u32 arbiter, u32 address) { 214void ArbitrateAllThreads(u32 arbiter, u32 address) {
219 215
220 // Iterate through threads, find highest priority thread that is waiting to be arbitrated... 216 // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
221 for (const auto& handle : thread_queue) { 217 for (Handle handle : thread_queue) {
218 Thread* thread = g_object_pool.Get<Thread>(handle);
222 219
223 // TODO(bunnei): Verify arbiter address... 220 // TODO(bunnei): Verify arbiter address...
224 if (VerifyWait(handle, WAITTYPE_ARB, arbiter)) 221 if (VerifyWait(thread, WAITTYPE_ARB, arbiter))
225 ResumeThreadFromWait(handle); 222 ResumeThreadFromWait(handle);
226 } 223 }
227} 224}
@@ -272,7 +269,7 @@ Thread* NextThread() {
272 if (next == 0) { 269 if (next == 0) {
273 return nullptr; 270 return nullptr;
274 } 271 }
275 return Kernel::g_object_pool.GetFast<Thread>(next); 272 return Kernel::g_object_pool.Get<Thread>(next);
276} 273}
277 274
278/** 275/**
@@ -289,8 +286,7 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
289 286
290/// Resumes a thread from waiting by marking it as "ready" 287/// Resumes a thread from waiting by marking it as "ready"
291void ResumeThreadFromWait(Handle handle) { 288void ResumeThreadFromWait(Handle handle) {
292 u32 error; 289 Thread* thread = Kernel::g_object_pool.Get<Thread>(handle);
293 Thread* thread = Kernel::g_object_pool.Get<Thread>(handle, error);
294 if (thread) { 290 if (thread) {
295 thread->status &= ~THREADSTATUS_WAIT; 291 thread->status &= ~THREADSTATUS_WAIT;
296 if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { 292 if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) {
@@ -378,19 +374,23 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3
378} 374}
379 375
380/// Get the priority of the thread specified by handle 376/// Get the priority of the thread specified by handle
381u32 GetThreadPriority(const Handle handle) { 377ResultVal<u32> GetThreadPriority(const Handle handle) {
382 Thread* thread = g_object_pool.GetFast<Thread>(handle); 378 Thread* thread = g_object_pool.Get<Thread>(handle);
383 _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); 379 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel);
384 return thread->current_priority; 380
381 return MakeResult<u32>(thread->current_priority);
385} 382}
386 383
387/// Set the priority of the thread specified by handle 384/// Set the priority of the thread specified by handle
388Result SetThreadPriority(Handle handle, s32 priority) { 385ResultCode SetThreadPriority(Handle handle, s32 priority) {
389 Thread* thread = nullptr; 386 Thread* thread = nullptr;
390 if (!handle) { 387 if (!handle) {
391 thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? 388 thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior?
392 } else { 389 } else {
393 thread = g_object_pool.GetFast<Thread>(handle); 390 thread = g_object_pool.Get<Thread>(handle);
391 if (thread == nullptr) {
392 return InvalidHandle(ErrorModule::Kernel);
393 }
394 } 394 }
395 _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); 395 _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!");
396 396
@@ -417,7 +417,7 @@ Result SetThreadPriority(Handle handle, s32 priority) {
417 thread_ready_queue.push_back(thread->current_priority, handle); 417 thread_ready_queue.push_back(thread->current_priority, handle);
418 } 418 }
419 419
420 return 0; 420 return RESULT_SUCCESS;
421} 421}
422 422
423/// Sets up the primary application thread 423/// Sets up the primary application thread
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 2a43797ee..ce63a70d3 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -6,6 +6,7 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "core/hle/kernel/kernel.h" 8#include "core/hle/kernel/kernel.h"
9#include "core/hle/result.h"
9 10
10enum ThreadPriority { 11enum ThreadPriority {
11 THREADPRIO_HIGHEST = 0, ///< Highest thread priority 12 THREADPRIO_HIGHEST = 0, ///< Highest thread priority
@@ -55,7 +56,7 @@ Handle SetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE);
55void Reschedule(); 56void Reschedule();
56 57
57/// Stops the current thread 58/// Stops the current thread
58void StopThread(Handle thread, const char* reason); 59ResultCode StopThread(Handle thread, const char* reason);
59 60
60/// Resumes a thread from waiting by marking it as "ready" 61/// Resumes a thread from waiting by marking it as "ready"
61void ResumeThreadFromWait(Handle handle); 62void ResumeThreadFromWait(Handle handle);
@@ -80,10 +81,10 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHa
80void WaitThread_Synchronization(); 81void WaitThread_Synchronization();
81 82
82/// Get the priority of the thread specified by handle 83/// Get the priority of the thread specified by handle
83u32 GetThreadPriority(const Handle handle); 84ResultVal<u32> GetThreadPriority(const Handle handle);
84 85
85/// Set the priority of the thread specified by handle 86/// Set the priority of the thread specified by handle
86Result SetThreadPriority(Handle handle, s32 priority); 87ResultCode SetThreadPriority(Handle handle, s32 priority);
87 88
88/// Initialize threading 89/// Initialize threading
89void ThreadingInit(); 90void ThreadingInit();