summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/audio_core/command_generator.cpp5
-rw-r--r--src/core/CMakeLists.txt5
-rw-r--r--src/core/crypto/key_manager.cpp5
-rw-r--r--src/core/hle/kernel/k_affinity_mask.h2
-rw-r--r--src/core/hle/kernel/k_light_condition_variable.h57
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp152
-rw-r--r--src/core/hle/kernel/k_resource_limit.h81
-rw-r--r--src/core/hle/kernel/k_thread.cpp4
-rw-r--r--src/core/hle/kernel/kernel.cpp26
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/kernel/memory/page_table.cpp10
-rw-r--r--src/core/hle/kernel/process.cpp24
-rw-r--r--src/core/hle/kernel/process.h6
-rw-r--r--src/core/hle/kernel/resource_limit.cpp73
-rw-r--r--src/core/hle/kernel/resource_limit.h106
-rw-r--r--src/core/hle/kernel/svc.cpp25
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp10
-rw-r--r--src/core/settings.cpp3
-rw-r--r--src/video_core/host_shaders/CMakeLists.txt20
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp6
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp2
21 files changed, 386 insertions, 240 deletions
diff --git a/src/audio_core/command_generator.cpp b/src/audio_core/command_generator.cpp
index a4a9a757d..5b1065520 100644
--- a/src/audio_core/command_generator.cpp
+++ b/src/audio_core/command_generator.cpp
@@ -383,11 +383,14 @@ void CommandGenerator::GenerateI3dl2ReverbEffectCommand(s32 mix_buffer_offset, E
383 const auto channel_count = params.channel_count; 383 const auto channel_count = params.channel_count;
384 for (s32 i = 0; i < channel_count; i++) { 384 for (s32 i = 0; i < channel_count; i++) {
385 // TODO(ogniK): Actually implement reverb 385 // TODO(ogniK): Actually implement reverb
386 /*
386 if (params.input[i] != params.output[i]) { 387 if (params.input[i] != params.output[i]) {
387 const auto* input = GetMixBuffer(mix_buffer_offset + params.input[i]); 388 const auto* input = GetMixBuffer(mix_buffer_offset + params.input[i]);
388 auto* output = GetMixBuffer(mix_buffer_offset + params.output[i]); 389 auto* output = GetMixBuffer(mix_buffer_offset + params.output[i]);
389 ApplyMix<1>(output, input, 32768, worker_params.sample_count); 390 ApplyMix<1>(output, input, 32768, worker_params.sample_count);
390 } 391 }*/
392 auto* output = GetMixBuffer(mix_buffer_offset + params.output[i]);
393 std::memset(output, 0, worker_params.sample_count * sizeof(s32));
391 } 394 }
392} 395}
393 396
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 397cc028f..0ee02c81d 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -160,9 +160,12 @@ add_library(core STATIC
160 hle/kernel/k_affinity_mask.h 160 hle/kernel/k_affinity_mask.h
161 hle/kernel/k_condition_variable.cpp 161 hle/kernel/k_condition_variable.cpp
162 hle/kernel/k_condition_variable.h 162 hle/kernel/k_condition_variable.h
163 hle/kernel/k_light_condition_variable.h
163 hle/kernel/k_light_lock.cpp 164 hle/kernel/k_light_lock.cpp
164 hle/kernel/k_light_lock.h 165 hle/kernel/k_light_lock.h
165 hle/kernel/k_priority_queue.h 166 hle/kernel/k_priority_queue.h
167 hle/kernel/k_resource_limit.cpp
168 hle/kernel/k_resource_limit.h
166 hle/kernel/k_scheduler.cpp 169 hle/kernel/k_scheduler.cpp
167 hle/kernel/k_scheduler.h 170 hle/kernel/k_scheduler.h
168 hle/kernel/k_scheduler_lock.h 171 hle/kernel/k_scheduler_lock.h
@@ -203,8 +206,6 @@ add_library(core STATIC
203 hle/kernel/process_capability.h 206 hle/kernel/process_capability.h
204 hle/kernel/readable_event.cpp 207 hle/kernel/readable_event.cpp
205 hle/kernel/readable_event.h 208 hle/kernel/readable_event.h
206 hle/kernel/resource_limit.cpp
207 hle/kernel/resource_limit.h
208 hle/kernel/server_port.cpp 209 hle/kernel/server_port.cpp
209 hle/kernel/server_port.h 210 hle/kernel/server_port.h
210 hle/kernel/server_session.cpp 211 hle/kernel/server_session.cpp
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index cebe2ce37..ad116dcc0 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -568,6 +568,11 @@ KeyManager::KeyManager() {
568 // Initialize keys 568 // Initialize keys
569 const std::string hactool_keys_dir = Common::FS::GetHactoolConfigurationPath(); 569 const std::string hactool_keys_dir = Common::FS::GetHactoolConfigurationPath();
570 const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir); 570 const std::string yuzu_keys_dir = Common::FS::GetUserPath(Common::FS::UserPath::KeysDir);
571
572 if (!Common::FS::Exists(yuzu_keys_dir)) {
573 Common::FS::CreateDir(yuzu_keys_dir);
574 }
575
571 if (Settings::values.use_dev_keys) { 576 if (Settings::values.use_dev_keys) {
572 dev_mode = true; 577 dev_mode = true;
573 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "dev.keys", false); 578 AttemptLoadKeyFile(yuzu_keys_dir, hactool_keys_dir, "dev.keys", false);
diff --git a/src/core/hle/kernel/k_affinity_mask.h b/src/core/hle/kernel/k_affinity_mask.h
index dd73781cd..b906895fc 100644
--- a/src/core/hle/kernel/k_affinity_mask.h
+++ b/src/core/hle/kernel/k_affinity_mask.h
@@ -27,7 +27,7 @@ public:
27 } 27 }
28 28
29 [[nodiscard]] constexpr bool GetAffinity(s32 core) const { 29 [[nodiscard]] constexpr bool GetAffinity(s32 core) const {
30 return this->mask & GetCoreBit(core); 30 return (this->mask & GetCoreBit(core)) != 0;
31 } 31 }
32 32
33 constexpr void SetAffinity(s32 core, bool set) { 33 constexpr void SetAffinity(s32 core, bool set) {
diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h
new file mode 100644
index 000000000..362d0db28
--- /dev/null
+++ b/src/core/hle/kernel/k_light_condition_variable.h
@@ -0,0 +1,57 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#pragma once
9
10#include "common/common_types.h"
11#include "core/hle/kernel/k_scheduler.h"
12#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
13#include "core/hle/kernel/k_thread_queue.h"
14#include "core/hle/kernel/time_manager.h"
15
16namespace Kernel {
17class KernelCore;
18
19class KLightConditionVariable {
20public:
21 explicit KLightConditionVariable(KernelCore& kernel) : thread_queue(kernel), kernel(kernel) {}
22
23 void Wait(KLightLock* lock, s64 timeout = -1) {
24 WaitImpl(lock, timeout);
25 lock->Lock();
26 }
27
28 void Broadcast() {
29 KScopedSchedulerLock lk{kernel};
30 while (thread_queue.WakeupFrontThread() != nullptr) {
31 // We want to signal all threads, and so should continue waking up until there's nothing
32 // to wake.
33 }
34 }
35
36private:
37 void WaitImpl(KLightLock* lock, s64 timeout) {
38 KThread* owner = GetCurrentThreadPointer(kernel);
39
40 // Sleep the thread.
41 {
42 KScopedSchedulerLockAndSleep lk(kernel, owner, timeout);
43 lock->Unlock();
44
45 if (!thread_queue.SleepThread(owner)) {
46 lk.CancelSleep();
47 return;
48 }
49 }
50
51 // Cancel the task that the sleep setup.
52 kernel.TimeManager().UnscheduleTimeEvent(owner);
53 }
54 KThreadQueue thread_queue;
55 KernelCore& kernel;
56};
57} // namespace Kernel
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
new file mode 100644
index 000000000..ab2ab683f
--- /dev/null
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -0,0 +1,152 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#include "common/assert.h"
9#include "core/core.h"
10#include "core/core_timing.h"
11#include "core/core_timing_util.h"
12#include "core/hle/kernel/k_resource_limit.h"
13#include "core/hle/kernel/svc_results.h"
14
15namespace Kernel {
16constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
17
18KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system)
19 : Object{kernel}, lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {}
20KResourceLimit::~KResourceLimit() = default;
21
22s64 KResourceLimit::GetLimitValue(LimitableResource which) const {
23 const auto index = static_cast<std::size_t>(which);
24 s64 value{};
25 {
26 KScopedLightLock lk{lock};
27 value = limit_values[index];
28 ASSERT(value >= 0);
29 ASSERT(current_values[index] <= limit_values[index]);
30 ASSERT(current_hints[index] <= current_values[index]);
31 }
32 return value;
33}
34
35s64 KResourceLimit::GetCurrentValue(LimitableResource which) const {
36 const auto index = static_cast<std::size_t>(which);
37 s64 value{};
38 {
39 KScopedLightLock lk{lock};
40 value = current_values[index];
41 ASSERT(value >= 0);
42 ASSERT(current_values[index] <= limit_values[index]);
43 ASSERT(current_hints[index] <= current_values[index]);
44 }
45 return value;
46}
47
48s64 KResourceLimit::GetPeakValue(LimitableResource which) const {
49 const auto index = static_cast<std::size_t>(which);
50 s64 value{};
51 {
52 KScopedLightLock lk{lock};
53 value = peak_values[index];
54 ASSERT(value >= 0);
55 ASSERT(current_values[index] <= limit_values[index]);
56 ASSERT(current_hints[index] <= current_values[index]);
57 }
58 return value;
59}
60
61s64 KResourceLimit::GetFreeValue(LimitableResource which) const {
62 const auto index = static_cast<std::size_t>(which);
63 s64 value{};
64 {
65 KScopedLightLock lk(lock);
66 ASSERT(current_values[index] >= 0);
67 ASSERT(current_values[index] <= limit_values[index]);
68 ASSERT(current_hints[index] <= current_values[index]);
69 value = limit_values[index] - current_values[index];
70 }
71
72 return value;
73}
74
75ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
76 const auto index = static_cast<std::size_t>(which);
77 KScopedLightLock lk(lock);
78 R_UNLESS(current_values[index] <= value, Svc::ResultInvalidState);
79
80 limit_values[index] = value;
81
82 return RESULT_SUCCESS;
83}
84
85bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
86 return Reserve(which, value, system.CoreTiming().GetGlobalTimeNs().count() + DefaultTimeout);
87}
88
89bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
90 ASSERT(value >= 0);
91 const auto index = static_cast<std::size_t>(which);
92 KScopedLightLock lk(lock);
93
94 ASSERT(current_hints[index] <= current_values[index]);
95 if (current_hints[index] >= limit_values[index]) {
96 return false;
97 }
98
99 // Loop until we reserve or run out of time.
100 while (true) {
101 ASSERT(current_values[index] <= limit_values[index]);
102 ASSERT(current_hints[index] <= current_values[index]);
103
104 // If we would overflow, don't allow to succeed.
105 if (current_values[index] + value <= current_values[index]) {
106 break;
107 }
108
109 if (current_values[index] + value <= limit_values[index]) {
110 current_values[index] += value;
111 current_hints[index] += value;
112 peak_values[index] = std::max(peak_values[index], current_values[index]);
113 return true;
114 }
115
116 if (current_hints[index] + value <= limit_values[index] &&
117 (timeout < 0 || system.CoreTiming().GetGlobalTimeNs().count() < timeout)) {
118 waiter_count++;
119 cond_var.Wait(&lock, timeout);
120 waiter_count--;
121 } else {
122 break;
123 }
124 }
125
126 return false;
127}
128
129void KResourceLimit::Release(LimitableResource which, s64 value) {
130 Release(which, value, value);
131}
132
133void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) {
134 ASSERT(value >= 0);
135 ASSERT(hint >= 0);
136
137 const auto index = static_cast<std::size_t>(which);
138 KScopedLightLock lk(lock);
139 ASSERT(current_values[index] <= limit_values[index]);
140 ASSERT(current_hints[index] <= current_values[index]);
141 ASSERT(value <= current_values[index]);
142 ASSERT(hint <= current_hints[index]);
143
144 current_values[index] -= value;
145 current_hints[index] -= hint;
146
147 if (waiter_count != 0) {
148 cond_var.Broadcast();
149 }
150}
151
152} // namespace Kernel
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
new file mode 100644
index 000000000..58ae456f1
--- /dev/null
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -0,0 +1,81 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#pragma once
9
10#include <array>
11#include "common/common_types.h"
12#include "core/hle/kernel/k_light_condition_variable.h"
13#include "core/hle/kernel/k_light_lock.h"
14#include "core/hle/kernel/object.h"
15
16union ResultCode;
17
18namespace Core {
19class System;
20}
21
22namespace Kernel {
23class KernelCore;
24enum class LimitableResource : u32 {
25 PhysicalMemory = 0,
26 Threads = 1,
27 Events = 2,
28 TransferMemory = 3,
29 Sessions = 4,
30
31 Count,
32};
33
34constexpr bool IsValidResourceType(LimitableResource type) {
35 return type < LimitableResource::Count;
36}
37
38class KResourceLimit final : public Object {
39public:
40 explicit KResourceLimit(KernelCore& kernel, Core::System& system);
41 ~KResourceLimit();
42
43 s64 GetLimitValue(LimitableResource which) const;
44 s64 GetCurrentValue(LimitableResource which) const;
45 s64 GetPeakValue(LimitableResource which) const;
46 s64 GetFreeValue(LimitableResource which) const;
47
48 ResultCode SetLimitValue(LimitableResource which, s64 value);
49
50 bool Reserve(LimitableResource which, s64 value);
51 bool Reserve(LimitableResource which, s64 value, s64 timeout);
52 void Release(LimitableResource which, s64 value);
53 void Release(LimitableResource which, s64 value, s64 hint);
54
55 std::string GetTypeName() const override {
56 return "KResourceLimit";
57 }
58 std::string GetName() const override {
59 return GetTypeName();
60 }
61
62 static constexpr HandleType HANDLE_TYPE = HandleType::ResourceLimit;
63 HandleType GetHandleType() const override {
64 return HANDLE_TYPE;
65 }
66
67 virtual void Finalize() override {}
68
69private:
70 using ResourceArray = std::array<s64, static_cast<std::size_t>(LimitableResource::Count)>;
71 ResourceArray limit_values{};
72 ResourceArray current_values{};
73 ResourceArray current_hints{};
74 ResourceArray peak_values{};
75 mutable KLightLock lock;
76 s32 waiter_count{};
77 KLightConditionVariable cond_var;
78 KernelCore& kernel;
79 Core::System& system;
80};
81} // namespace Kernel
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index aa100e139..b59259c4f 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -21,6 +21,7 @@
21#include "core/hle/kernel/errors.h" 21#include "core/hle/kernel/errors.h"
22#include "core/hle/kernel/handle_table.h" 22#include "core/hle/kernel/handle_table.h"
23#include "core/hle/kernel/k_condition_variable.h" 23#include "core/hle/kernel/k_condition_variable.h"
24#include "core/hle/kernel/k_resource_limit.h"
24#include "core/hle/kernel/k_scheduler.h" 25#include "core/hle/kernel/k_scheduler.h"
25#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 26#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
26#include "core/hle/kernel/k_thread.h" 27#include "core/hle/kernel/k_thread.h"
@@ -29,7 +30,6 @@
29#include "core/hle/kernel/memory/memory_layout.h" 30#include "core/hle/kernel/memory/memory_layout.h"
30#include "core/hle/kernel/object.h" 31#include "core/hle/kernel/object.h"
31#include "core/hle/kernel/process.h" 32#include "core/hle/kernel/process.h"
32#include "core/hle/kernel/resource_limit.h"
33#include "core/hle/kernel/svc_results.h" 33#include "core/hle/kernel/svc_results.h"
34#include "core/hle/kernel/time_manager.h" 34#include "core/hle/kernel/time_manager.h"
35#include "core/hle/result.h" 35#include "core/hle/result.h"
@@ -247,7 +247,7 @@ void KThread::Finalize() {
247 // Decrement the parent process's thread count. 247 // Decrement the parent process's thread count.
248 if (parent != nullptr) { 248 if (parent != nullptr) {
249 parent->DecrementThreadCount(); 249 parent->DecrementThreadCount();
250 parent->GetResourceLimit()->Release(ResourceType::Threads, 1); 250 parent->GetResourceLimit()->Release(LimitableResource::Threads, 1);
251 } 251 }
252} 252}
253 253
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index df309d523..b20c2d13a 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -28,6 +28,7 @@
28#include "core/hle/kernel/client_port.h" 28#include "core/hle/kernel/client_port.h"
29#include "core/hle/kernel/errors.h" 29#include "core/hle/kernel/errors.h"
30#include "core/hle/kernel/handle_table.h" 30#include "core/hle/kernel/handle_table.h"
31#include "core/hle/kernel/k_resource_limit.h"
31#include "core/hle/kernel/k_scheduler.h" 32#include "core/hle/kernel/k_scheduler.h"
32#include "core/hle/kernel/k_thread.h" 33#include "core/hle/kernel/k_thread.h"
33#include "core/hle/kernel/kernel.h" 34#include "core/hle/kernel/kernel.h"
@@ -36,7 +37,6 @@
36#include "core/hle/kernel/memory/slab_heap.h" 37#include "core/hle/kernel/memory/slab_heap.h"
37#include "core/hle/kernel/physical_core.h" 38#include "core/hle/kernel/physical_core.h"
38#include "core/hle/kernel/process.h" 39#include "core/hle/kernel/process.h"
39#include "core/hle/kernel/resource_limit.h"
40#include "core/hle/kernel/service_thread.h" 40#include "core/hle/kernel/service_thread.h"
41#include "core/hle/kernel/shared_memory.h" 41#include "core/hle/kernel/shared_memory.h"
42#include "core/hle/kernel/time_manager.h" 42#include "core/hle/kernel/time_manager.h"
@@ -66,7 +66,7 @@ struct KernelCore::Impl {
66 is_phantom_mode_for_singlecore = false; 66 is_phantom_mode_for_singlecore = false;
67 67
68 InitializePhysicalCores(); 68 InitializePhysicalCores();
69 InitializeSystemResourceLimit(kernel); 69 InitializeSystemResourceLimit(kernel, system);
70 InitializeMemoryLayout(); 70 InitializeMemoryLayout();
71 InitializePreemption(kernel); 71 InitializePreemption(kernel);
72 InitializeSchedulers(); 72 InitializeSchedulers();
@@ -131,19 +131,19 @@ struct KernelCore::Impl {
131 } 131 }
132 132
133 // Creates the default system resource limit 133 // Creates the default system resource limit
134 void InitializeSystemResourceLimit(KernelCore& kernel) { 134 void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) {
135 system_resource_limit = ResourceLimit::Create(kernel); 135 system_resource_limit = std::make_shared<KResourceLimit>(kernel, system);
136 136
137 // If setting the default system values fails, then something seriously wrong has occurred. 137 // If setting the default system values fails, then something seriously wrong has occurred.
138 ASSERT(system_resource_limit->SetLimitValue(ResourceType::PhysicalMemory, 0x100000000) 138 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000)
139 .IsSuccess()); 139 .IsSuccess());
140 ASSERT(system_resource_limit->SetLimitValue(ResourceType::Threads, 800).IsSuccess()); 140 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess());
141 ASSERT(system_resource_limit->SetLimitValue(ResourceType::Events, 700).IsSuccess()); 141 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess());
142 ASSERT(system_resource_limit->SetLimitValue(ResourceType::TransferMemory, 200).IsSuccess()); 142 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200)
143 ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess()); 143 .IsSuccess());
144 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 900).IsSuccess());
144 145
145 if (!system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0) || 146 if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, 0x60000)) {
146 !system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0x60000)) {
147 UNREACHABLE(); 147 UNREACHABLE();
148 } 148 }
149 } 149 }
@@ -320,7 +320,7 @@ struct KernelCore::Impl {
320 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; 320 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
321 Kernel::TimeManager time_manager; 321 Kernel::TimeManager time_manager;
322 322
323 std::shared_ptr<ResourceLimit> system_resource_limit; 323 std::shared_ptr<KResourceLimit> system_resource_limit;
324 324
325 std::shared_ptr<Core::Timing::EventType> preemption_event; 325 std::shared_ptr<Core::Timing::EventType> preemption_event;
326 326
@@ -390,7 +390,7 @@ void KernelCore::Shutdown() {
390 impl->Shutdown(); 390 impl->Shutdown();
391} 391}
392 392
393std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const { 393std::shared_ptr<KResourceLimit> KernelCore::GetSystemResourceLimit() const {
394 return impl->system_resource_limit; 394 return impl->system_resource_limit;
395} 395}
396 396
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index e7c77727b..806a0d986 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -38,7 +38,7 @@ class GlobalSchedulerContext;
38class HandleTable; 38class HandleTable;
39class PhysicalCore; 39class PhysicalCore;
40class Process; 40class Process;
41class ResourceLimit; 41class KResourceLimit;
42class KScheduler; 42class KScheduler;
43class SharedMemory; 43class SharedMemory;
44class ServiceThread; 44class ServiceThread;
@@ -85,7 +85,7 @@ public:
85 void Shutdown(); 85 void Shutdown();
86 86
87 /// Retrieves a shared pointer to the system resource limit instance. 87 /// Retrieves a shared pointer to the system resource limit instance.
88 std::shared_ptr<ResourceLimit> GetSystemResourceLimit() const; 88 std::shared_ptr<KResourceLimit> GetSystemResourceLimit() const;
89 89
90 /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. 90 /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
91 std::shared_ptr<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const; 91 std::shared_ptr<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const;
diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp
index 080886554..7de91c768 100644
--- a/src/core/hle/kernel/memory/page_table.cpp
+++ b/src/core/hle/kernel/memory/page_table.cpp
@@ -7,6 +7,7 @@
7#include "common/scope_exit.h" 7#include "common/scope_exit.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/kernel/errors.h" 9#include "core/hle/kernel/errors.h"
10#include "core/hle/kernel/k_resource_limit.h"
10#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/memory/address_space_info.h" 12#include "core/hle/kernel/memory/address_space_info.h"
12#include "core/hle/kernel/memory/memory_block.h" 13#include "core/hle/kernel/memory/memory_block.h"
@@ -15,7 +16,6 @@
15#include "core/hle/kernel/memory/page_table.h" 16#include "core/hle/kernel/memory/page_table.h"
16#include "core/hle/kernel/memory/system_control.h" 17#include "core/hle/kernel/memory/system_control.h"
17#include "core/hle/kernel/process.h" 18#include "core/hle/kernel/process.h"
18#include "core/hle/kernel/resource_limit.h"
19#include "core/memory.h" 19#include "core/memory.h"
20 20
21namespace Kernel::Memory { 21namespace Kernel::Memory {
@@ -414,7 +414,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
414 const std::size_t remaining_pages{remaining_size / PageSize}; 414 const std::size_t remaining_pages{remaining_size / PageSize};
415 415
416 if (process->GetResourceLimit() && 416 if (process->GetResourceLimit() &&
417 !process->GetResourceLimit()->Reserve(ResourceType::PhysicalMemory, remaining_size)) { 417 !process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemory, remaining_size)) {
418 return ERR_RESOURCE_LIMIT_EXCEEDED; 418 return ERR_RESOURCE_LIMIT_EXCEEDED;
419 } 419 }
420 420
@@ -422,7 +422,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
422 { 422 {
423 auto block_guard = detail::ScopeExit([&] { 423 auto block_guard = detail::ScopeExit([&] {
424 system.Kernel().MemoryManager().Free(page_linked_list, remaining_pages, memory_pool); 424 system.Kernel().MemoryManager().Free(page_linked_list, remaining_pages, memory_pool);
425 process->GetResourceLimit()->Release(ResourceType::PhysicalMemory, remaining_size); 425 process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, remaining_size);
426 }); 426 });
427 427
428 CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, 428 CASCADE_CODE(system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages,
@@ -474,7 +474,7 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
474 CASCADE_CODE(UnmapMemory(addr, size)); 474 CASCADE_CODE(UnmapMemory(addr, size));
475 475
476 auto process{system.Kernel().CurrentProcess()}; 476 auto process{system.Kernel().CurrentProcess()};
477 process->GetResourceLimit()->Release(ResourceType::PhysicalMemory, mapped_size); 477 process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size);
478 physical_memory_usage -= mapped_size; 478 physical_memory_usage -= mapped_size;
479 479
480 return RESULT_SUCCESS; 480 return RESULT_SUCCESS;
@@ -783,7 +783,7 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
783 783
784 auto process{system.Kernel().CurrentProcess()}; 784 auto process{system.Kernel().CurrentProcess()};
785 if (process->GetResourceLimit() && delta != 0 && 785 if (process->GetResourceLimit() && delta != 0 &&
786 !process->GetResourceLimit()->Reserve(ResourceType::PhysicalMemory, delta)) { 786 !process->GetResourceLimit()->Reserve(LimitableResource::PhysicalMemory, delta)) {
787 return ERR_RESOURCE_LIMIT_EXCEEDED; 787 return ERR_RESOURCE_LIMIT_EXCEEDED;
788 } 788 }
789 789
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 0edbfc4cc..afdb27c54 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -15,6 +15,7 @@
15#include "core/file_sys/program_metadata.h" 15#include "core/file_sys/program_metadata.h"
16#include "core/hle/kernel/code_set.h" 16#include "core/hle/kernel/code_set.h"
17#include "core/hle/kernel/errors.h" 17#include "core/hle/kernel/errors.h"
18#include "core/hle/kernel/k_resource_limit.h"
18#include "core/hle/kernel/k_scheduler.h" 19#include "core/hle/kernel/k_scheduler.h"
19#include "core/hle/kernel/k_thread.h" 20#include "core/hle/kernel/k_thread.h"
20#include "core/hle/kernel/kernel.h" 21#include "core/hle/kernel/kernel.h"
@@ -22,7 +23,6 @@
22#include "core/hle/kernel/memory/page_table.h" 23#include "core/hle/kernel/memory/page_table.h"
23#include "core/hle/kernel/memory/slab_heap.h" 24#include "core/hle/kernel/memory/slab_heap.h"
24#include "core/hle/kernel/process.h" 25#include "core/hle/kernel/process.h"
25#include "core/hle/kernel/resource_limit.h"
26#include "core/hle/lock.h" 26#include "core/hle/lock.h"
27#include "core/memory.h" 27#include "core/memory.h"
28#include "core/settings.h" 28#include "core/settings.h"
@@ -116,7 +116,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
116 116
117 std::shared_ptr<Process> process = std::make_shared<Process>(system); 117 std::shared_ptr<Process> process = std::make_shared<Process>(system);
118 process->name = std::move(name); 118 process->name = std::move(name);
119 process->resource_limit = ResourceLimit::Create(kernel); 119 process->resource_limit = std::make_shared<KResourceLimit>(kernel, system);
120 process->status = ProcessStatus::Created; 120 process->status = ProcessStatus::Created;
121 process->program_id = 0; 121 process->program_id = 0;
122 process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() 122 process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
@@ -132,7 +132,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
132 return process; 132 return process;
133} 133}
134 134
135std::shared_ptr<ResourceLimit> Process::GetResourceLimit() const { 135std::shared_ptr<KResourceLimit> Process::GetResourceLimit() const {
136 return resource_limit; 136 return resource_limit;
137} 137}
138 138
@@ -154,7 +154,7 @@ void Process::DecrementThreadCount() {
154} 154}
155 155
156u64 Process::GetTotalPhysicalMemoryAvailable() const { 156u64 Process::GetTotalPhysicalMemoryAvailable() const {
157 const u64 capacity{resource_limit->GetCurrentResourceValue(ResourceType::PhysicalMemory) + 157 const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
158 page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + 158 page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
159 main_thread_stack_size}; 159 main_thread_stack_size};
160 160
@@ -308,13 +308,13 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
308 308
309 // Set initial resource limits 309 // Set initial resource limits
310 resource_limit->SetLimitValue( 310 resource_limit->SetLimitValue(
311 ResourceType::PhysicalMemory, 311 LimitableResource::PhysicalMemory,
312 kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application)); 312 kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application));
313 resource_limit->SetLimitValue(ResourceType::Threads, 608); 313 resource_limit->SetLimitValue(LimitableResource::Threads, 608);
314 resource_limit->SetLimitValue(ResourceType::Events, 700); 314 resource_limit->SetLimitValue(LimitableResource::Events, 700);
315 resource_limit->SetLimitValue(ResourceType::TransferMemory, 128); 315 resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128);
316 resource_limit->SetLimitValue(ResourceType::Sessions, 894); 316 resource_limit->SetLimitValue(LimitableResource::Sessions, 894);
317 ASSERT(resource_limit->Reserve(ResourceType::PhysicalMemory, code_size)); 317 ASSERT(resource_limit->Reserve(LimitableResource::PhysicalMemory, code_size));
318 318
319 // Create TLS region 319 // Create TLS region
320 tls_region_address = CreateTLSRegion(); 320 tls_region_address = CreateTLSRegion();
@@ -331,8 +331,8 @@ void Process::Run(s32 main_thread_priority, u64 stack_size) {
331 ChangeStatus(ProcessStatus::Running); 331 ChangeStatus(ProcessStatus::Running);
332 332
333 SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top); 333 SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top);
334 resource_limit->Reserve(ResourceType::Threads, 1); 334 resource_limit->Reserve(LimitableResource::Threads, 1);
335 resource_limit->Reserve(ResourceType::PhysicalMemory, main_thread_stack_size); 335 resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size);
336} 336}
337 337
338void Process::PrepareForTermination() { 338void Process::PrepareForTermination() {
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 26e647743..c8af76ce8 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -29,7 +29,7 @@ class ProgramMetadata;
29namespace Kernel { 29namespace Kernel {
30 30
31class KernelCore; 31class KernelCore;
32class ResourceLimit; 32class KResourceLimit;
33class KThread; 33class KThread;
34class TLSPage; 34class TLSPage;
35 35
@@ -170,7 +170,7 @@ public:
170 } 170 }
171 171
172 /// Gets the resource limit descriptor for this process 172 /// Gets the resource limit descriptor for this process
173 std::shared_ptr<ResourceLimit> GetResourceLimit() const; 173 std::shared_ptr<KResourceLimit> GetResourceLimit() const;
174 174
175 /// Gets the ideal CPU core ID for this process 175 /// Gets the ideal CPU core ID for this process
176 u8 GetIdealCoreId() const { 176 u8 GetIdealCoreId() const {
@@ -402,7 +402,7 @@ private:
402 u32 system_resource_size = 0; 402 u32 system_resource_size = 0;
403 403
404 /// Resource limit descriptor for this process 404 /// Resource limit descriptor for this process
405 std::shared_ptr<ResourceLimit> resource_limit; 405 std::shared_ptr<KResourceLimit> resource_limit;
406 406
407 /// The ideal CPU core for this process, threads are scheduled on this core by default. 407 /// The ideal CPU core for this process, threads are scheduled on this core by default.
408 u8 ideal_core = 0; 408 u8 ideal_core = 0;
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
deleted file mode 100644
index 7bf50339d..000000000
--- a/src/core/hle/kernel/resource_limit.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/errors.h"
6#include "core/hle/kernel/resource_limit.h"
7#include "core/hle/result.h"
8
9namespace Kernel {
10namespace {
11constexpr std::size_t ResourceTypeToIndex(ResourceType type) {
12 return static_cast<std::size_t>(type);
13}
14} // Anonymous namespace
15
16ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {}
17ResourceLimit::~ResourceLimit() = default;
18
19bool ResourceLimit::Reserve(ResourceType resource, s64 amount) {
20 return Reserve(resource, amount, 10000000000);
21}
22
23bool ResourceLimit::Reserve(ResourceType resource, s64 amount, u64 timeout) {
24 const std::size_t index{ResourceTypeToIndex(resource)};
25
26 s64 new_value = current[index] + amount;
27 if (new_value > limit[index] && available[index] + amount <= limit[index]) {
28 // TODO(bunnei): This is wrong for multicore, we should wait the calling thread for timeout
29 new_value = current[index] + amount;
30 }
31
32 if (new_value <= limit[index]) {
33 current[index] = new_value;
34 return true;
35 }
36 return false;
37}
38
39void ResourceLimit::Release(ResourceType resource, u64 amount) {
40 Release(resource, amount, amount);
41}
42
43void ResourceLimit::Release(ResourceType resource, u64 used_amount, u64 available_amount) {
44 const std::size_t index{ResourceTypeToIndex(resource)};
45
46 current[index] -= used_amount;
47 available[index] -= available_amount;
48}
49
50std::shared_ptr<ResourceLimit> ResourceLimit::Create(KernelCore& kernel) {
51 return std::make_shared<ResourceLimit>(kernel);
52}
53
54s64 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {
55 return limit.at(ResourceTypeToIndex(resource)) - current.at(ResourceTypeToIndex(resource));
56}
57
58s64 ResourceLimit::GetMaxResourceValue(ResourceType resource) const {
59 return limit.at(ResourceTypeToIndex(resource));
60}
61
62ResultCode ResourceLimit::SetLimitValue(ResourceType resource, s64 value) {
63 const std::size_t index{ResourceTypeToIndex(resource)};
64 if (current[index] <= value) {
65 limit[index] = value;
66 return RESULT_SUCCESS;
67 } else {
68 LOG_ERROR(Kernel, "Limit value is too large! resource={}, value={}, index={}", resource,
69 value, index);
70 return ERR_INVALID_STATE;
71 }
72}
73} // namespace Kernel
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
deleted file mode 100644
index 464d4f2a6..000000000
--- a/src/core/hle/kernel/resource_limit.h
+++ /dev/null
@@ -1,106 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <memory>
9
10#include "common/common_types.h"
11#include "core/hle/kernel/object.h"
12
13union ResultCode;
14
15namespace Kernel {
16
17class KernelCore;
18
19enum class ResourceType : u32 {
20 PhysicalMemory,
21 Threads,
22 Events,
23 TransferMemory,
24 Sessions,
25
26 // Used as a count, not an actual type.
27 ResourceTypeCount
28};
29
30constexpr bool IsValidResourceType(ResourceType type) {
31 return type < ResourceType::ResourceTypeCount;
32}
33
34class ResourceLimit final : public Object {
35public:
36 explicit ResourceLimit(KernelCore& kernel);
37 ~ResourceLimit() override;
38
39 /// Creates a resource limit object.
40 static std::shared_ptr<ResourceLimit> Create(KernelCore& kernel);
41
42 std::string GetTypeName() const override {
43 return "ResourceLimit";
44 }
45 std::string GetName() const override {
46 return GetTypeName();
47 }
48
49 static constexpr HandleType HANDLE_TYPE = HandleType::ResourceLimit;
50 HandleType GetHandleType() const override {
51 return HANDLE_TYPE;
52 }
53
54 bool Reserve(ResourceType resource, s64 amount);
55 bool Reserve(ResourceType resource, s64 amount, u64 timeout);
56 void Release(ResourceType resource, u64 amount);
57 void Release(ResourceType resource, u64 used_amount, u64 available_amount);
58
59 /**
60 * Gets the current value for the specified resource.
61 * @param resource Requested resource type
62 * @returns The current value of the resource type
63 */
64 s64 GetCurrentResourceValue(ResourceType resource) const;
65
66 /**
67 * Gets the max value for the specified resource.
68 * @param resource Requested resource type
69 * @returns The max value of the resource type
70 */
71 s64 GetMaxResourceValue(ResourceType resource) const;
72
73 /**
74 * Sets the limit value for a given resource type.
75 *
76 * @param resource The resource type to apply the limit to.
77 * @param value The limit to apply to the given resource type.
78 *
79 * @return A result code indicating if setting the limit value
80 * was successful or not.
81 *
82 * @note The supplied limit value *must* be greater than or equal to
83 * the current resource value for the given resource type,
84 * otherwise ERR_INVALID_STATE will be returned.
85 */
86 ResultCode SetLimitValue(ResourceType resource, s64 value);
87
88 void Finalize() override {}
89
90private:
91 // TODO(Subv): Increment resource limit current values in their respective Kernel::T::Create
92 // functions
93 //
94 // Currently we have no way of distinguishing if a Create was called by the running application,
95 // or by a service module. Approach this once we have separated the service modules into their
96 // own processes
97
98 using ResourceArray =
99 std::array<s64, static_cast<std::size_t>(ResourceType::ResourceTypeCount)>;
100
101 ResourceArray limit{};
102 ResourceArray current{};
103 ResourceArray available{};
104};
105
106} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 7fd514e9d..74eb90100 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -26,6 +26,7 @@
26#include "core/hle/kernel/handle_table.h" 26#include "core/hle/kernel/handle_table.h"
27#include "core/hle/kernel/k_address_arbiter.h" 27#include "core/hle/kernel/k_address_arbiter.h"
28#include "core/hle/kernel/k_condition_variable.h" 28#include "core/hle/kernel/k_condition_variable.h"
29#include "core/hle/kernel/k_resource_limit.h"
29#include "core/hle/kernel/k_scheduler.h" 30#include "core/hle/kernel/k_scheduler.h"
30#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 31#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
31#include "core/hle/kernel/k_synchronization_object.h" 32#include "core/hle/kernel/k_synchronization_object.h"
@@ -37,7 +38,6 @@
37#include "core/hle/kernel/physical_core.h" 38#include "core/hle/kernel/physical_core.h"
38#include "core/hle/kernel/process.h" 39#include "core/hle/kernel/process.h"
39#include "core/hle/kernel/readable_event.h" 40#include "core/hle/kernel/readable_event.h"
40#include "core/hle/kernel/resource_limit.h"
41#include "core/hle/kernel/shared_memory.h" 41#include "core/hle/kernel/shared_memory.h"
42#include "core/hle/kernel/svc.h" 42#include "core/hle/kernel/svc.h"
43#include "core/hle/kernel/svc_results.h" 43#include "core/hle/kernel/svc_results.h"
@@ -141,7 +141,7 @@ enum class ResourceLimitValueType {
141ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit, 141ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_limit,
142 u32 resource_type, ResourceLimitValueType value_type) { 142 u32 resource_type, ResourceLimitValueType value_type) {
143 std::lock_guard lock{HLE::g_hle_lock}; 143 std::lock_guard lock{HLE::g_hle_lock};
144 const auto type = static_cast<ResourceType>(resource_type); 144 const auto type = static_cast<LimitableResource>(resource_type);
145 if (!IsValidResourceType(type)) { 145 if (!IsValidResourceType(type)) {
146 LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); 146 LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
147 return ERR_INVALID_ENUM_VALUE; 147 return ERR_INVALID_ENUM_VALUE;
@@ -151,7 +151,7 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
151 ASSERT(current_process != nullptr); 151 ASSERT(current_process != nullptr);
152 152
153 const auto resource_limit_object = 153 const auto resource_limit_object =
154 current_process->GetHandleTable().Get<ResourceLimit>(resource_limit); 154 current_process->GetHandleTable().Get<KResourceLimit>(resource_limit);
155 if (!resource_limit_object) { 155 if (!resource_limit_object) {
156 LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", 156 LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
157 resource_limit); 157 resource_limit);
@@ -159,10 +159,10 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
159 } 159 }
160 160
161 if (value_type == ResourceLimitValueType::CurrentValue) { 161 if (value_type == ResourceLimitValueType::CurrentValue) {
162 return MakeResult(resource_limit_object->GetCurrentResourceValue(type)); 162 return MakeResult(resource_limit_object->GetCurrentValue(type));
163 } 163 }
164 164
165 return MakeResult(resource_limit_object->GetMaxResourceValue(type)); 165 return MakeResult(resource_limit_object->GetLimitValue(type));
166} 166}
167} // Anonymous namespace 167} // Anonymous namespace
168 168
@@ -312,7 +312,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
312 return ERR_NOT_FOUND; 312 return ERR_NOT_FOUND;
313 } 313 }
314 314
315 ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Sessions, 1)); 315 ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(LimitableResource::Sessions, 1));
316 316
317 auto client_port = it->second; 317 auto client_port = it->second;
318 318
@@ -1450,7 +1450,8 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
1450 Svc::ResultInvalidPriority); 1450 Svc::ResultInvalidPriority);
1451 R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority); 1451 R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority);
1452 1452
1453 ASSERT(process.GetResourceLimit()->Reserve(ResourceType::Threads, 1)); 1453 ASSERT(process.GetResourceLimit()->Reserve(
1454 LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000));
1454 1455
1455 std::shared_ptr<KThread> thread; 1456 std::shared_ptr<KThread> thread;
1456 { 1457 {
@@ -1972,7 +1973,7 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle)
1972 LOG_DEBUG(Kernel_SVC, "called"); 1973 LOG_DEBUG(Kernel_SVC, "called");
1973 1974
1974 auto& kernel = system.Kernel(); 1975 auto& kernel = system.Kernel();
1975 auto resource_limit = ResourceLimit::Create(kernel); 1976 auto resource_limit = std::make_shared<KResourceLimit>(kernel, system);
1976 1977
1977 auto* const current_process = kernel.CurrentProcess(); 1978 auto* const current_process = kernel.CurrentProcess();
1978 ASSERT(current_process != nullptr); 1979 ASSERT(current_process != nullptr);
@@ -2019,7 +2020,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
2019 LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit, 2020 LOG_DEBUG(Kernel_SVC, "called. Handle={:08X}, Resource type={}, Value={}", resource_limit,
2020 resource_type, value); 2021 resource_type, value);
2021 2022
2022 const auto type = static_cast<ResourceType>(resource_type); 2023 const auto type = static_cast<LimitableResource>(resource_type);
2023 if (!IsValidResourceType(type)) { 2024 if (!IsValidResourceType(type)) {
2024 LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type); 2025 LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
2025 return ERR_INVALID_ENUM_VALUE; 2026 return ERR_INVALID_ENUM_VALUE;
@@ -2029,7 +2030,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
2029 ASSERT(current_process != nullptr); 2030 ASSERT(current_process != nullptr);
2030 2031
2031 auto resource_limit_object = 2032 auto resource_limit_object =
2032 current_process->GetHandleTable().Get<ResourceLimit>(resource_limit); 2033 current_process->GetHandleTable().Get<KResourceLimit>(resource_limit);
2033 if (!resource_limit_object) { 2034 if (!resource_limit_object) {
2034 LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}", 2035 LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
2035 resource_limit); 2036 resource_limit);
@@ -2041,8 +2042,8 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
2041 LOG_ERROR( 2042 LOG_ERROR(
2042 Kernel_SVC, 2043 Kernel_SVC,
2043 "Attempted to lower resource limit ({}) for category '{}' below its current value ({})", 2044 "Attempted to lower resource limit ({}) for category '{}' below its current value ({})",
2044 resource_limit_object->GetMaxResourceValue(type), resource_type, 2045 resource_limit_object->GetLimitValue(type), resource_type,
2045 resource_limit_object->GetCurrentResourceValue(type)); 2046 resource_limit_object->GetCurrentValue(type));
2046 return set_result; 2047 return set_result;
2047 } 2048 }
2048 2049
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index d9865d56f..50b2c58e2 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -41,12 +41,18 @@ constexpr char ACC_SAVE_AVATORS_BASE_PATH[] = "/system/save/8000000000000010/su/
41ProfileManager::ProfileManager() { 41ProfileManager::ProfileManager() {
42 ParseUserSaveFile(); 42 ParseUserSaveFile();
43 43
44 if (user_count == 0) 44 // Create an user if none are present
45 if (user_count == 0) {
45 CreateNewUser(UUID::Generate(), "yuzu"); 46 CreateNewUser(UUID::Generate(), "yuzu");
47 }
46 48
47 auto current = std::clamp<int>(Settings::values.current_user, 0, MAX_USERS - 1); 49 auto current = std::clamp<int>(Settings::values.current_user, 0, MAX_USERS - 1);
48 if (UserExistsIndex(current)) 50
51 // If user index don't exist. Load the first user and change the active user
52 if (!UserExistsIndex(current)) {
49 current = 0; 53 current = 0;
54 Settings::values.current_user = 0;
55 }
50 56
51 OpenUser(*GetUser(current)); 57 OpenUser(*GetUser(current));
52} 58}
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 39306509a..2ae5196e0 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -70,6 +70,9 @@ void LogSettings() {
70 log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); 70 log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue());
71 log_setting("Audio_OutputDevice", values.audio_device_id); 71 log_setting("Audio_OutputDevice", values.audio_device_id);
72 log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd); 72 log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd);
73 log_setting("DataStorage_CacheDir", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir));
74 log_setting("DataStorage_ConfigDir", Common::FS::GetUserPath(Common::FS::UserPath::ConfigDir));
75 log_setting("DataStorage_LoadDir", Common::FS::GetUserPath(Common::FS::UserPath::LoadDir));
73 log_setting("DataStorage_NandDir", Common::FS::GetUserPath(Common::FS::UserPath::NANDDir)); 76 log_setting("DataStorage_NandDir", Common::FS::GetUserPath(Common::FS::UserPath::NANDDir));
74 log_setting("DataStorage_SdmcDir", Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir)); 77 log_setting("DataStorage_SdmcDir", Common::FS::GetUserPath(Common::FS::UserPath::SDMCDir));
75 log_setting("Debugging_ProgramArgs", values.program_args); 78 log_setting("Debugging_ProgramArgs", values.program_args);
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt
index 73f331d4c..28f2b8614 100644
--- a/src/video_core/host_shaders/CMakeLists.txt
+++ b/src/video_core/host_shaders/CMakeLists.txt
@@ -20,6 +20,7 @@ set(SHADER_FILES
20find_program(GLSLANGVALIDATOR "glslangValidator" REQUIRED) 20find_program(GLSLANGVALIDATOR "glslangValidator" REQUIRED)
21 21
22set(GLSL_FLAGS "") 22set(GLSL_FLAGS "")
23set(QUIET_FLAG "--quiet")
23 24
24set(SHADER_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/include) 25set(SHADER_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/include)
25set(SHADER_DIR ${SHADER_INCLUDE}/video_core/host_shaders) 26set(SHADER_DIR ${SHADER_INCLUDE}/video_core/host_shaders)
@@ -28,6 +29,23 @@ set(HOST_SHADERS_INCLUDE ${SHADER_INCLUDE} PARENT_SCOPE)
28set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in) 29set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in)
29set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake) 30set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake)
30 31
32# Check if `--quiet` is available on host's glslangValidator version
33# glslangValidator prints to STDERR iff an unrecognized flag is passed to it
34execute_process(
35 COMMAND
36 ${GLSLANGVALIDATOR} ${QUIET_FLAG}
37 ERROR_VARIABLE
38 GLSLANG_ERROR
39 # STDOUT variable defined to silence unnecessary output during CMake configuration
40 OUTPUT_VARIABLE
41 GLSLANG_OUTPUT
42)
43
44if (NOT GLSLANG_ERROR STREQUAL "")
45 message(WARNING "Refusing to use unavailable flag `${QUIET_FLAG}` on `${GLSLANGVALIDATOR}`")
46 set(QUIET_FLAG "")
47endif()
48
31foreach(FILENAME IN ITEMS ${SHADER_FILES}) 49foreach(FILENAME IN ITEMS ${SHADER_FILES})
32 string(REPLACE "." "_" SHADER_NAME ${FILENAME}) 50 string(REPLACE "." "_" SHADER_NAME ${FILENAME})
33 set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}) 51 set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME})
@@ -55,7 +73,7 @@ foreach(FILENAME IN ITEMS ${SHADER_FILES})
55 OUTPUT 73 OUTPUT
56 ${SPIRV_HEADER_FILE} 74 ${SPIRV_HEADER_FILE}
57 COMMAND 75 COMMAND
58 ${GLSLANGVALIDATOR} -V --quiet ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} 76 ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE}
59 MAIN_DEPENDENCY 77 MAIN_DEPENDENCY
60 ${SOURCE_FILE} 78 ${SOURCE_FILE}
61 ) 79 )
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index fbe36046b..1ab5bcbb9 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -580,9 +580,7 @@ void ConfigureInputPlayer::ApplyConfiguration() {
580 if (player_index == 0) { 580 if (player_index == 0) {
581 auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; 581 auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
582 const auto handheld_connected = handheld.connected; 582 const auto handheld_connected = handheld.connected;
583 if (player.controller_type == Settings::ControllerType::Handheld) { 583 handheld = player;
584 handheld = player;
585 }
586 handheld.connected = handheld_connected; 584 handheld.connected = handheld_connected;
587 } 585 }
588} 586}
@@ -596,7 +594,7 @@ void ConfigureInputPlayer::TryConnectSelectedController() {
596 controller_type != Settings::ControllerType::Handheld; 594 controller_type != Settings::ControllerType::Handheld;
597 595
598 // Connect Handheld depending on Player 1's controller configuration. 596 // Connect Handheld depending on Player 1's controller configuration.
599 if (player_index == 0 && controller_type == Settings::ControllerType::Handheld) { 597 if (player_index == 0) {
600 auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; 598 auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
601 const auto handheld_connected = ui->groupConnectedController->isChecked() && 599 const auto handheld_connected = ui->groupConnectedController->isChecked() &&
602 controller_type == Settings::ControllerType::Handheld; 600 controller_type == Settings::ControllerType::Handheld;
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index d102a43af..51647a028 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -116,8 +116,8 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent)
116 scene = new QGraphicsScene; 116 scene = new QGraphicsScene;
117 ui->current_user_icon->setScene(scene); 117 ui->current_user_icon->setScene(scene);
118 118
119 SetConfiguration();
120 RetranslateUI(); 119 RetranslateUI();
120 SetConfiguration();
121} 121}
122 122
123ConfigureProfileManager::~ConfigureProfileManager() = default; 123ConfigureProfileManager::~ConfigureProfileManager() = default;