summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2014-10-23 01:20:01 -0200
committerGravatar Yuri Kunde Schlesner2014-11-24 17:08:36 -0200
commitc2588403c0b8cf198f13f903f626851c7e94266c (patch)
tree09d26cdae187a47338caf94943291c60b4a40a4c /src/core/hle/kernel
parentChange some SkyEye defines to const ints (diff)
downloadyuzu-c2588403c0b8cf198f13f903f626851c7e94266c.tar.gz
yuzu-c2588403c0b8cf198f13f903f626851c7e94266c.tar.xz
yuzu-c2588403c0b8cf198f13f903f626851c7e94266c.zip
HLE: Revamp error handling throrough the HLE code
All service calls in the CTR OS return result codes indicating the success or failure of the call. Previous to this commit, Citra's HLE emulation of services and the kernel universally either ignored errors or returned dummy -1 error codes. This commit makes an initial effort to provide an infrastructure for error reporting and propagation which can be use going forward to make HLE calls accurately return errors as the original system. A few parts of the code have been updated to use the new system where applicable. One part of this effort is the definition of the `ResultCode` type, which provides facilities for constructing and parsing error codes in the structured format used by the CTR. The `ResultVal` type builds on `ResultCode` by providing a container for values returned by function that can report errors. It enforces that correct error checking will be done on function returns by preventing the use of the return value if the function returned an error code. Currently this change is mostly internal since errors are still suppressed on the ARM<->HLE border, as a temporary compatibility hack. As functionality is implemented and tested this hack can be eventually removed.
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp10
-rw-r--r--src/core/hle/kernel/address_arbiter.h2
-rw-r--r--src/core/hle/kernel/archive.cpp147
-rw-r--r--src/core/hle/kernel/archive.h23
-rw-r--r--src/core/hle/kernel/event.cpp38
-rw-r--r--src/core/hle/kernel/event.h8
-rw-r--r--src/core/hle/kernel/kernel.h44
-rw-r--r--src/core/hle/kernel/mutex.cpp25
-rw-r--r--src/core/hle/kernel/mutex.h2
-rw-r--r--src/core/hle/kernel/shared_memory.cpp27
-rw-r--r--src/core/hle/kernel/shared_memory.h4
-rw-r--r--src/core/hle/kernel/thread.cpp51
-rw-r--r--src/core/hle/kernel/thread.h7
13 files changed, 187 insertions, 201 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 2b21657da..1e697fac1 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -30,17 +30,17 @@ public:
30 * @param wait Boolean wait set if current thread should wait as a result of sync operation 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 31 * @return Result of operation, 0 on success, otherwise error code
32 */ 32 */
33 Result WaitSynchronization(bool* wait) override { 33 ResultVal<bool> WaitSynchronization() override {
34 // TODO(bunnei): ImplementMe 34 // TODO(bunnei): ImplementMe
35 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 35 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
36 return 0; 36 return UnimplementedFunction(ErrorModule::OS);
37 } 37 }
38}; 38};
39 39
40//////////////////////////////////////////////////////////////////////////////////////////////////// 40////////////////////////////////////////////////////////////////////////////////////////////////////
41 41
42/// Arbitrate an address 42/// Arbitrate an address
43Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) { 43ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) {
44 switch (type) { 44 switch (type) {
45 45
46 // Signal thread(s) waiting for arbitrate address... 46 // Signal thread(s) waiting for arbitrate address...
@@ -65,9 +65,9 @@ Result ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 va
65 65
66 default: 66 default:
67 ERROR_LOG(KERNEL, "unknown type=%d", type); 67 ERROR_LOG(KERNEL, "unknown type=%d", type);
68 return -1; 68 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage);
69 } 69 }
70 return 0; 70 return RESULT_SUCCESS;
71} 71}
72 72
73/// Create an address arbiter 73/// 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..e11dddc84 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
@@ -56,7 +57,7 @@ public:
56 * @param wait Boolean wait set if current thread should wait as a result of sync operation 57 * @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 * @return Result of operation, 0 on success, otherwise error code
58 */ 59 */
59 Result SyncRequest(bool* wait) override { 60 ResultVal<bool> SyncRequest() override {
60 u32* cmd_buff = Service::GetCommandBuffer(); 61 u32* cmd_buff = Service::GetCommandBuffer();
61 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 62 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
62 63
@@ -106,11 +107,11 @@ public:
106 default: 107 default:
107 { 108 {
108 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); 109 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
109 return -1; 110 return UnimplementedFunction(ErrorModule::FS);
110 } 111 }
111 } 112 }
112 cmd_buff[1] = 0; // No error 113 cmd_buff[1] = 0; // No error
113 return 0; 114 return MakeResult<bool>(false);
114 } 115 }
115 116
116 /** 117 /**
@@ -118,10 +119,10 @@ public:
118 * @param wait Boolean wait set if current thread should wait as a result of sync operation 119 * @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 * @return Result of operation, 0 on success, otherwise error code
120 */ 121 */
121 Result WaitSynchronization(bool* wait) override { 122 ResultVal<bool> WaitSynchronization() override {
122 // TODO(bunnei): ImplementMe 123 // TODO(bunnei): ImplementMe
123 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 124 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
124 return 0; 125 return UnimplementedFunction(ErrorModule::FS);
125 } 126 }
126}; 127};
127 128
@@ -141,7 +142,7 @@ public:
141 * @param wait Boolean wait set if current thread should wait as a result of sync operation 142 * @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 * @return Result of operation, 0 on success, otherwise error code
143 */ 144 */
144 Result SyncRequest(bool* wait) override { 145 ResultVal<bool> SyncRequest() override {
145 u32* cmd_buff = Service::GetCommandBuffer(); 146 u32* cmd_buff = Service::GetCommandBuffer();
146 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 147 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
147 switch (cmd) { 148 switch (cmd) {
@@ -183,7 +184,8 @@ public:
183 case FileCommand::SetSize: 184 case FileCommand::SetSize:
184 { 185 {
185 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); 186 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); 187 DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu",
188 GetTypeName().c_str(), GetName().c_str(), size);
187 backend->SetSize(size); 189 backend->SetSize(size);
188 break; 190 break;
189 } 191 }
@@ -198,11 +200,12 @@ public:
198 // Unknown command... 200 // Unknown command...
199 default: 201 default:
200 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); 202 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
201 cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. 203 ResultCode error = UnimplementedFunction(ErrorModule::FS);
202 return -1; 204 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
205 return error;
203 } 206 }
204 cmd_buff[1] = 0; // No error 207 cmd_buff[1] = 0; // No error
205 return 0; 208 return MakeResult<bool>(false);
206 } 209 }
207 210
208 /** 211 /**
@@ -210,10 +213,10 @@ public:
210 * @param wait Boolean wait set if current thread should wait as a result of sync operation 213 * @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 214 * @return Result of operation, 0 on success, otherwise error code
212 */ 215 */
213 Result WaitSynchronization(bool* wait) override { 216 ResultVal<bool> WaitSynchronization() override {
214 // TODO(bunnei): ImplementMe 217 // TODO(bunnei): ImplementMe
215 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 218 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
216 return 0; 219 return UnimplementedFunction(ErrorModule::FS);
217 } 220 }
218}; 221};
219 222
@@ -233,7 +236,7 @@ public:
233 * @param wait Boolean wait set if current thread should wait as a result of sync operation 236 * @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 237 * @return Result of operation, 0 on success, otherwise error code
235 */ 238 */
236 Result SyncRequest(bool* wait) override { 239 ResultVal<bool> SyncRequest() override {
237 u32* cmd_buff = Service::GetCommandBuffer(); 240 u32* cmd_buff = Service::GetCommandBuffer();
238 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); 241 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
239 switch (cmd) { 242 switch (cmd) {
@@ -243,8 +246,9 @@ public:
243 { 246 {
244 u32 count = cmd_buff[1]; 247 u32 count = cmd_buff[1];
245 u32 address = cmd_buff[3]; 248 u32 address = cmd_buff[3];
246 FileSys::Entry* entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); 249 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); 250 DEBUG_LOG(KERNEL, "Read %s %s: count=%d",
251 GetTypeName().c_str(), GetName().c_str(), count);
248 252
249 // Number of entries actually read 253 // Number of entries actually read
250 cmd_buff[2] = backend->Read(count, entries); 254 cmd_buff[2] = backend->Read(count, entries);
@@ -261,11 +265,12 @@ public:
261 // Unknown command... 265 // Unknown command...
262 default: 266 default:
263 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); 267 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
264 cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. 268 ResultCode error = UnimplementedFunction(ErrorModule::FS);
265 return -1; 269 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
270 return error;
266 } 271 }
267 cmd_buff[1] = 0; // No error 272 cmd_buff[1] = 0; // No error
268 return 0; 273 return MakeResult<bool>(false);
269 } 274 }
270 275
271 /** 276 /**
@@ -273,10 +278,10 @@ public:
273 * @param wait Boolean wait set if current thread should wait as a result of sync operation 278 * @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 279 * @return Result of operation, 0 on success, otherwise error code
275 */ 280 */
276 Result WaitSynchronization(bool* wait) override { 281 ResultVal<bool> WaitSynchronization() override {
277 // TODO(bunnei): ImplementMe 282 // TODO(bunnei): ImplementMe
278 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 283 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
279 return 0; 284 return UnimplementedFunction(ErrorModule::FS);
280 } 285 }
281}; 286};
282 287
@@ -284,89 +289,59 @@ public:
284 289
285std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode 290std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode
286 291
287/** 292ResultVal<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); 293 auto itr = g_archive_map.find(id_code);
294 if (itr == g_archive_map.end()) { 294 if (itr == g_archive_map.end()) {
295 return 0; 295 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
296 ErrorSummary::NotFound, ErrorLevel::Permanent);
296 } 297 }
297 return itr->second; 298
299 return MakeResult<Handle>(itr->second);
298} 300}
299 301
300/** 302ResultCode 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); 303 auto itr = g_archive_map.find(id_code);
307 if (itr == g_archive_map.end()) { 304 if (itr == g_archive_map.end()) {
308 ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code); 305 ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code);
309 return -1; 306 return InvalidHandle(ErrorModule::FS);
310 } 307 }
311 308
312 INFO_LOG(KERNEL, "Closed archive %d", (int) id_code); 309 INFO_LOG(KERNEL, "Closed archive %d", (int) id_code);
313 return 0; 310 return RESULT_SUCCESS;
314} 311}
315 312
316/** 313/**
317 * Mounts an archive 314 * Mounts an archive
318 * @param archive Pointer to the archive to mount 315 * @param archive Pointer to the archive to mount
319 * @return Result of operation, 0 on success, otherwise error code 316 * @return Result of operation
320 */ 317 */
321Result MountArchive(Archive* archive) { 318ResultCode MountArchive(Archive* archive) {
322 FileSys::Archive::IdCode id_code = archive->backend->GetIdCode(); 319 FileSys::Archive::IdCode id_code = archive->backend->GetIdCode();
323 if (0 != OpenArchive(id_code)) { 320 ResultVal<Handle> archive_handle = OpenArchive(id_code);
321 if (archive_handle.Succeeded()) {
324 ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code); 322 ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code);
325 return -1; 323 return archive_handle.Code();
326 } 324 }
327 g_archive_map[id_code] = archive->GetHandle(); 325 g_archive_map[id_code] = archive->GetHandle();
328 INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str()); 326 INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str());
329 return 0; 327 return RESULT_SUCCESS;
330} 328}
331 329
332/** 330ResultCode 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; 331 Archive* archive = new Archive;
341 handle = Kernel::g_object_pool.Create(archive); 332 Handle handle = Kernel::g_object_pool.Create(archive);
342 archive->name = name; 333 archive->name = name;
343 archive->backend = backend; 334 archive->backend = backend;
344 335
345 MountArchive(archive); 336 ResultCode result = MountArchive(archive);
346 337 if (result.IsError()) {
347 return archive; 338 return result;
348} 339 }
349 340
350/** 341 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} 342}
361 343
362/** 344ResultVal<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 345 // 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. 346 // 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. 347 // Archives file handles are just reused and not actually freed until emulation shut down.
@@ -376,19 +351,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 351 // design. While the functionally of this is OK, our implementation decision to separate
377 // normal files from archive file pointers is very likely wrong. 352 // normal files from archive file pointers is very likely wrong.
378 // See https://github.com/citra-emu/citra/issues/205 353 // See https://github.com/citra-emu/citra/issues/205
379 return archive_handle; 354 return MakeResult<Handle>(archive_handle);
380 355
381 File* file = new File; 356 File* file = new File;
382 Handle handle = Kernel::g_object_pool.Create(file); 357 Handle handle = Kernel::g_object_pool.Create(file);
383 358
384 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); 359 Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle);
360 if (archive == nullptr) {
361 return InvalidHandle(ErrorModule::FS);
362 }
385 file->path = path; 363 file->path = path;
386 file->backend = archive->backend->OpenFile(path, mode); 364 file->backend = archive->backend->OpenFile(path, mode);
387 365
388 if (!file->backend) 366 if (!file->backend) {
389 return 0; 367 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
368 ErrorSummary::NotFound, ErrorLevel::Permanent);
369 }
390 370
391 return handle; 371 return MakeResult<Handle>(handle);
392} 372}
393 373
394/** 374/**
@@ -442,15 +422,18 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa
442 * @param path Path to the Directory inside of the Archive 422 * @param path Path to the Directory inside of the Archive
443 * @return Opened Directory object 423 * @return Opened Directory object
444 */ 424 */
445Handle OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { 425ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
446 Directory* directory = new Directory; 426 Directory* directory = new Directory;
447 Handle handle = Kernel::g_object_pool.Create(directory); 427 Handle handle = Kernel::g_object_pool.Create(directory);
448 428
449 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); 429 Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle);
430 if (archive == nullptr) {
431 return InvalidHandle(ErrorModule::FS);
432 }
450 directory->path = path; 433 directory->path = path;
451 directory->backend = archive->backend->OpenDirectory(path); 434 directory->backend = archive->backend->OpenDirectory(path);
452 435
453 return handle; 436 return MakeResult<Handle>(handle);
454} 437}
455 438
456/// Initialize archives 439/// 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..8a2925a3c 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -35,8 +35,8 @@ public:
35 * @param wait Boolean wait set if current thread should wait as a result of sync operation 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 36 * @return Result of operation, 0 on success, otherwise error code
37 */ 37 */
38 Result WaitSynchronization(bool* wait) override { 38 ResultVal<bool> WaitSynchronization() override {
39 *wait = locked; 39 bool wait = locked;
40 if (locked) { 40 if (locked) {
41 Handle thread = GetCurrentThreadHandle(); 41 Handle thread = GetCurrentThreadHandle();
42 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { 42 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
@@ -47,7 +47,7 @@ public:
47 if (reset_type != RESETTYPE_STICKY && !permanent_locked) { 47 if (reset_type != RESETTYPE_STICKY && !permanent_locked) {
48 locked = true; 48 locked = true;
49 } 49 }
50 return 0; 50 return MakeResult<bool>(wait);
51 } 51 }
52}; 52};
53 53
@@ -57,12 +57,12 @@ public:
57 * @param permanent_locked Boolean permanent locked value to set event 57 * @param permanent_locked Boolean permanent locked value to set event
58 * @return Result of operation, 0 on success, otherwise error code 58 * @return Result of operation, 0 on success, otherwise error code
59 */ 59 */
60Result SetPermanentLock(Handle handle, const bool permanent_locked) { 60ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) {
61 Event* evt = g_object_pool.GetFast<Event>(handle); 61 Event* evt = g_object_pool.Get<Event>(handle);
62 _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); 62 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
63 63
64 evt->permanent_locked = permanent_locked; 64 evt->permanent_locked = permanent_locked;
65 return 0; 65 return RESULT_SUCCESS;
66} 66}
67 67
68/** 68/**
@@ -71,14 +71,14 @@ Result SetPermanentLock(Handle handle, const bool permanent_locked) {
71 * @param locked Boolean locked value to set event 71 * @param locked Boolean locked value to set event
72 * @return Result of operation, 0 on success, otherwise error code 72 * @return Result of operation, 0 on success, otherwise error code
73 */ 73 */
74Result SetEventLocked(const Handle handle, const bool locked) { 74ResultCode SetEventLocked(const Handle handle, const bool locked) {
75 Event* evt = g_object_pool.GetFast<Event>(handle); 75 Event* evt = g_object_pool.Get<Event>(handle);
76 _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); 76 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
77 77
78 if (!evt->permanent_locked) { 78 if (!evt->permanent_locked) {
79 evt->locked = locked; 79 evt->locked = locked;
80 } 80 }
81 return 0; 81 return RESULT_SUCCESS;
82} 82}
83 83
84/** 84/**
@@ -86,9 +86,9 @@ Result SetEventLocked(const Handle handle, const bool locked) {
86 * @param handle Handle to event to signal 86 * @param handle Handle to event to signal
87 * @return Result of operation, 0 on success, otherwise error code 87 * @return Result of operation, 0 on success, otherwise error code
88 */ 88 */
89Result SignalEvent(const Handle handle) { 89ResultCode SignalEvent(const Handle handle) {
90 Event* evt = g_object_pool.GetFast<Event>(handle); 90 Event* evt = g_object_pool.Get<Event>(handle);
91 _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); 91 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
92 92
93 // Resume threads waiting for event to signal 93 // Resume threads waiting for event to signal
94 bool event_caught = false; 94 bool event_caught = false;
@@ -106,7 +106,7 @@ Result SignalEvent(const Handle handle) {
106 if (!evt->permanent_locked) { 106 if (!evt->permanent_locked) {
107 evt->locked = event_caught; 107 evt->locked = event_caught;
108 } 108 }
109 return 0; 109 return RESULT_SUCCESS;
110} 110}
111 111
112/** 112/**
@@ -114,14 +114,14 @@ Result SignalEvent(const Handle handle) {
114 * @param handle Handle to event to clear 114 * @param handle Handle to event to clear
115 * @return Result of operation, 0 on success, otherwise error code 115 * @return Result of operation, 0 on success, otherwise error code
116 */ 116 */
117Result ClearEvent(Handle handle) { 117ResultCode ClearEvent(Handle handle) {
118 Event* evt = g_object_pool.GetFast<Event>(handle); 118 Event* evt = g_object_pool.Get<Event>(handle);
119 _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); 119 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
120 120
121 if (!evt->permanent_locked) { 121 if (!evt->permanent_locked) {
122 evt->locked = true; 122 evt->locked = true;
123 } 123 }
124 return 0; 124 return RESULT_SUCCESS;
125} 125}
126 126
127/** 127/**
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 6add72897..6c17ed232 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -17,7 +17,7 @@ namespace Kernel {
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 18 * @return Result of operation, 0 on success, otherwise error code
19 */ 19 */
20Result SetEventLocked(const Handle handle, const bool locked); 20ResultCode SetEventLocked(const Handle handle, const bool locked);
21 21
22/** 22/**
23 * Hackish function to set an events permanent lock state, used to pass through synch blocks 23 * Hackish function to set an events permanent lock state, used to pass through synch blocks
@@ -25,21 +25,21 @@ Result SetEventLocked(const Handle handle, const bool locked);
25 * @param permanent_locked Boolean permanent locked value to set event 25 * @param permanent_locked Boolean permanent locked value to set event
26 * @return Result of operation, 0 on success, otherwise error code 26 * @return Result of operation, 0 on success, otherwise error code
27 */ 27 */
28Result SetPermanentLock(Handle handle, const bool permanent_locked); 28ResultCode SetPermanentLock(Handle handle, const bool permanent_locked);
29 29
30/** 30/**
31 * Signals an event 31 * Signals an event
32 * @param handle Handle to event to signal 32 * @param handle Handle to event to signal
33 * @return Result of operation, 0 on success, otherwise error code 33 * @return Result of operation, 0 on success, otherwise error code
34 */ 34 */
35Result SignalEvent(const Handle handle); 35ResultCode SignalEvent(const Handle handle);
36 36
37/** 37/**
38 * Clears an event 38 * Clears an event
39 * @param handle Handle to event to clear 39 * @param handle Handle to event to clear
40 * @return Result of operation, 0 on success, otherwise error code 40 * @return Result of operation, 0 on success, otherwise error code
41 */ 41 */
42Result ClearEvent(Handle handle); 42ResultCode ClearEvent(Handle handle);
43 43
44/** 44/**
45 * Creates an event 45 * 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..e4ff1ef40 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -32,10 +32,10 @@ public:
32 * @param wait Boolean wait set if current thread should wait as a result of sync operation 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 33 * @return Result of operation, 0 on success, otherwise error code
34 */ 34 */
35 Result SyncRequest(bool* wait) override { 35 ResultVal<bool> SyncRequest() override {
36 // TODO(bunnei): ImplementMe 36 // TODO(bunnei): ImplementMe
37 locked = true; 37 locked = true;
38 return 0; 38 return MakeResult<bool>(false);
39 } 39 }
40 40
41 /** 41 /**
@@ -43,15 +43,14 @@ public:
43 * @param wait Boolean wait set if current thread should wait as a result of sync operation 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 44 * @return Result of operation, 0 on success, otherwise error code
45 */ 45 */
46 Result WaitSynchronization(bool* wait) override { 46 ResultVal<bool> WaitSynchronization() override {
47 // TODO(bunnei): ImplementMe 47 // TODO(bunnei): ImplementMe
48 *wait = locked; 48 bool wait = locked;
49
50 if (locked) { 49 if (locked) {
51 Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle()); 50 Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle());
52 } 51 }
53 52
54 return 0; 53 return MakeResult<bool>(wait);
55 } 54 }
56}; 55};
57 56
@@ -119,15 +118,17 @@ bool ReleaseMutex(Mutex* mutex) {
119 * Releases a mutex 118 * Releases a mutex
120 * @param handle Handle to mutex to release 119 * @param handle Handle to mutex to release
121 */ 120 */
122Result ReleaseMutex(Handle handle) { 121ResultCode ReleaseMutex(Handle handle) {
123 Mutex* mutex = Kernel::g_object_pool.GetFast<Mutex>(handle); 122 Mutex* mutex = Kernel::g_object_pool.Get<Mutex>(handle);
124 123 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel);
125 _assert_msg_(KERNEL, (mutex != nullptr), "ReleaseMutex tried to release a nullptr mutex!");
126 124
127 if (!ReleaseMutex(mutex)) { 125 if (!ReleaseMutex(mutex)) {
128 return -1; 126 // TODO(yuriks): Verify error code, this one was pulled out of thin air. I'm not even sure
127 // what error condition this is supposed to be signaling.
128 return ResultCode(ErrorDescription::AlreadyDone, ErrorModule::Kernel,
129 ErrorSummary::NothingHappened, ErrorLevel::Temporary);
129 } 130 }
130 return 0; 131 return RESULT_SUCCESS;
131} 132}
132 133
133/** 134/**
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 313ba6fee..233d8c420 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -15,7 +15,7 @@ namespace Kernel {
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 16 * @return Result of operation, 0 on success, otherwise error code
17 */ 17 */
18Result ReleaseMutex(Handle handle); 18ResultCode ReleaseMutex(Handle handle);
19 19
20/** 20/**
21 * Creates a mutex 21 * Creates a mutex
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 7ef3e54cc..b91fc98da 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -21,10 +21,10 @@ public:
21 * @param wait Boolean wait set if current thread should wait as a result of sync operation 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 22 * @return Result of operation, 0 on success, otherwise error code
23 */ 23 */
24 Result WaitSynchronization(bool* wait) override { 24 ResultVal<bool> WaitSynchronization() override {
25 // TODO(bunnei): ImplementMe 25 // TODO(bunnei): ImplementMe
26 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 26 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
27 return 0; 27 return UnimplementedFunction(ErrorModule::OS);
28 } 28 }
29 29
30 u32 base_address; ///< Address of shared memory block in RAM 30 u32 base_address; ///< Address of shared memory block in RAM
@@ -67,22 +67,23 @@ Handle CreateSharedMemory(const std::string& name) {
67 * @param other_permissions Memory block map other permissions (specified by SVC field) 67 * @param other_permissions Memory block map other permissions (specified by SVC field)
68 * @return Result of operation, 0 on success, otherwise error code 68 * @return Result of operation, 0 on success, otherwise error code
69 */ 69 */
70Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, 70ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
71 MemoryPermission other_permissions) { 71 MemoryPermission other_permissions) {
72 72
73 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { 73 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!", 74 ERROR_LOG(KERNEL, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!",
75 handle, address); 75 handle, address);
76 return -1; 76 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
77 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
77 } 78 }
78 SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle); 79 SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle);
79 _assert_msg_(KERNEL, (shared_memory != nullptr), "handle 0x%08X is not valid!", handle); 80 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
80 81
81 shared_memory->base_address = address; 82 shared_memory->base_address = address;
82 shared_memory->permissions = permissions; 83 shared_memory->permissions = permissions;
83 shared_memory->other_permissions = other_permissions; 84 shared_memory->other_permissions = other_permissions;
84 85
85 return 0; 86 return RESULT_SUCCESS;
86} 87}
87 88
88/** 89/**
@@ -91,15 +92,17 @@ Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
91 * @param offset Offset from the start of the shared memory block to get pointer 92 * @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 * @return Pointer to the shared memory block from the specified offset
93 */ 94 */
94u8* GetSharedMemoryPointer(Handle handle, u32 offset) { 95ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) {
95 SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle); 96 SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle);
96 _assert_msg_(KERNEL, (shared_memory != nullptr), "handle 0x%08X is not valid!", handle); 97 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
97 98
98 if (0 != shared_memory->base_address) 99 if (0 != shared_memory->base_address)
99 return Memory::GetPointer(shared_memory->base_address + offset); 100 return MakeResult<u8*>(Memory::GetPointer(shared_memory->base_address + offset));
100 101
101 ERROR_LOG(KERNEL, "memory block handle=0x%08X not mapped!", handle); 102 ERROR_LOG(KERNEL, "memory block handle=0x%08X not mapped!", handle);
102 return nullptr; 103 // TODO(yuriks): Verify error code.
104 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
105 ErrorSummary::InvalidState, ErrorLevel::Permanent);
103} 106}
104 107
105} // namespace 108} // namespace
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 0aec03538..6ed427088 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -34,7 +34,7 @@ Handle CreateSharedMemory(const std::string& name="Unknown");
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 35 * @return Result of operation, 0 on success, otherwise error code
36 */ 36 */
37Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions, 37ResultCode MapSharedMemory(Handle handle, u32 address, MemoryPermission permissions,
38 MemoryPermission other_permissions); 38 MemoryPermission other_permissions);
39 39
40/** 40/**
@@ -43,6 +43,6 @@ Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
43 * @param offset Offset from the start of the shared memory block to get pointer 43 * @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 44 * @return Pointer to the shared memory block from the specified offset
45 */ 45 */
46u8* GetSharedMemoryPointer(Handle handle, u32 offset); 46ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset);
47 47
48} // namespace 48} // namespace
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index cc70cbca7..b01779f2e 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
@@ -38,16 +39,17 @@ public:
38 * @param wait Boolean wait set if current thread should wait as a result of sync operation 39 * @param wait Boolean wait set if current thread should wait as a result of sync operation
39 * @return Result of operation, 0 on success, otherwise error code 40 * @return Result of operation, 0 on success, otherwise error code
40 */ 41 */
41 Result WaitSynchronization(bool* wait) override { 42 ResultVal<bool> WaitSynchronization() override {
42 if (status != THREADSTATUS_DORMANT) { 43 if (status != THREADSTATUS_DORMANT) {
43 Handle thread = GetCurrentThreadHandle(); 44 Handle thread = GetCurrentThreadHandle();
44 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { 45 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
45 waiting_threads.push_back(thread); 46 waiting_threads.push_back(thread);
46 } 47 }
47 WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle()); 48 WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle());
48 *wait = true; 49 return MakeResult<bool>(true);
50 } else {
51 return MakeResult<bool>(false);
49 } 52 }
50 return 0;
51 } 53 }
52 54
53 ThreadContext context; 55 ThreadContext context;
@@ -144,9 +146,9 @@ void ChangeReadyState(Thread* t, bool ready) {
144} 146}
145 147
146/// Verify that a thread has not been released from waiting 148/// Verify that a thread has not been released from waiting
147inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) { 149inline bool VerifyWait(Handle handle, WaitType type, Handle wait_handle) {
148 Thread* thread = g_object_pool.GetFast<Thread>(handle); 150 Thread* thread = g_object_pool.Get<Thread>(handle);
149 _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); 151 _dbg_assert_(KERNEL, thread != nullptr);
150 152
151 if (type != thread->wait_type || wait_handle != thread->wait_handle) 153 if (type != thread->wait_type || wait_handle != thread->wait_handle)
152 return false; 154 return false;
@@ -155,9 +157,9 @@ inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle)
155} 157}
156 158
157/// Stops the current thread 159/// Stops the current thread
158void StopThread(Handle handle, const char* reason) { 160ResultCode StopThread(Handle handle, const char* reason) {
159 Thread* thread = g_object_pool.GetFast<Thread>(handle); 161 Thread* thread = g_object_pool.Get<Thread>(handle);
160 _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); 162 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel);
161 163
162 ChangeReadyState(thread, false); 164 ChangeReadyState(thread, false);
163 thread->status = THREADSTATUS_DORMANT; 165 thread->status = THREADSTATUS_DORMANT;
@@ -172,6 +174,8 @@ void StopThread(Handle handle, const char* reason) {
172 // Stopped threads are never waiting. 174 // Stopped threads are never waiting.
173 thread->wait_type = WAITTYPE_NONE; 175 thread->wait_type = WAITTYPE_NONE;
174 thread->wait_handle = 0; 176 thread->wait_handle = 0;
177
178 return RESULT_SUCCESS;
175} 179}
176 180
177/// Changes a threads state 181/// Changes a threads state
@@ -201,7 +205,9 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {
201 if (!VerifyWait(handle, WAITTYPE_ARB, arbiter)) 205 if (!VerifyWait(handle, WAITTYPE_ARB, arbiter))
202 continue; 206 continue;
203 207
204 Thread* thread = g_object_pool.GetFast<Thread>(handle); 208 Thread* thread = g_object_pool.Get<Thread>(handle);
209 if (thread == nullptr)
210 continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up.
205 if(thread->current_priority <= priority) { 211 if(thread->current_priority <= priority) {
206 highest_priority_thread = handle; 212 highest_priority_thread = handle;
207 priority = thread->current_priority; 213 priority = thread->current_priority;
@@ -272,7 +278,7 @@ Thread* NextThread() {
272 if (next == 0) { 278 if (next == 0) {
273 return nullptr; 279 return nullptr;
274 } 280 }
275 return Kernel::g_object_pool.GetFast<Thread>(next); 281 return Kernel::g_object_pool.Get<Thread>(next);
276} 282}
277 283
278/** 284/**
@@ -289,8 +295,7 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
289 295
290/// Resumes a thread from waiting by marking it as "ready" 296/// Resumes a thread from waiting by marking it as "ready"
291void ResumeThreadFromWait(Handle handle) { 297void ResumeThreadFromWait(Handle handle) {
292 u32 error; 298 Thread* thread = Kernel::g_object_pool.Get<Thread>(handle);
293 Thread* thread = Kernel::g_object_pool.Get<Thread>(handle, error);
294 if (thread) { 299 if (thread) {
295 thread->status &= ~THREADSTATUS_WAIT; 300 thread->status &= ~THREADSTATUS_WAIT;
296 if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { 301 if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) {
@@ -378,19 +383,23 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3
378} 383}
379 384
380/// Get the priority of the thread specified by handle 385/// Get the priority of the thread specified by handle
381u32 GetThreadPriority(const Handle handle) { 386ResultVal<u32> GetThreadPriority(const Handle handle) {
382 Thread* thread = g_object_pool.GetFast<Thread>(handle); 387 Thread* thread = g_object_pool.Get<Thread>(handle);
383 _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); 388 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel);
384 return thread->current_priority; 389
390 return MakeResult<u32>(thread->current_priority);
385} 391}
386 392
387/// Set the priority of the thread specified by handle 393/// Set the priority of the thread specified by handle
388Result SetThreadPriority(Handle handle, s32 priority) { 394ResultCode SetThreadPriority(Handle handle, s32 priority) {
389 Thread* thread = nullptr; 395 Thread* thread = nullptr;
390 if (!handle) { 396 if (!handle) {
391 thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? 397 thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior?
392 } else { 398 } else {
393 thread = g_object_pool.GetFast<Thread>(handle); 399 thread = g_object_pool.Get<Thread>(handle);
400 if (thread == nullptr) {
401 return InvalidHandle(ErrorModule::Kernel);
402 }
394 } 403 }
395 _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); 404 _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!");
396 405
@@ -417,7 +426,7 @@ Result SetThreadPriority(Handle handle, s32 priority) {
417 thread_ready_queue.push_back(thread->current_priority, handle); 426 thread_ready_queue.push_back(thread->current_priority, handle);
418 } 427 }
419 428
420 return 0; 429 return RESULT_SUCCESS;
421} 430}
422 431
423/// Sets up the primary application thread 432/// 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();