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/semaphore.cpp94
-rw-r--r--src/core/hle/kernel/semaphore.h32
2 files changed, 126 insertions, 0 deletions
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
new file mode 100644
index 000000000..6f56da8a9
--- /dev/null
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -0,0 +1,94 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+
3// Refer to the license.txt file included.
4
5#include <queue>
6
7#include "common/common.h"
8
9#include "core/hle/kernel/kernel.h"
10#include "core/hle/kernel/semaphore.h"
11#include "core/hle/kernel/thread.h"
12
13namespace Kernel {
14
15class Semaphore : public Object {
16public:
17 std::string GetTypeName() const override { return "Semaphore"; }
18 std::string GetName() const override { return name; }
19
20 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; }
21 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Semaphore; }
22
23 u32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
24 u32 available_count; ///< Number of free slots left in the semaphore
25 std::queue<Handle> waiting_threads; ///< Threads that are waiting for the semaphore
26 std::string name; ///< Name of semaphore (optional)
27
28 /**
29 * Tests whether a semaphore still has free slots
30 * @return Whether the semaphore is available
31 */
32 bool IsAvailable() const {
33 return available_count > 0;
34 }
35
36 ResultVal<bool> WaitSynchronization() override {
37 bool wait = !IsAvailable();
38
39 if (wait) {
40 Kernel::WaitCurrentThread(WAITTYPE_SEMA, GetHandle());
41 waiting_threads.push(GetCurrentThreadHandle());
42 } else {
43 --available_count;
44 }
45
46 return MakeResult<bool>(wait);
47 }
48};
49
50////////////////////////////////////////////////////////////////////////////////////////////////////
51
52ResultCode CreateSemaphore(Handle* handle, u32 initial_count,
53 u32 max_count, const std::string& name) {
54
55 if (initial_count > max_count)
56 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
57 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
58
59 Semaphore* semaphore = new Semaphore;
60 *handle = g_object_pool.Create(semaphore);
61
62 // When the semaphore is created, some slots are reserved for other threads,
63 // and the rest is reserved for the caller thread
64 semaphore->max_count = max_count;
65 semaphore->available_count = initial_count;
66 semaphore->name = name;
67
68 return RESULT_SUCCESS;
69}
70
71ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
72 Semaphore* semaphore = g_object_pool.Get<Semaphore>(handle);
73 if (semaphore == nullptr)
74 return InvalidHandle(ErrorModule::Kernel);
75
76 if (semaphore->max_count - semaphore->available_count < release_count)
77 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,
78 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
79
80 *count = semaphore->available_count;
81 semaphore->available_count += release_count;
82
83 // Notify some of the threads that the semaphore has been released
84 // stop once the semaphore is full again or there are no more waiting threads
85 while (!semaphore->waiting_threads.empty() && semaphore->IsAvailable()) {
86 Kernel::ResumeThreadFromWait(semaphore->waiting_threads.front());
87 semaphore->waiting_threads.pop();
88 --semaphore->available_count;
89 }
90
91 return RESULT_SUCCESS;
92}
93
94} // namespace
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
new file mode 100644
index 000000000..f0075fdb8
--- /dev/null
+++ b/src/core/hle/kernel/semaphore.h
@@ -0,0 +1,32 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9#include "core/hle/kernel/kernel.h"
10
11namespace Kernel {
12
13/**
14 * Creates a semaphore.
15 * @param handle Pointer to the handle of the newly created object
16 * @param initial_count Number of slots reserved for other threads
17 * @param max_count Maximum number of slots the semaphore can have
18 * @param name Optional name of semaphore
19 * @return ResultCode of the error
20 */
21ResultCode CreateSemaphore(Handle* handle, u32 initial_count, u32 max_count, const std::string& name = "Unknown");
22
23/**
24 * Releases a certain number of slots from a semaphore.
25 * @param count The number of free slots the semaphore had before this call
26 * @param handle The handle of the semaphore to release
27 * @param release_count The number of slots to release
28 * @return ResultCode of the error
29 */
30ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count);
31
32} // namespace