summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/function_wrappers.h14
-rw-r--r--src/core/hle/kernel/semaphore.cpp94
-rw-r--r--src/core/hle/kernel/semaphore.h32
-rw-r--r--src/core/hle/svc.cpp20
5 files changed, 160 insertions, 2 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 8f6792791..567d7454e 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -28,6 +28,7 @@ set(SRCS
28 hle/kernel/event.cpp 28 hle/kernel/event.cpp
29 hle/kernel/kernel.cpp 29 hle/kernel/kernel.cpp
30 hle/kernel/mutex.cpp 30 hle/kernel/mutex.cpp
31 hle/kernel/semaphore.cpp
31 hle/kernel/shared_memory.cpp 32 hle/kernel/shared_memory.cpp
32 hle/kernel/thread.cpp 33 hle/kernel/thread.cpp
33 hle/service/ac_u.cpp 34 hle/service/ac_u.cpp
@@ -106,6 +107,7 @@ set(HEADERS
106 hle/kernel/event.h 107 hle/kernel/event.h
107 hle/kernel/kernel.h 108 hle/kernel/kernel.h
108 hle/kernel/mutex.h 109 hle/kernel/mutex.h
110 hle/kernel/semaphore.h
109 hle/kernel/shared_memory.h 111 hle/kernel/shared_memory.h
110 hle/kernel/thread.h 112 hle/kernel/thread.h
111 hle/service/ac_u.h 113 hle/service/ac_u.h
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 3dbe25037..b44479b2f 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -114,6 +114,20 @@ template<s32 func(u32*, const char*)> void Wrap() {
114 FuncReturn(retval); 114 FuncReturn(retval);
115} 115}
116 116
117template<s32 func(u32*, s32, s32)> void Wrap() {
118 u32 param_1 = 0;
119 u32 retval = func(&param_1, PARAM(1), PARAM(2));
120 Core::g_app_core->SetReg(1, param_1);
121 FuncReturn(retval);
122}
123
124template<s32 func(s32*, u32, s32)> void Wrap() {
125 s32 param_1 = 0;
126 u32 retval = func(&param_1, PARAM(1), PARAM(2));
127 Core::g_app_core->SetReg(1, param_1);
128 FuncReturn(retval);
129}
130
117//////////////////////////////////////////////////////////////////////////////////////////////////// 131////////////////////////////////////////////////////////////////////////////////////////////////////
118// Function wrappers that return type u32 132// Function wrappers that return type u32
119 133
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
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index db0c42e74..f3595096e 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -12,6 +12,7 @@
12#include "core/hle/kernel/address_arbiter.h" 12#include "core/hle/kernel/address_arbiter.h"
13#include "core/hle/kernel/event.h" 13#include "core/hle/kernel/event.h"
14#include "core/hle/kernel/mutex.h" 14#include "core/hle/kernel/mutex.h"
15#include "core/hle/kernel/semaphore.h"
15#include "core/hle/kernel/shared_memory.h" 16#include "core/hle/kernel/shared_memory.h"
16#include "core/hle/kernel/thread.h" 17#include "core/hle/kernel/thread.h"
17 18
@@ -288,6 +289,21 @@ static Result GetThreadId(u32* thread_id, Handle handle) {
288 return result.raw; 289 return result.raw;
289} 290}
290 291
292/// Creates a semaphore
293static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) {
294 ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count);
295 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
296 initial_count, max_count, *semaphore);
297 return res.raw;
298}
299
300/// Releases a certain number of slots in a semaphore
301static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) {
302 LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore);
303 ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count);
304 return res.raw;
305}
306
291/// Query memory 307/// Query memory
292static Result QueryMemory(void* info, void* out, u32 addr) { 308static Result QueryMemory(void* info, void* out, u32 addr) {
293 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); 309 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr);
@@ -366,8 +382,8 @@ const HLE::FunctionDef SVC_Table[] = {
366 {0x12, nullptr, "Run"}, 382 {0x12, nullptr, "Run"},
367 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, 383 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"},
368 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, 384 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"},
369 {0x15, nullptr, "CreateSemaphore"}, 385 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"},
370 {0x16, nullptr, "ReleaseSemaphore"}, 386 {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"},
371 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, 387 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"},
372 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, 388 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"},
373 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, 389 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"},