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.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();