summaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2015-01-11 13:53:11 -0200
committerGravatar Yuri Kunde Schlesner2015-01-30 11:47:05 -0200
commitd9b19be1d9c1baa5e8b92c1960c14e435e6b532f (patch)
treeda083beea826952f0a9c07ab392992ef6ca84c5c /src/core/hle
parentKernel: Convert SharedMemory to not use Handles (diff)
downloadyuzu-d9b19be1d9c1baa5e8b92c1960c14e435e6b532f.tar.gz
yuzu-d9b19be1d9c1baa5e8b92c1960c14e435e6b532f.tar.xz
yuzu-d9b19be1d9c1baa5e8b92c1960c14e435e6b532f.zip
Kernel: Convert Semaphore to not use Handles
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/kernel/semaphore.cpp65
-rw-r--r--src/core/hle/kernel/semaphore.h57
-rw-r--r--src/core/hle/svc.cpp33
3 files changed, 88 insertions, 67 deletions
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 135d8fb2a..a9e406ef4 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <queue>
6
7#include "common/common.h" 5#include "common/common.h"
8 6
9#include "core/hle/kernel/kernel.h" 7#include "core/hle/kernel/kernel.h"
@@ -12,69 +10,50 @@
12 10
13namespace Kernel { 11namespace Kernel {
14 12
15class Semaphore : public WaitObject { 13ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
16public: 14 std::string name) {
17 std::string GetTypeName() const override { return "Semaphore"; }
18 std::string GetName() const override { return name; }
19
20 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
21 HandleType GetHandleType() const override { return HANDLE_TYPE; }
22
23 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
24 s32 available_count; ///< Number of free slots left in the semaphore
25 std::string name; ///< Name of semaphore (optional)
26
27 bool ShouldWait() override {
28 return available_count <= 0;
29 }
30
31 void Acquire() override {
32 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
33 --available_count;
34 }
35};
36
37////////////////////////////////////////////////////////////////////////////////////////////////////
38
39ResultCode CreateSemaphore(Handle* handle, s32 initial_count,
40 s32 max_count, const std::string& name) {
41 15
42 if (initial_count > max_count) 16 if (initial_count > max_count)
43 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, 17 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
44 ErrorSummary::WrongArgument, ErrorLevel::Permanent); 18 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
45 19
46 Semaphore* semaphore = new Semaphore; 20 SharedPtr<Semaphore> semaphore(new Semaphore);
47 // TOOD(yuriks): Fix error reporting 21 // TOOD(yuriks): Don't create Handle (see Thread::Create())
48 *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE); 22 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore));
49 23
50 // When the semaphore is created, some slots are reserved for other threads, 24 // When the semaphore is created, some slots are reserved for other threads,
51 // and the rest is reserved for the caller thread 25 // and the rest is reserved for the caller thread
52 semaphore->max_count = max_count; 26 semaphore->max_count = max_count;
53 semaphore->available_count = initial_count; 27 semaphore->available_count = initial_count;
54 semaphore->name = name; 28 semaphore->name = std::move(name);
55 29
56 return RESULT_SUCCESS; 30 return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore));
57} 31}
58 32
59ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { 33bool Semaphore::ShouldWait() {
60 Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle).get(); 34 return available_count <= 0;
61 if (semaphore == nullptr) 35}
62 return InvalidHandle(ErrorModule::Kernel); 36
37void Semaphore::Acquire() {
38 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
39 --available_count;
40}
63 41
64 if (semaphore->max_count - semaphore->available_count < release_count) 42ResultVal<s32> Semaphore::Release(s32 release_count) {
43 if (max_count - available_count < release_count)
65 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, 44 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,
66 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 45 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
67 46
68 *count = semaphore->available_count; 47 s32 previous_count = available_count;
69 semaphore->available_count += release_count; 48 available_count += release_count;
70 49
71 // Notify some of the threads that the semaphore has been released 50 // Notify some of the threads that the semaphore has been released
72 // stop once the semaphore is full again or there are no more waiting threads 51 // stop once the semaphore is full again or there are no more waiting threads
73 while (!semaphore->ShouldWait() && semaphore->WakeupNextThread() != nullptr) { 52 while (!ShouldWait() && WakeupNextThread() != nullptr) {
74 semaphore->Acquire(); 53 Acquire();
75 } 54 }
76 55
77 return RESULT_SUCCESS; 56 return MakeResult<s32>(previous_count);
78} 57}
79 58
80} // namespace 59} // namespace
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index 8644ecf0c..b7f22b86e 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -4,29 +4,50 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <queue>
8#include <string>
9
7#include "common/common_types.h" 10#include "common/common_types.h"
8 11
9#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
10 13
11namespace Kernel { 14namespace Kernel {
12 15
13/** 16class Semaphore : public WaitObject {
14 * Creates a semaphore. 17public:
15 * @param handle Pointer to the handle of the newly created object 18 /**
16 * @param initial_count Number of slots reserved for other threads 19 * Creates a semaphore.
17 * @param max_count Maximum number of slots the semaphore can have 20 * @param handle Pointer to the handle of the newly created object
18 * @param name Optional name of semaphore 21 * @param initial_count Number of slots reserved for other threads
19 * @return ResultCode of the error 22 * @param max_count Maximum number of slots the semaphore can have
20 */ 23 * @param name Optional name of semaphore
21ResultCode CreateSemaphore(Handle* handle, s32 initial_count, s32 max_count, const std::string& name = "Unknown"); 24 * @return The created semaphore
22 25 */
23/** 26 static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count,
24 * Releases a certain number of slots from a semaphore. 27 std::string name = "Unknown");
25 * @param count The number of free slots the semaphore had before this call 28
26 * @param handle The handle of the semaphore to release 29 std::string GetTypeName() const override { return "Semaphore"; }
27 * @param release_count The number of slots to release 30 std::string GetName() const override { return name; }
28 * @return ResultCode of the error 31
29 */ 32 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
30ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count); 33 HandleType GetHandleType() const override { return HANDLE_TYPE; }
34
35 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
36 s32 available_count; ///< Number of free slots left in the semaphore
37 std::string name; ///< Name of semaphore (optional)
38
39 bool ShouldWait() override;
40 void Acquire() override;
41
42 /**
43 * Releases a certain number of slots from a semaphore.
44 * @param release_count The number of slots to release
45 * @return The number of free slots the semaphore had before this call
46 */
47 ResultVal<s32> Release(s32 release_count);
48
49private:
50 Semaphore() = default;
51};
31 52
32} // namespace 53} // namespace
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 165da0402..6cbe38bc3 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -374,17 +374,38 @@ static Result GetThreadId(u32* thread_id, Handle handle) {
374 374
375/// Creates a semaphore 375/// Creates a semaphore
376static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { 376static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) {
377 ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count); 377 using Kernel::Semaphore;
378
379 ResultVal<SharedPtr<Semaphore>> semaphore_res = Semaphore::Create(initial_count, max_count);
380 if (semaphore_res.Failed())
381 return semaphore_res.Code().raw;
382
383 ResultVal<Handle> handle_res = Kernel::g_handle_table.Create(*semaphore_res);
384 if (handle_res.Failed())
385 return handle_res.Code().raw;
386
387 *semaphore = *handle_res;
378 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", 388 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
379 initial_count, max_count, *semaphore); 389 initial_count, max_count, *semaphore);
380 return res.raw; 390 return RESULT_SUCCESS.raw;
381} 391}
382 392
383/// Releases a certain number of slots in a semaphore 393/// Releases a certain number of slots in a semaphore
384static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) { 394static Result ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
385 LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore); 395 using Kernel::Semaphore;
386 ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count); 396
387 return res.raw; 397 LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, handle);
398
399 SharedPtr<Semaphore> semaphore = Kernel::g_handle_table.Get<Semaphore>(handle);
400 if (semaphore == nullptr)
401 return InvalidHandle(ErrorModule::Kernel).raw;
402
403 ResultVal<s32> release_res = semaphore->Release(release_count);
404 if (release_res.Failed())
405 return release_res.Code().raw;
406
407 *count = *release_res;
408 return RESULT_SUCCESS.raw;
388} 409}
389 410
390/// Query memory 411/// Query memory