Compare commits

...

44 Commits

Author SHA1 Message Date
Liam
72e5552409 sm:: fix lingering session initialization issues 2023-02-21 12:19:25 -05:00
Liam
87749d217e cheat_engine: add check for hid initialization 2023-02-21 12:19:25 -05:00
Liam
6e0a33089b sm:: support service registration deferral 2023-02-21 12:19:25 -05:00
Liam
a936972614 service: refactor server architecture
Converts services to have their own processes
2023-02-21 12:19:25 -05:00
Liam
23151ff498 core: defer cpu shutdown 2023-02-21 12:19:25 -05:00
liamwhite
89221ca7d5 Merge pull request #9834 from german77/reverted
Qt: Reintroduce scaling for touch input
2023-02-20 09:05:49 -05:00
german77
165ebbb63c Qt: Reintroduce scaling for touch input 2023-02-19 17:52:44 -06:00
liamwhite
898c5d35a5 Merge pull request #9771 from ameerj/host-thread-id
kernel: Refactor thread_local variable usage
2023-02-19 13:12:43 -05:00
liamwhite
a4d0663158 Merge pull request #9588 from liamwhite/bylaws-reverts
Revert "shader_recompiler: Align SSBO offsets to meet host requirements"
2023-02-19 13:11:57 -05:00
liamwhite
e531d1fae9 Merge pull request #9815 from german77/qt-mouse
Qt: Fix mouse scalling
2023-02-18 16:25:48 -05:00
Morph
41183b622f Merge pull request #9825 from liamwhite/object-name
kernel: add KObjectName
2023-02-18 16:22:50 -05:00
bunnei
e91ff9b7bd Merge pull request #9810 from Kelebek1/nvdec_threads
Allow >1 cpu threads on video decoding, disable multi-frame decoding
2023-02-17 09:44:38 -08:00
Liam
1773a1039f kernel: add KObjectName 2023-02-17 09:16:05 -05:00
Mai
61b1772e51 Merge pull request #9817 from german77/save
yuzu: Write to config file on important config changes
2023-02-16 22:58:29 -05:00
Narr the Reg
0a88c7dbbe yuzu: Shutdown game on restart to reload per game config 2023-02-16 21:17:30 -06:00
Narr the Reg
df9c8bdfd9 yuzu: Write to config file on important config changes 2023-02-16 21:17:01 -06:00
bunnei
889bfce447 Merge pull request #9802 from Kelebek1/wait_data_cache
Re-add the invalidate_texture_data_cache register
2023-02-16 12:27:24 -08:00
bunnei
744434de38 Merge pull request #9769 from Kelebek1/audio_oob
[audio_core] Fix depop prepare
2023-02-16 12:26:23 -08:00
Narr the Reg
17207939e5 input_common: Split mouse input into individual devices 2023-02-16 14:22:13 -06:00
german77
57aaf00a0c Qt: Fix mouse scalling 2023-02-15 20:57:45 -06:00
liamwhite
6d77de96da Merge pull request #9796 from liamwhite/current
general: rename CurrentProcess to ApplicationProcess
2023-02-15 17:42:45 -05:00
liamwhite
04d2d2ef5f Merge pull request #9782 from arades79/fix-consexpr-value-declaration-usage
Fix consexpr value declaration usage
2023-02-15 17:42:38 -05:00
bunnei
0eb40117af Merge pull request #9809 from liamwhite/unused-service
service: remove deleted services
2023-02-15 12:33:59 -08:00
bunnei
3599ef2077 Merge pull request #9811 from yuzu-emu/revert-9793-borderless-hidpi
Revert "main: Fix borderless fullscreen for high dpi scaled displays"
2023-02-14 18:27:21 -08:00
arades79
98631b45b6 remove constexpr from virtual function
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 19:14:29 -05:00
liamwhite
58a2c19982 Revert "main: Fix borderless fullscreen for high dpi scaled displays" 2023-02-14 16:29:35 -05:00
Kelebek1
3b50906f00 Reimplement the invalidate_texture_data_cache register 2023-02-14 19:34:10 +00:00
Kelebek1
139b645aa2 Allow >1 cpu threads on video decoding, disable multi-frame decoding 2023-02-14 18:55:46 +00:00
Liam
79fbdfca17 service: remove deleted services 2023-02-14 12:38:21 -05:00
arades79
880b6e9795 use a string view to skip allocation
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:35:40 -05:00
arades79
683019878f remove static from pointer sized or smaller types for aesthetics, change constexpr static to static constexpr for consistency
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:35:39 -05:00
arades79
26e44a3be4 apply clang-format
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:35:39 -05:00
arades79
392a029ef4 don't use static inside constexpr function
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:33:11 -05:00
arades79
45e13b03f3 add static lifetime to constexpr values to force compile time evaluation where possible
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:33:11 -05:00
liamwhite
5f5a6e4b2e Merge pull request #9795 from Kelebek1/biquad_fix
[audio_core] Use different state offset for each biquad filter channel
2023-02-14 09:11:26 -05:00
liamwhite
d87db919f9 Merge pull request #9793 from Morph1984/borderless-hidpi
main: Fix borderless fullscreen for high dpi scaled displays
2023-02-14 09:11:15 -05:00
Liam
ceda2d280e general: rename CurrentProcess to ApplicationProcess 2023-02-13 19:03:12 -05:00
Liam
4363ca304a kernel: use GetCurrentProcess 2023-02-13 11:05:14 -05:00
Morph
d6677b50f6 main: Fix borderless fullscreen for high dpi scaled displays
On Windows, a borderless window will be treated the same as exclusive fullscreen
when the window geometry matches the physical dimensions of the screen.
However, with High DPI scaling, when the devicePixelRatioF() is > 1, the borderless
window apparently is not treated as exclusive fullscreen and functions correctly.
One can verify and replicate this behavior by using a high resolution (4K) display,
and switching between 100% and 200% scaling in Windows' display settings.
At 100%, without the addition of 1, it is treated as exclusive fullscreen.
At 200%, with or without the addition of 1, it is treated as borderless windowed.
Therefore, we can use (read: abuse) this difference in behavior to fix this issue for
those with higher resolution displays when the Qt scaling ratio is > 1.
Should this behavior be changed in the future, please revisit this workaround.
2023-02-12 21:58:49 -05:00
Kelebek1
2e02ed8bb5 Add fallback for memory read/write in case the address goes over a 4K page 2023-02-11 16:27:43 +00:00
Kelebek1
19e1ea6a02 Fix depop prepare receiving bad mix infos and writing out of bounds, and update aux a bit, may help 2023-02-11 10:21:25 +00:00
ameerj
5e746da981 kernel: Refactor thread_local variable usage
On MSVC at least, there seems to be a non-trivial overhead to calling GetHostThreadId().

This slightly reworks the host_thread_id variable to reduce some of the complexity around its usage, along with some small refactors around current_thread and dummy thread
2023-02-10 20:43:06 -05:00
Liam
505923f0f3 Revert "shader_recompiler: Align SSBO offsets to meet host requirements"
This reverts commit 8804a4eb23.
2023-01-07 15:50:58 -05:00
Liam
57a4388e2d Revert "Vulkan, OpenGL: Hook up storage buffer alignment code"
This reverts commit 9e2997c4b6.
2023-01-07 15:48:50 -05:00
255 changed files with 2445 additions and 2254 deletions

View File

@@ -132,7 +132,7 @@ void AudioRenderer::CreateSinkStreams() {
}
void AudioRenderer::ThreadFunc() {
constexpr char name[]{"AudioRenderer"};
static constexpr char name[]{"AudioRenderer"};
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical);

View File

@@ -46,7 +46,7 @@ void CommandGenerator::GenerateDataSourceCommand(VoiceInfo& voice_info,
while (destination != nullptr) {
if (destination->IsConfigured()) {
auto mix_id{destination->GetMixId()};
if (mix_id < mix_context.GetCount()) {
if (mix_id < mix_context.GetCount() && mix_id != UnusedSplitterId) {
auto mix_info{mix_context.GetInfo(mix_id)};
command_buffer.GenerateDepopPrepareCommand(
voice_info.node_id, voice_state, render_context.depop_buffer,

View File

@@ -4,6 +4,7 @@
#include "audio_core/renderer/adsp/command_list_processor.h"
#include "audio_core/renderer/command/effect/aux_.h"
#include "audio_core/renderer/effect/aux_.h"
#include "core/core.h"
#include "core/memory.h"
namespace AudioCore::AudioRenderer {
@@ -19,10 +20,24 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in
return;
}
auto info{reinterpret_cast<AuxInfo::AuxInfoDsp*>(memory.GetPointer(aux_info))};
info->read_offset = 0;
info->write_offset = 0;
info->total_sample_count = 0;
AuxInfo::AuxInfoDsp info{};
auto info_ptr{&info};
bool host_safe{(aux_info & Core::Memory::YUZU_PAGEMASK) <=
(Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp))};
if (host_safe) [[likely]] {
info_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(aux_info);
} else {
memory.ReadBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp));
}
info_ptr->read_offset = 0;
info_ptr->write_offset = 0;
info_ptr->total_sample_count = 0;
if (!host_safe) [[unlikely]] {
memory.WriteBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp));
}
}
/**
@@ -40,11 +55,10 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in
* @param update_count - If non-zero, send_info_ will be updated.
* @return Number of samples written.
*/
static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_info_,
[[maybe_unused]] u32 sample_count, const CpuAddr send_buffer,
const u32 count_max, std::span<const s32> input,
const u32 write_count_, const u32 write_offset,
const u32 update_count) {
static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
[[maybe_unused]] u32 sample_count, CpuAddr send_buffer, u32 count_max,
std::span<const s32> input, u32 write_count_, u32 write_offset,
u32 update_count) {
if (write_count_ > count_max) {
LOG_ERROR(Service_Audio,
"write_count must be smaller than count_max! write_count {}, count_max {}",
@@ -52,6 +66,11 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
return 0;
}
if (send_info_ == 0) {
LOG_ERROR(Service_Audio, "send_info_ is 0!");
return 0;
}
if (input.empty()) {
LOG_ERROR(Service_Audio, "input buffer is empty!");
return 0;
@@ -67,33 +86,47 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
}
AuxInfo::AuxInfoDsp send_info{};
memory.ReadBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp));
auto send_ptr = &send_info;
bool host_safe = (send_info_ & Core::Memory::YUZU_PAGEMASK) <=
(Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp));
u32 target_write_offset{send_info.write_offset + write_offset};
if (target_write_offset > count_max || write_count_ == 0) {
if (host_safe) [[likely]] {
send_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(send_info_);
} else {
memory.ReadBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp));
}
u32 target_write_offset{send_ptr->write_offset + write_offset};
if (target_write_offset > count_max) {
return 0;
}
u32 write_count{write_count_};
u32 write_pos{0};
u32 read_pos{0};
while (write_count > 0) {
u32 to_write{std::min(count_max - target_write_offset, write_count)};
if (to_write > 0) {
const auto write_addr = send_buffer + target_write_offset * sizeof(s32);
bool write_safe{(write_addr & Core::Memory::YUZU_PAGEMASK) <=
(Core::Memory::YUZU_PAGESIZE - (write_addr + to_write * sizeof(s32)))};
if (write_safe) [[likely]] {
auto ptr = memory.GetPointer(write_addr);
std::memcpy(ptr, &input[read_pos], to_write * sizeof(s32));
} else {
memory.WriteBlockUnsafe(send_buffer + target_write_offset * sizeof(s32),
&input[write_pos], to_write * sizeof(s32));
&input[read_pos], to_write * sizeof(s32));
}
target_write_offset = (target_write_offset + to_write) % count_max;
write_count -= to_write;
write_pos += to_write;
read_pos += to_write;
}
if (update_count) {
send_info.write_offset = (send_info.write_offset + update_count) % count_max;
send_ptr->write_offset = (send_ptr->write_offset + update_count) % count_max;
}
memory.WriteBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp));
if (!host_safe) [[unlikely]] {
memory.WriteBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp));
}
return write_count_;
}
@@ -102,7 +135,7 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
* Read the given memory at return_buffer into the output mix buffer, and update return_info_ if
* update_count is set, to notify the game that an update happened.
*
* @param memory - Core memory for writing.
* @param memory - Core memory for reading.
* @param return_info_ - Meta information for where to read the mix buffer.
* @param return_buffer - Memory address to read the samples from.
* @param count_max - Maximum number of samples in the receiving buffer.
@@ -112,16 +145,21 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
* @param update_count - If non-zero, send_info_ will be updated.
* @return Number of samples read.
*/
static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_info_,
const CpuAddr return_buffer, const u32 count_max, std::span<s32> output,
const u32 count_, const u32 read_offset, const u32 update_count) {
static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_,
CpuAddr return_buffer, u32 count_max, std::span<s32> output,
u32 read_count_, u32 read_offset, u32 update_count) {
if (count_max == 0) {
return 0;
}
if (count_ > count_max) {
if (read_count_ > count_max) {
LOG_ERROR(Service_Audio, "count must be smaller than count_max! count {}, count_max {}",
count_, count_max);
read_count_, count_max);
return 0;
}
if (return_info_ == 0) {
LOG_ERROR(Service_Audio, "return_info_ is 0!");
return 0;
}
@@ -136,35 +174,49 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_i
}
AuxInfo::AuxInfoDsp return_info{};
memory.ReadBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp));
auto return_ptr = &return_info;
bool host_safe = (return_info_ & Core::Memory::YUZU_PAGEMASK) <=
(Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp));
u32 target_read_offset{return_info.read_offset + read_offset};
if (host_safe) [[likely]] {
return_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(return_info_);
} else {
memory.ReadBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp));
}
u32 target_read_offset{return_ptr->read_offset + read_offset};
if (target_read_offset > count_max) {
return 0;
}
u32 read_count{count_};
u32 read_pos{0};
u32 read_count{read_count_};
u32 write_pos{0};
while (read_count > 0) {
u32 to_read{std::min(count_max - target_read_offset, read_count)};
if (to_read > 0) {
const auto read_addr = return_buffer + target_read_offset * sizeof(s32);
bool read_safe{(read_addr & Core::Memory::YUZU_PAGEMASK) <=
(Core::Memory::YUZU_PAGESIZE - (read_addr + to_read * sizeof(s32)))};
if (read_safe) [[likely]] {
auto ptr = memory.GetPointer(read_addr);
std::memcpy(&output[write_pos], ptr, to_read * sizeof(s32));
} else {
memory.ReadBlockUnsafe(return_buffer + target_read_offset * sizeof(s32),
&output[read_pos], to_read * sizeof(s32));
&output[write_pos], to_read * sizeof(s32));
}
target_read_offset = (target_read_offset + to_read) % count_max;
read_count -= to_read;
read_pos += to_read;
write_pos += to_read;
}
if (update_count) {
return_info.read_offset = (return_info.read_offset + update_count) % count_max;
return_ptr->read_offset = (return_ptr->read_offset + update_count) % count_max;
}
memory.WriteBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp));
if (!host_safe) [[unlikely]] {
memory.WriteBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp));
}
return count_;
return read_count_;
}
void AuxCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
@@ -189,7 +241,7 @@ void AuxCommand::Process(const ADSP::CommandListProcessor& processor) {
update_count)};
if (read != processor.sample_count) {
std::memset(&output_buffer[read], 0, processor.sample_count - read);
std::memset(&output_buffer[read], 0, (processor.sample_count - read) * sizeof(s32));
}
} else {
ResetAuxBufferDsp(*processor.memory, send_buffer_info);

View File

@@ -244,16 +244,16 @@ template <size_t NumChannels>
static void ApplyI3dl2ReverbEffect(I3dl2ReverbInfo::State& state,
std::span<std::span<const s32>> inputs,
std::span<std::span<s32>> outputs, const u32 sample_count) {
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1,
};
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 3, 3, 3,
};
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
2, 0, 0, 1, 1, 1, 1, 4, 4, 4, 1, 1, 1, 0, 0, 0, 0, 5, 5, 5,
};

View File

@@ -252,16 +252,16 @@ template <size_t NumChannels>
static void ApplyReverbEffect(const ReverbInfo::ParameterVersion2& params, ReverbInfo::State& state,
std::vector<std::span<const s32>>& inputs,
std::vector<std::span<s32>>& outputs, const u32 sample_count) {
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
0, 0, 1, 1, 0, 1, 0, 0, 1, 1,
};
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
0, 0, 1, 1, 0, 1, 2, 2, 3, 3,
};
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
0, 0, 1, 1, 2, 2, 4, 4, 5, 5,
};

View File

@@ -19,24 +19,24 @@ namespace AudioCore::AudioRenderer {
static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input,
const u32 target_sample_count, const u32 source_sample_count,
UpsamplerState* state) {
constexpr u32 WindowSize = 10;
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc1{
static constexpr u32 WindowSize = 10;
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc1{
0.95376587f, -0.12872314f, 0.060028076f, -0.032470703f, 0.017669678f,
-0.009124756f, 0.004272461f, -0.001739502f, 0.000579834f, -0.000091552734f,
};
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc2{
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc2{
0.8230896f, -0.19161987f, 0.093444824f, -0.05090332f, 0.027557373f,
-0.014038086f, 0.0064697266f, -0.002532959f, 0.00079345703f, -0.00012207031f,
};
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc3{
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc3{
0.6298828f, -0.19274902f, 0.09725952f, -0.05319214f, 0.028625488f,
-0.014373779f, 0.006500244f, -0.0024719238f, 0.0007324219f, -0.000091552734f,
};
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc4{
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc4{
0.4057312f, -0.1468811f, 0.07601929f, -0.041656494f, 0.022216797f,
-0.011016846f, 0.004852295f, -0.0017700195f, 0.00048828125f, -0.000030517578f,
};
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc5{
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc5{
0.1854248f, -0.075164795f, 0.03967285f, -0.021728516f, 0.011474609f,
-0.005584717f, 0.0024108887f, -0.0008239746f, 0.00021362305f, 0.0f,
};

View File

@@ -127,7 +127,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
render_device = params.rendering_device;
execution_mode = params.execution_mode;
core.Memory().ZeroBlock(*core.Kernel().CurrentProcess(), transfer_memory->GetSourceAddress(),
core.Memory().ZeroBlock(*core.ApplicationProcess(), transfer_memory->GetSourceAddress(),
transfer_memory_size);
// Note: We're not actually using the transfer memory because it's a pain to code for.

View File

@@ -94,7 +94,7 @@ bool SystemManager::Remove(System& system_) {
}
void SystemManager::ThreadFunc() {
constexpr char name[]{"AudioRenderSystemManager"};
static constexpr char name[]{"AudioRenderSystemManager"};
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);

View File

@@ -35,7 +35,7 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::vector<s16>& samples) {
if (system_channels == 6 && device_channels == 2) {
// We're given 6 channels, but our device only outputs 2, so downmix.
constexpr std::array<f32, 4> down_mix_coeff{1.0f, 0.707f, 0.251f, 0.707f};
static constexpr std::array<f32, 4> down_mix_coeff{1.0f, 0.707f, 0.251f, 0.707f};
for (u32 read_index = 0, write_index = 0; read_index < samples.size();
read_index += system_channels, write_index += device_channels) {
@@ -202,7 +202,7 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
// If we're paused or going to shut down, we don't want to consume buffers as coretiming is
// paused and we'll desync, so just play silence.
if (system.IsPaused() || system.IsShuttingDown()) {
constexpr std::array<s16, 6> silence{};
static constexpr std::array<s16, 6> silence{};
for (size_t i = frames_written; i < num_frames; i++) {
std::memcpy(&output_buffer[i * frame_size], &silence[0], frame_size_bytes);
}
@@ -270,7 +270,7 @@ void SinkStream::Stall() {
if (stalled_lock) {
return;
}
stalled_lock = system.StallProcesses();
stalled_lock = system.StallApplication();
}
void SinkStream::Unstall() {
@@ -278,7 +278,7 @@ void SinkStream::Unstall() {
if (!stalled_lock) {
return;
}
system.UnstallProcesses();
system.UnstallApplication();
stalled_lock.unlock();
}

View File

@@ -225,6 +225,8 @@ add_library(core STATIC
hle/kernel/k_memory_manager.h
hle/kernel/k_memory_region.h
hle/kernel/k_memory_region_type.h
hle/kernel/k_object_name.cpp
hle/kernel/k_object_name.h
hle/kernel/k_page_bitmap.h
hle/kernel/k_page_buffer.cpp
hle/kernel/k_page_buffer.h
@@ -291,8 +293,6 @@ add_library(core STATIC
hle/kernel/physical_memory.h
hle/kernel/process_capability.cpp
hle/kernel/process_capability.h
hle/kernel/service_thread.cpp
hle/kernel/service_thread.h
hle/kernel/slab_helpers.h
hle/kernel/svc.cpp
hle/kernel/svc.h
@@ -384,8 +384,6 @@ add_library(core STATIC
hle/service/am/omm.h
hle/service/am/spsm.cpp
hle/service/am/spsm.h
hle/service/am/tcap.cpp
hle/service/am/tcap.h
hle/service/aoc/aoc_u.cpp
hle/service/aoc/aoc_u.h
hle/service/apm/apm.cpp
@@ -396,28 +394,18 @@ add_library(core STATIC
hle/service/apm/apm_interface.h
hle/service/audio/audctl.cpp
hle/service/audio/audctl.h
hle/service/audio/auddbg.cpp
hle/service/audio/auddbg.h
hle/service/audio/audin_a.cpp
hle/service/audio/audin_a.h
hle/service/audio/audin_u.cpp
hle/service/audio/audin_u.h
hle/service/audio/audio.cpp
hle/service/audio/audio.h
hle/service/audio/audout_a.cpp
hle/service/audio/audout_a.h
hle/service/audio/audout_u.cpp
hle/service/audio/audout_u.h
hle/service/audio/audrec_a.cpp
hle/service/audio/audrec_a.h
hle/service/audio/audrec_u.cpp
hle/service/audio/audrec_u.h
hle/service/audio/audren_a.cpp
hle/service/audio/audren_a.h
hle/service/audio/audren_u.cpp
hle/service/audio/audren_u.h
hle/service/audio/codecctl.cpp
hle/service/audio/codecctl.h
hle/service/audio/errors.h
hle/service/audio/hwopus.cpp
hle/service/audio/hwopus.h
@@ -694,6 +682,10 @@ add_library(core STATIC
hle/service/ptm/ts.h
hle/service/kernel_helpers.cpp
hle/service/kernel_helpers.h
hle/service/mutex.cpp
hle/service/mutex.h
hle/service/server_manager.cpp
hle/service/server_manager.h
hle/service/service.cpp
hle/service/service.h
hle/service/set/set.cpp
@@ -712,8 +704,6 @@ add_library(core STATIC
hle/service/sm/sm_controller.h
hle/service/sockets/bsd.cpp
hle/service/sockets/bsd.h
hle/service/sockets/ethc.cpp
hle/service/sockets/ethc.h
hle/service/sockets/nsd.cpp
hle/service/sockets/nsd.h
hle/service/sockets/sfdnsres.cpp
@@ -780,8 +770,6 @@ add_library(core STATIC
hle/service/vi/vi_s.h
hle/service/vi/vi_u.cpp
hle/service/vi/vi_u.h
hle/service/wlan/wlan.cpp
hle/service/wlan/wlan.h
internal_network/network.cpp
internal_network/network.h
internal_network/network_interface.cpp

View File

@@ -43,9 +43,9 @@ void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<Backt
std::map<std::string, Symbols::Symbols> symbols;
for (const auto& module : modules) {
symbols.insert_or_assign(module.second,
Symbols::GetSymbols(module.first, system.Memory(),
system.CurrentProcess()->Is64BitProcess()));
symbols.insert_or_assign(
module.second, Symbols::GetSymbols(module.first, system.Memory(),
system.ApplicationProcess()->Is64BitProcess()));
}
for (auto& entry : out) {

View File

@@ -186,7 +186,7 @@ struct System::Impl {
void Run() {
std::unique_lock<std::mutex> lk(suspend_guard);
kernel.Suspend(false);
kernel.SuspendApplication(false);
core_timing.SyncPause(false);
is_paused.store(false, std::memory_order_relaxed);
}
@@ -195,7 +195,7 @@ struct System::Impl {
std::unique_lock<std::mutex> lk(suspend_guard);
core_timing.SyncPause(true);
kernel.Suspend(true);
kernel.SuspendApplication(true);
is_paused.store(true, std::memory_order_relaxed);
}
@@ -203,17 +203,17 @@ struct System::Impl {
return is_paused.load(std::memory_order_relaxed);
}
std::unique_lock<std::mutex> StallProcesses() {
std::unique_lock<std::mutex> StallApplication() {
std::unique_lock<std::mutex> lk(suspend_guard);
kernel.Suspend(true);
kernel.SuspendApplication(true);
core_timing.SyncPause(true);
return lk;
}
void UnstallProcesses() {
void UnstallApplication() {
if (!IsPaused()) {
core_timing.SyncPause(false);
kernel.Suspend(false);
kernel.SuspendApplication(false);
}
}
@@ -221,7 +221,7 @@ struct System::Impl {
debugger = std::make_unique<Debugger>(system, port);
}
SystemResultStatus SetupForMainProcess(System& system, Frontend::EmuWindow& emu_window) {
SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) {
LOG_DEBUG(Core, "initialized OK");
// Setting changes may require a full system reinitialization (e.g., disabling multicore).
@@ -273,7 +273,7 @@ struct System::Impl {
return SystemResultStatus::ErrorGetLoader;
}
SystemResultStatus init_result{SetupForMainProcess(system, emu_window)};
SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)};
if (init_result != SystemResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to initialize system (Error {})!",
static_cast<int>(init_result));
@@ -302,7 +302,7 @@ struct System::Impl {
static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
}
AddGlueRegistrationForProcess(*app_loader, *main_process);
kernel.MakeCurrentProcess(main_process);
kernel.MakeApplicationProcess(main_process);
kernel.InitializeCores();
// Initialize cheat engine
@@ -380,9 +380,7 @@ struct System::Impl {
gpu_core->NotifyShutdown();
}
kernel.ShutdownCores();
cpu_manager.Shutdown();
debugger.reset();
kernel.SuspendApplication(true);
if (services) {
services->KillNVNFlinger();
}
@@ -398,6 +396,9 @@ struct System::Impl {
gpu_core.reset();
host1x_core.reset();
perf_stats.reset();
kernel.ShutdownCores();
cpu_manager.Shutdown();
debugger.reset();
kernel.Shutdown();
memory.Reset();
@@ -585,12 +586,12 @@ void System::DetachDebugger() {
}
}
std::unique_lock<std::mutex> System::StallProcesses() {
return impl->StallProcesses();
std::unique_lock<std::mutex> System::StallApplication() {
return impl->StallApplication();
}
void System::UnstallProcesses() {
impl->UnstallProcesses();
void System::UnstallApplication() {
impl->UnstallApplication();
}
void System::InitializeDebugger() {
@@ -648,8 +649,8 @@ const Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() const {
return impl->kernel.GlobalSchedulerContext();
}
Kernel::KProcess* System::CurrentProcess() {
return impl->kernel.CurrentProcess();
Kernel::KProcess* System::ApplicationProcess() {
return impl->kernel.ApplicationProcess();
}
Core::DeviceMemory& System::DeviceMemory() {
@@ -660,8 +661,8 @@ const Core::DeviceMemory& System::DeviceMemory() const {
return *impl->device_memory;
}
const Kernel::KProcess* System::CurrentProcess() const {
return impl->kernel.CurrentProcess();
const Kernel::KProcess* System::ApplicationProcess() const {
return impl->kernel.ApplicationProcess();
}
ARM_Interface& System::ArmInterface(std::size_t core_index) {
@@ -760,8 +761,8 @@ const Core::SpeedLimiter& System::SpeedLimiter() const {
return impl->speed_limiter;
}
u64 System::GetCurrentProcessProgramID() const {
return impl->kernel.CurrentProcess()->GetProgramID();
u64 System::GetApplicationProcessProgramID() const {
return impl->kernel.ApplicationProcess()->GetProgramID();
}
Loader::ResultStatus System::GetGameName(std::string& out) const {
@@ -880,11 +881,11 @@ bool System::GetExitLock() const {
return impl->exit_lock;
}
void System::SetCurrentProcessBuildID(const CurrentBuildProcessID& id) {
void System::SetApplicationProcessBuildID(const CurrentBuildProcessID& id) {
impl->build_id = id;
}
const System::CurrentBuildProcessID& System::GetCurrentProcessBuildID() const {
const System::CurrentBuildProcessID& System::GetApplicationProcessBuildID() const {
return impl->build_id;
}
@@ -938,6 +939,10 @@ const Network::RoomNetwork& System::GetRoomNetwork() const {
return impl->room_network;
}
void System::RunServer(std::unique_ptr<Service::ServerManager>&& server_manager) {
return impl->kernel.RunServer(std::move(server_manager));
}
void System::RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback) {
impl->execute_program_callback = std::move(callback);
}

View File

@@ -61,6 +61,8 @@ namespace Glue {
class ARPManager;
}
class ServerManager;
namespace SM {
class ServiceManager;
} // namespace SM
@@ -184,8 +186,8 @@ public:
/// Forcibly detach the debugger if it is running.
void DetachDebugger();
std::unique_lock<std::mutex> StallProcesses();
void UnstallProcesses();
std::unique_lock<std::mutex> StallApplication();
void UnstallApplication();
/**
* Initialize the debugger.
@@ -295,11 +297,11 @@ public:
/// Gets the manager for the guest device memory
[[nodiscard]] const Core::DeviceMemory& DeviceMemory() const;
/// Provides a pointer to the current process
[[nodiscard]] Kernel::KProcess* CurrentProcess();
/// Provides a pointer to the application process
[[nodiscard]] Kernel::KProcess* ApplicationProcess();
/// Provides a constant pointer to the current process.
[[nodiscard]] const Kernel::KProcess* CurrentProcess() const;
/// Provides a constant pointer to the application process.
[[nodiscard]] const Kernel::KProcess* ApplicationProcess() const;
/// Provides a reference to the core timing instance.
[[nodiscard]] Timing::CoreTiming& CoreTiming();
@@ -331,7 +333,7 @@ public:
/// Provides a constant reference to the speed limiter
[[nodiscard]] const Core::SpeedLimiter& SpeedLimiter() const;
[[nodiscard]] u64 GetCurrentProcessProgramID() const;
[[nodiscard]] u64 GetApplicationProcessProgramID() const;
/// Gets the name of the current game
[[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const;
@@ -396,8 +398,8 @@ public:
void SetExitLock(bool locked);
[[nodiscard]] bool GetExitLock() const;
void SetCurrentProcessBuildID(const CurrentBuildProcessID& id);
[[nodiscard]] const CurrentBuildProcessID& GetCurrentProcessBuildID() const;
void SetApplicationProcessBuildID(const CurrentBuildProcessID& id);
[[nodiscard]] const CurrentBuildProcessID& GetApplicationProcessBuildID() const;
/// Register a host thread as an emulated CPU Core.
void RegisterCoreThread(std::size_t id);
@@ -417,6 +419,9 @@ public:
/// Tells if the system debugger is enabled.
[[nodiscard]] bool DebuggerEnabled() const;
/// Runs a server instance until shutdown.
void RunServer(std::unique_ptr<Service::ServerManager>&& server_manager);
/// Type used for the frontend to designate a callback for System to re-launch the application
/// using a specified program index.
using ExecuteProgramCallback = std::function<void(std::size_t)>;

View File

@@ -45,7 +45,7 @@ CoreTiming::~CoreTiming() {
}
void CoreTiming::ThreadEntry(CoreTiming& instance) {
constexpr char name[] = "HostTiming";
static constexpr char name[] = "HostTiming";
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical);

View File

@@ -16,6 +16,7 @@
#include "core/debugger/debugger_interface.h"
#include "core/debugger/gdbstub.h"
#include "core/hle/kernel/global_scheduler_context.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_scheduler.h"
template <typename Readable, typename Buffer, typename Callback>
@@ -284,12 +285,12 @@ private:
void UpdateActiveThread() {
const auto& threads{ThreadList()};
if (std::find(threads.begin(), threads.end(), state->active_thread) == threads.end()) {
state->active_thread = threads[0];
state->active_thread = threads.front();
}
}
const std::vector<Kernel::KThread*>& ThreadList() {
return system.GlobalSchedulerContext().GetThreadList();
const std::list<Kernel::KThread*>& ThreadList() {
return system.ApplicationProcess()->GetThreadList();
}
private:

View File

@@ -96,7 +96,7 @@ static std::string EscapeXML(std::string_view data) {
GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_)
: DebuggerFrontend(backend_), system{system_} {
if (system.CurrentProcess()->Is64BitProcess()) {
if (system.ApplicationProcess()->Is64BitProcess()) {
arch = std::make_unique<GDBStubA64>();
} else {
arch = std::make_unique<GDBStubA32>();
@@ -340,15 +340,15 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
success = true;
break;
case BreakpointType::WriteWatch:
success = system.CurrentProcess()->InsertWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Write);
success = system.ApplicationProcess()->InsertWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Write);
break;
case BreakpointType::ReadWatch:
success = system.CurrentProcess()->InsertWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Read);
success = system.ApplicationProcess()->InsertWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Read);
break;
case BreakpointType::AccessWatch:
success = system.CurrentProcess()->InsertWatchpoint(
success = system.ApplicationProcess()->InsertWatchpoint(
system, addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
break;
case BreakpointType::Hardware:
@@ -391,15 +391,15 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
break;
}
case BreakpointType::WriteWatch:
success = system.CurrentProcess()->RemoveWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Write);
success = system.ApplicationProcess()->RemoveWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Write);
break;
case BreakpointType::ReadWatch:
success = system.CurrentProcess()->RemoveWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Read);
success = system.ApplicationProcess()->RemoveWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Read);
break;
case BreakpointType::AccessWatch:
success = system.CurrentProcess()->RemoveWatchpoint(
success = system.ApplicationProcess()->RemoveWatchpoint(
system, addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
break;
case BreakpointType::Hardware:
@@ -482,7 +482,7 @@ static std::optional<std::string> GetNameFromThreadType64(Core::Memory::Memory&
static std::optional<std::string> GetThreadName(Core::System& system,
const Kernel::KThread* thread) {
if (system.CurrentProcess()->Is64BitProcess()) {
if (system.ApplicationProcess()->Is64BitProcess()) {
return GetNameFromThreadType64(system.Memory(), thread);
} else {
return GetNameFromThreadType32(system.Memory(), thread);
@@ -555,7 +555,7 @@ void GDBStub::HandleQuery(std::string_view command) {
SendReply(fmt::format("TextSeg={:x}", main->first));
} else {
SendReply(fmt::format("TextSeg={:x}",
system.CurrentProcess()->PageTable().GetCodeRegionStart()));
system.ApplicationProcess()->PageTable().GetCodeRegionStart()));
}
} else if (command.starts_with("Xfer:libraries:read::")) {
Loader::AppLoader::Modules modules;
@@ -573,7 +573,7 @@ void GDBStub::HandleQuery(std::string_view command) {
SendReply(PaginateBuffer(buffer, command.substr(21)));
} else if (command.starts_with("fThreadInfo")) {
// beginning of list
const auto& threads = system.GlobalSchedulerContext().GetThreadList();
const auto& threads = system.ApplicationProcess()->GetThreadList();
std::vector<std::string> thread_ids;
for (const auto& thread : threads) {
thread_ids.push_back(fmt::format("{:x}", thread->GetThreadID()));
@@ -587,7 +587,7 @@ void GDBStub::HandleQuery(std::string_view command) {
buffer += R"(<?xml version="1.0"?>)";
buffer += "<threads>";
const auto& threads = system.GlobalSchedulerContext().GetThreadList();
const auto& threads = system.ApplicationProcess()->GetThreadList();
for (const auto* thread : threads) {
auto thread_name{GetThreadName(system, thread)};
if (!thread_name) {
@@ -729,7 +729,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()};
std::string reply;
auto* process = system.CurrentProcess();
auto* process = system.ApplicationProcess();
auto& page_table = process->PageTable();
const char* commands = "Commands:\n"
@@ -817,7 +817,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
}
Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) {
const auto& threads{system.GlobalSchedulerContext().GetThreadList()};
const auto& threads{system.ApplicationProcess()->GetThreadList()};
for (auto* thread : threads) {
if (thread->GetThreadID() == thread_id) {
return thread;

View File

@@ -41,9 +41,8 @@ static void PutSIMDRegister(std::array<u32, 64>& simd_regs, size_t offset, const
// For sample XML files see the GDB source /gdb/features
// This XML defines what the registers are for this specific ARM device
std::string GDBStubA64::GetTargetXML() const {
constexpr const char* target_xml =
R"(<?xml version="1.0"?>
std::string_view GDBStubA64::GetTargetXML() const {
return R"(<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target version="1.0">
<architecture>aarch64</architecture>
@@ -178,8 +177,6 @@ std::string GDBStubA64::GetTargetXML() const {
<reg name="fpcr" bitsize="32"/>
</feature>
</target>)";
return target_xml;
}
std::string GDBStubA64::RegRead(const Kernel::KThread* thread, size_t id) const {
@@ -270,9 +267,8 @@ u32 GDBStubA64::BreakpointInstruction() const {
return 0xd4200000;
}
std::string GDBStubA32::GetTargetXML() const {
constexpr const char* target_xml =
R"(<?xml version="1.0"?>
std::string_view GDBStubA32::GetTargetXML() const {
return R"(<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target version="1.0">
<architecture>arm</architecture>
@@ -378,8 +374,6 @@ std::string GDBStubA32::GetTargetXML() const {
<reg name="fpscr" bitsize="32" type="int" group="float" regnum="80"/>
</feature>
</target>)";
return target_xml;
}
std::string GDBStubA32::RegRead(const Kernel::KThread* thread, size_t id) const {

View File

@@ -16,7 +16,7 @@ namespace Core {
class GDBStubArch {
public:
virtual ~GDBStubArch() = default;
virtual std::string GetTargetXML() const = 0;
virtual std::string_view GetTargetXML() const = 0;
virtual std::string RegRead(const Kernel::KThread* thread, size_t id) const = 0;
virtual void RegWrite(Kernel::KThread* thread, size_t id, std::string_view value) const = 0;
virtual std::string ReadRegisters(const Kernel::KThread* thread) const = 0;
@@ -27,7 +27,7 @@ public:
class GDBStubA64 final : public GDBStubArch {
public:
std::string GetTargetXML() const override;
std::string_view GetTargetXML() const override;
std::string RegRead(const Kernel::KThread* thread, size_t id) const override;
void RegWrite(Kernel::KThread* thread, size_t id, std::string_view value) const override;
std::string ReadRegisters(const Kernel::KThread* thread) const override;
@@ -47,7 +47,7 @@ private:
class GDBStubA32 final : public GDBStubArch {
public:
std::string GetTargetXML() const override;
std::string_view GetTargetXML() const override;
std::string RegRead(const Kernel::KThread* thread, size_t id) const override;
void RegWrite(Kernel::KThread* thread, size_t id, std::string_view value) const override;
std::string ReadRegisters(const Kernel::KThread* thread) const override;

View File

@@ -41,12 +41,12 @@ static IPSFileType IdentifyMagic(const std::vector<u8>& magic) {
return IPSFileType::Error;
}
constexpr std::array<u8, 5> patch_magic{{'P', 'A', 'T', 'C', 'H'}};
static constexpr std::array<u8, 5> patch_magic{{'P', 'A', 'T', 'C', 'H'}};
if (std::equal(magic.begin(), magic.end(), patch_magic.begin())) {
return IPSFileType::IPS;
}
constexpr std::array<u8, 5> ips32_magic{{'I', 'P', 'S', '3', '2'}};
static constexpr std::array<u8, 5> ips32_magic{{'I', 'P', 'S', '3', '2'}};
if (std::equal(magic.begin(), magic.end(), ips32_magic.begin())) {
return IPSFileType::IPS32;
}
@@ -55,12 +55,12 @@ static IPSFileType IdentifyMagic(const std::vector<u8>& magic) {
}
static bool IsEOF(IPSFileType type, const std::vector<u8>& data) {
constexpr std::array<u8, 3> eof{{'E', 'O', 'F'}};
static constexpr std::array<u8, 3> eof{{'E', 'O', 'F'}};
if (type == IPSFileType::IPS && std::equal(data.begin(), data.end(), eof.begin())) {
return true;
}
constexpr std::array<u8, 4> eeof{{'E', 'E', 'O', 'F'}};
static constexpr std::array<u8, 4> eeof{{'E', 'E', 'O', 'F'}};
return type == IPSFileType::IPS32 && std::equal(data.begin(), data.end(), eeof.begin());
}

View File

@@ -71,7 +71,7 @@ static std::string GetRelativePathFromNcaID(const std::array<u8, 16>& nca_id, bo
}
static std::string GetCNMTName(TitleType type, u64 title_id) {
constexpr std::array<const char*, 9> TITLE_TYPE_NAMES{
static constexpr std::array<const char*, 9> TITLE_TYPE_NAMES{
"SystemProgram",
"SystemData",
"SystemUpdate",

View File

@@ -172,7 +172,7 @@ std::string SaveDataFactory::GetFullPath(Core::System& system, VirtualDir dir,
// be interpreted as the title id of the current process.
if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) {
if (title_id == 0) {
title_id = system.GetCurrentProcessProgramID();
title_id = system.GetApplicationProcessProgramID();
}
}

View File

@@ -23,7 +23,8 @@ void EmulatedConsole::SetTouchParams() {
// We can't use mouse as touch if native mouse is enabled
if (!Settings::values.mouse_enabled) {
touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"};
touch_params[index++] =
Common::ParamPackage{"engine:mouse,axis_x:0,axis_y:1,button:0,port:2"};
}
touch_params[index++] =

View File

@@ -34,9 +34,12 @@ void EmulatedDevices::ReloadInput() {
// First two axis are reserved for mouse position
key_index = 2;
for (auto& mouse_device : mouse_analog_devices) {
// Mouse axis are only mapped on port 1, pad 0
Common::ParamPackage mouse_params;
mouse_params.Set("engine", "mouse");
mouse_params.Set("axis", static_cast<int>(key_index));
mouse_params.Set("port", 1);
mouse_params.Set("pad", 0);
mouse_device = Common::Input::CreateInputDevice(mouse_params);
key_index++;
}

View File

@@ -15,6 +15,7 @@
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_session.h"
#include "core/hle/result.h"
#include "core/hle/service/server_manager.h"
namespace IPC {
@@ -145,16 +146,21 @@ public:
template <class T>
void PushIpcInterface(std::shared_ptr<T> iface) {
if (context->GetManager()->IsDomain()) {
auto manager{context->GetManager()};
if (manager->IsDomain()) {
context->AddDomainObject(std::move(iface));
} else {
kernel.CurrentProcess()->GetResourceLimit()->Reserve(
kernel.ApplicationProcess()->GetResourceLimit()->Reserve(
Kernel::LimitableResource::SessionCountMax, 1);
auto* session = Kernel::KSession::Create(kernel);
session->Initialize(nullptr, iface->GetServiceName());
iface->RegisterSession(&session->GetServerSession(),
std::make_shared<Kernel::SessionRequestManager>(kernel));
auto next_manager = std::make_shared<Kernel::SessionRequestManager>(
kernel, manager->GetServerManager());
next_manager->SetSessionHandler(iface);
manager->GetServerManager().RegisterSession(&session->GetServerSession(), next_manager);
context->AddMoveObject(&session->GetClientSession());
}

View File

@@ -21,36 +21,18 @@
#include "core/hle/kernel/k_server_session.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/service_thread.h"
#include "core/memory.h"
namespace Kernel {
SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_,
ServiceThreadType thread_type)
: kernel{kernel_}, service_thread{thread_type == ServiceThreadType::CreateNew
? kernel.CreateServiceThread(service_name_)
: kernel.GetDefaultServiceThread()} {}
SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_)
: kernel{kernel_} {}
SessionRequestHandler::~SessionRequestHandler() {
kernel.ReleaseServiceThread(service_thread);
}
SessionRequestHandler::~SessionRequestHandler() = default;
void SessionRequestHandler::AcceptSession(KServerPort* server_port) {
auto* server_session = server_port->AcceptSession();
ASSERT(server_session != nullptr);
RegisterSession(server_session, std::make_shared<SessionRequestManager>(kernel));
}
void SessionRequestHandler::RegisterSession(KServerSession* server_session,
std::shared_ptr<SessionRequestManager> manager) {
manager->SetSessionHandler(shared_from_this());
service_thread.RegisterServerSession(server_session, manager);
server_session->Close();
}
SessionRequestManager::SessionRequestManager(KernelCore& kernel_) : kernel{kernel_} {}
SessionRequestManager::SessionRequestManager(KernelCore& kernel_,
Service::ServerManager& server_manager_)
: kernel{kernel_}, server_manager{server_manager_} {}
SessionRequestManager::~SessionRequestManager() = default;

View File

@@ -31,12 +31,8 @@ class ResponseBuilder;
namespace Service {
class ServiceFrameworkBase;
}
enum class ServiceThreadType {
Default,
CreateNew,
};
class ServerManager;
} // namespace Service
namespace Kernel {
@@ -53,9 +49,6 @@ class KThread;
class KReadableEvent;
class KSession;
class SessionRequestManager;
class ServiceThread;
enum class ThreadWakeupReason;
/**
* Interface implemented by HLE Session handlers.
@@ -64,8 +57,7 @@ enum class ThreadWakeupReason;
*/
class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> {
public:
SessionRequestHandler(KernelCore& kernel_, const char* service_name_,
ServiceThreadType thread_type);
SessionRequestHandler(KernelCore& kernel_, const char* service_name_);
virtual ~SessionRequestHandler();
/**
@@ -79,17 +71,8 @@ public:
virtual Result HandleSyncRequest(Kernel::KServerSession& session,
Kernel::HLERequestContext& context) = 0;
void AcceptSession(KServerPort* server_port);
void RegisterSession(KServerSession* server_session,
std::shared_ptr<SessionRequestManager> manager);
ServiceThread& GetServiceThread() const {
return service_thread;
}
protected:
KernelCore& kernel;
ServiceThread& service_thread;
};
using SessionRequestHandlerWeakPtr = std::weak_ptr<SessionRequestHandler>;
@@ -102,7 +85,7 @@ using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>;
*/
class SessionRequestManager final {
public:
explicit SessionRequestManager(KernelCore& kernel);
explicit SessionRequestManager(KernelCore& kernel, Service::ServerManager& server_manager);
~SessionRequestManager();
bool IsDomain() const {
@@ -155,23 +138,36 @@ public:
session_handler = std::move(handler);
}
ServiceThread& GetServiceThread() const {
return session_handler->GetServiceThread();
}
bool HasSessionRequestHandler(const HLERequestContext& context) const;
Result HandleDomainSyncRequest(KServerSession* server_session, HLERequestContext& context);
Result CompleteSyncRequest(KServerSession* server_session, HLERequestContext& context);
Service::ServerManager& GetServerManager() {
return server_manager;
}
// TODO: remove this when sm: is implemented with the proper IUserInterface
// abstraction, creating a new C++ handler object for each session:
bool GetIsInitializedForSm() const {
return is_initialized_for_sm;
}
void SetIsInitializedForSm() {
is_initialized_for_sm = true;
}
private:
bool convert_to_domain{};
bool is_domain{};
bool is_initialized_for_sm{};
SessionRequestHandlerPtr session_handler;
std::vector<SessionRequestHandlerPtr> domain_handlers;
private:
KernelCore& kernel;
Service::ServerManager& server_manager;
};
/**
@@ -374,6 +370,14 @@ public:
return manager.lock();
}
bool GetIsDeferred() const {
return is_deferred;
}
void SetIsDeferred(bool is_deferred_ = true) {
is_deferred = is_deferred_;
}
private:
friend class IPC::ResponseBuilder;
@@ -408,6 +412,7 @@ private:
u32 domain_offset{};
std::weak_ptr<SessionRequestManager> manager{};
bool is_deferred{false};
KernelCore& kernel;
Core::Memory::Memory& memory;

View File

@@ -16,6 +16,7 @@
#include "core/hle/kernel/k_event_info.h"
#include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_memory_manager.h"
#include "core/hle/kernel/k_object_name.h"
#include "core/hle/kernel/k_page_buffer.h"
#include "core/hle/kernel/k_port.h"
#include "core/hle/kernel/k_process.h"
@@ -49,6 +50,7 @@ namespace Kernel::Init {
HANDLER(KThreadLocalPage, \
(SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), \
##__VA_ARGS__) \
HANDLER(KObjectName, (SLAB_COUNT(KObjectName)), ##__VA_ARGS__) \
HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__) \
HANDLER(KEventInfo, (SLAB_COUNT(KThread) + SLAB_COUNT(KDebug)), ##__VA_ARGS__) \
HANDLER(KDebug, (SLAB_COUNT(KDebug)), ##__VA_ARGS__) \

View File

@@ -60,7 +60,8 @@ bool KClientPort::IsSignaled() const {
Result KClientPort::CreateSession(KClientSession** out) {
// Reserve a new session from the resource limit.
KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(),
//! FIXME: we are reserving this from the wrong resource limit!
KScopedResourceReservation session_reservation(kernel.ApplicationProcess()->GetResourceLimit(),
LimitableResource::SessionCountMax);
R_UNLESS(session_reservation.Succeeded(), ResultLimitReached);

View File

@@ -21,7 +21,7 @@ KCodeMemory::KCodeMemory(KernelCore& kernel_)
Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr, size_t size) {
// Set members.
m_owner = kernel.CurrentProcess();
m_owner = GetCurrentProcessPointer(kernel);
// Get the owner page table.
auto& page_table = m_owner->PageTable();
@@ -74,7 +74,7 @@ Result KCodeMemory::Map(VAddr address, size_t size) {
R_UNLESS(!m_is_mapped, ResultInvalidState);
// Map the memory.
R_TRY(kernel.CurrentProcess()->PageTable().MapPageGroup(
R_TRY(GetCurrentProcess(kernel).PageTable().MapPageGroup(
address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite));
// Mark ourselves as mapped.
@@ -91,8 +91,8 @@ Result KCodeMemory::Unmap(VAddr address, size_t size) {
KScopedLightLock lk(m_lock);
// Unmap the memory.
R_TRY(kernel.CurrentProcess()->PageTable().UnmapPageGroup(address, *m_page_group,
KMemoryState::CodeOut));
R_TRY(GetCurrentProcess(kernel).PageTable().UnmapPageGroup(address, *m_page_group,
KMemoryState::CodeOut));
// Mark ourselves as unmapped.
m_is_mapped = false;

View File

@@ -164,8 +164,8 @@ Result KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 value)
R_SUCCEED_IF(test_tag != (handle | Svc::HandleWaitMask));
// Get the lock owner thread.
owner_thread = kernel.CurrentProcess()
->GetHandleTable()
owner_thread = GetCurrentProcess(kernel)
.GetHandleTable()
.GetObjectWithoutPseudoHandle<KThread>(handle)
.ReleasePointerUnsafe();
R_UNLESS(owner_thread != nullptr, ResultInvalidHandle);
@@ -213,8 +213,8 @@ void KConditionVariable::SignalImpl(KThread* thread) {
thread->EndWait(ResultSuccess);
} else {
// Get the previous owner.
KThread* owner_thread = kernel.CurrentProcess()
->GetHandleTable()
KThread* owner_thread = GetCurrentProcess(kernel)
.GetHandleTable()
.GetObjectWithoutPseudoHandle<KThread>(
static_cast<Handle>(prev_tag & ~Svc::HandleWaitMask))
.ReleasePointerUnsafe();

View File

@@ -90,7 +90,8 @@ public:
// Handle pseudo-handles.
if constexpr (std::derived_from<KProcess, T>) {
if (handle == Svc::PseudoHandle::CurrentProcess) {
auto* const cur_process = m_kernel.CurrentProcess();
//! FIXME: this is the wrong process!
auto* const cur_process = m_kernel.ApplicationProcess();
ASSERT(cur_process != nullptr);
return cur_process;
}

View File

@@ -16,7 +16,7 @@ void HandleInterrupt(KernelCore& kernel, s32 core_id) {
auto& current_thread = GetCurrentThread(kernel);
if (auto* process = kernel.CurrentProcess(); process) {
if (auto* process = GetCurrentProcessPointer(kernel); process) {
// If the user disable count is set, we may need to pin the current thread.
if (current_thread.GetUserDisableCount() && !process->GetPinnedThread(core_id)) {
KScopedSchedulerLock sl{kernel};

View File

@@ -0,0 +1,102 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/k_object_name.h"
namespace Kernel {
KObjectNameGlobalData::KObjectNameGlobalData(KernelCore& kernel) : m_object_list_lock{kernel} {}
KObjectNameGlobalData::~KObjectNameGlobalData() = default;
void KObjectName::Initialize(KAutoObject* obj, const char* name) {
// Set member variables.
m_object = obj;
std::strncpy(m_name.data(), name, sizeof(m_name) - 1);
m_name[sizeof(m_name) - 1] = '\x00';
// Open a reference to the object we hold.
m_object->Open();
}
bool KObjectName::MatchesName(const char* name) const {
return std::strncmp(m_name.data(), name, sizeof(m_name)) == 0;
}
Result KObjectName::NewFromName(KernelCore& kernel, KAutoObject* obj, const char* name) {
// Create a new object name.
KObjectName* new_name = KObjectName::Allocate(kernel);
R_UNLESS(new_name != nullptr, ResultOutOfResource);
// Initialize the new name.
new_name->Initialize(obj, name);
// Check if there's an existing name.
{
// Get the global data.
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
// Ensure we have exclusive access to the global list.
KScopedLightLock lk{gd.GetObjectListLock()};
// If the object doesn't exist, put it into the list.
KScopedAutoObject existing_object = FindImpl(kernel, name);
if (existing_object.IsNull()) {
gd.GetObjectList().push_back(*new_name);
R_SUCCEED();
}
}
// The object already exists, which is an error condition. Perform cleanup.
obj->Close();
KObjectName::Free(kernel, new_name);
R_THROW(ResultInvalidState);
}
Result KObjectName::Delete(KernelCore& kernel, KAutoObject* obj, const char* compare_name) {
// Get the global data.
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
// Ensure we have exclusive access to the global list.
KScopedLightLock lk{gd.GetObjectListLock()};
// Find a matching entry in the list, and delete it.
for (auto& name : gd.GetObjectList()) {
if (name.MatchesName(compare_name) && obj == name.GetObject()) {
// We found a match, clean up its resources.
obj->Close();
gd.GetObjectList().erase(gd.GetObjectList().iterator_to(name));
KObjectName::Free(kernel, std::addressof(name));
R_SUCCEED();
}
}
// We didn't find the object in the list.
R_THROW(ResultNotFound);
}
KScopedAutoObject<KAutoObject> KObjectName::Find(KernelCore& kernel, const char* name) {
// Get the global data.
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
// Ensure we have exclusive access to the global list.
KScopedLightLock lk{gd.GetObjectListLock()};
return FindImpl(kernel, name);
}
KScopedAutoObject<KAutoObject> KObjectName::FindImpl(KernelCore& kernel, const char* compare_name) {
// Get the global data.
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
// Try to find a matching object in the global list.
for (const auto& name : gd.GetObjectList()) {
if (name.MatchesName(compare_name)) {
return name.GetObject();
}
}
// There's no matching entry in the list.
return nullptr;
}
} // namespace Kernel

View File

@@ -0,0 +1,86 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <memory>
#include <boost/intrusive/list.hpp>
#include "core/hle/kernel/k_light_lock.h"
#include "core/hle/kernel/slab_helpers.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel {
class KObjectNameGlobalData;
class KObjectName : public KSlabAllocated<KObjectName>, public boost::intrusive::list_base_hook<> {
public:
explicit KObjectName(KernelCore&) {}
virtual ~KObjectName() = default;
static constexpr size_t NameLengthMax = 12;
using List = boost::intrusive::list<KObjectName>;
static Result NewFromName(KernelCore& kernel, KAutoObject* obj, const char* name);
static Result Delete(KernelCore& kernel, KAutoObject* obj, const char* name);
static KScopedAutoObject<KAutoObject> Find(KernelCore& kernel, const char* name);
template <typename Derived>
static Result Delete(KernelCore& kernel, const char* name) {
// Find the object.
KScopedAutoObject obj = Find(kernel, name);
R_UNLESS(obj.IsNotNull(), ResultNotFound);
// Cast the object to the desired type.
Derived* derived = obj->DynamicCast<Derived*>();
R_UNLESS(derived != nullptr, ResultNotFound);
// Check that the object is closed.
R_UNLESS(derived->IsServerClosed(), ResultInvalidState);
return Delete(kernel, obj.GetPointerUnsafe(), name);
}
template <typename Derived>
requires(std::derived_from<Derived, KAutoObject>)
static KScopedAutoObject<Derived> Find(KernelCore& kernel, const char* name) {
return Find(kernel, name);
}
private:
static KScopedAutoObject<KAutoObject> FindImpl(KernelCore& kernel, const char* name);
void Initialize(KAutoObject* obj, const char* name);
bool MatchesName(const char* name) const;
KAutoObject* GetObject() const {
return m_object;
}
private:
std::array<char, NameLengthMax> m_name{};
KAutoObject* m_object{};
};
class KObjectNameGlobalData {
public:
explicit KObjectNameGlobalData(KernelCore& kernel);
~KObjectNameGlobalData();
KLightLock& GetObjectListLock() {
return m_object_list_lock;
}
KObjectName::List& GetObjectList() {
return m_object_list;
}
private:
KLightLock m_object_list_lock;
KObjectName::List m_object_list;
};
} // namespace Kernel

View File

@@ -119,7 +119,6 @@ void KProcess::DecrementRunningThreadCount() {
if (const auto prev = num_running_threads--; prev == 1) {
// TODO(bunnei): Process termination to be implemented when multiprocess is supported.
UNIMPLEMENTED_MSG("KProcess termination is not implemennted!");
}
}
@@ -357,9 +356,6 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
system_resource_size = metadata.GetSystemResourceSize();
image_size = code_size;
// We currently do not support process-specific system resource
UNIMPLEMENTED_IF(system_resource_size != 0);
KScopedResourceReservation memory_reservation(
resource_limit, LimitableResource::PhysicalMemoryMax, code_size + system_resource_size);
if (!memory_reservation.Succeeded()) {

View File

@@ -328,7 +328,7 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) {
}
void KScheduler::SwitchThread(KThread* next_thread) {
KProcess* const cur_process = kernel.CurrentProcess();
KProcess* const cur_process = GetCurrentProcessPointer(kernel);
KThread* const cur_thread = GetCurrentThreadPointer(kernel);
// We never want to schedule a null thread, so use the idle thread if we don't have a next.
@@ -689,11 +689,11 @@ void KScheduler::RotateScheduledQueue(KernelCore& kernel, s32 core_id, s32 prior
void KScheduler::YieldWithoutCoreMigration(KernelCore& kernel) {
// Validate preconditions.
ASSERT(CanSchedule(kernel));
ASSERT(kernel.CurrentProcess() != nullptr);
ASSERT(GetCurrentProcessPointer(kernel) != nullptr);
// Get the current thread and process.
KThread& cur_thread = GetCurrentThread(kernel);
KProcess& cur_process = *kernel.CurrentProcess();
KProcess& cur_process = GetCurrentProcess(kernel);
// If the thread's yield count matches, there's nothing for us to do.
if (cur_thread.GetYieldScheduleCount() == cur_process.GetScheduledCount()) {
@@ -728,11 +728,11 @@ void KScheduler::YieldWithoutCoreMigration(KernelCore& kernel) {
void KScheduler::YieldWithCoreMigration(KernelCore& kernel) {
// Validate preconditions.
ASSERT(CanSchedule(kernel));
ASSERT(kernel.CurrentProcess() != nullptr);
ASSERT(GetCurrentProcessPointer(kernel) != nullptr);
// Get the current thread and process.
KThread& cur_thread = GetCurrentThread(kernel);
KProcess& cur_process = *kernel.CurrentProcess();
KProcess& cur_process = GetCurrentProcess(kernel);
// If the thread's yield count matches, there's nothing for us to do.
if (cur_thread.GetYieldScheduleCount() == cur_process.GetScheduledCount()) {
@@ -816,11 +816,11 @@ void KScheduler::YieldWithCoreMigration(KernelCore& kernel) {
void KScheduler::YieldToAnyThread(KernelCore& kernel) {
// Validate preconditions.
ASSERT(CanSchedule(kernel));
ASSERT(kernel.CurrentProcess() != nullptr);
ASSERT(GetCurrentProcessPointer(kernel) != nullptr);
// Get the current thread and process.
KThread& cur_thread = GetCurrentThread(kernel);
KProcess& cur_process = *kernel.CurrentProcess();
KProcess& cur_process = GetCurrentProcess(kernel);
// If the thread's yield count matches, there's nothing for us to do.
if (cur_thread.GetYieldScheduleCount() == cur_process.GetScheduledCount()) {

View File

@@ -33,7 +33,8 @@ void KSession::Initialize(KClientPort* port_, const std::string& name_) {
name = name_;
// Set our owner process.
process = kernel.CurrentProcess();
//! FIXME: this is the wrong process!
process = kernel.ApplicationProcess();
process->Open();
// Set our port.

View File

@@ -29,6 +29,7 @@
#include "core/hle/kernel/k_thread_queue.h"
#include "core/hle/kernel/k_worker_task_manager.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h"
@@ -298,6 +299,25 @@ Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThr
ThreadType::User, system.GetCpuManager().GetGuestThreadFunc()));
}
Result KThread::InitializeServiceThread(Core::System& system, KThread* thread,
std::function<void()>&& func, s32 prio, s32 virt_core,
KProcess* owner) {
system.Kernel().GlobalSchedulerContext().AddThread(thread);
std::function<void()> func2{[&system, func{std::move(func)}] {
// Similar to UserModeThreadStarter.
system.Kernel().CurrentScheduler()->OnThreadStart();
// Run the guest function.
func();
// Exit.
Svc::ExitThread(system);
}};
R_RETURN(InitializeThread(thread, {}, {}, {}, prio, virt_core, owner, ThreadType::HighPriority,
std::move(func2)));
}
void KThread::PostDestroy(uintptr_t arg) {
KProcess* owner = reinterpret_cast<KProcess*>(arg & ~1ULL);
const bool resource_limit_release_hint = (arg & 1);
@@ -1266,6 +1286,14 @@ KThread& GetCurrentThread(KernelCore& kernel) {
return *GetCurrentThreadPointer(kernel);
}
KProcess* GetCurrentProcessPointer(KernelCore& kernel) {
return GetCurrentThread(kernel).GetOwnerProcess();
}
KProcess& GetCurrentProcess(KernelCore& kernel) {
return *GetCurrentProcessPointer(kernel);
}
s32 GetCurrentCoreId(KernelCore& kernel) {
return GetCurrentThread(kernel).GetCurrentCore();
}

View File

@@ -110,6 +110,8 @@ enum class StepState : u32 {
void SetCurrentThread(KernelCore& kernel, KThread* thread);
[[nodiscard]] KThread* GetCurrentThreadPointer(KernelCore& kernel);
[[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel);
[[nodiscard]] KProcess* GetCurrentProcessPointer(KernelCore& kernel);
[[nodiscard]] KProcess& GetCurrentProcess(KernelCore& kernel);
[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel);
class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>,
@@ -432,6 +434,10 @@ public:
VAddr user_stack_top, s32 prio, s32 virt_core,
KProcess* owner);
[[nodiscard]] static Result InitializeServiceThread(Core::System& system, KThread* thread,
std::function<void()>&& thread_func,
s32 prio, s32 virt_core, KProcess* owner);
public:
struct StackParameters {
u8 svc_permission[0x10];

View File

@@ -16,7 +16,7 @@ KTransferMemory::~KTransferMemory() = default;
Result KTransferMemory::Initialize(VAddr address_, std::size_t size_,
Svc::MemoryPermission owner_perm_) {
// Set members.
owner = kernel.CurrentProcess();
owner = GetCurrentProcessPointer(kernel);
// TODO(bunnei): Lock for transfer memory

View File

@@ -29,18 +29,20 @@
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_memory_manager.h"
#include "core/hle/kernel/k_object_name.h"
#include "core/hle/kernel/k_page_buffer.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_resource_reservation.h"
#include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/kernel/k_system_resource.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_worker_task_manager.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/service_thread.h"
#include "core/hle/result.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/sm/sm.h"
#include "core/memory.h"
@@ -54,9 +56,7 @@ struct KernelCore::Impl {
static constexpr size_t BlockInfoSlabHeapSize = 4000;
static constexpr size_t ReservedDynamicPageCount = 64;
explicit Impl(Core::System& system_, KernelCore& kernel_)
: service_threads_manager{1, "ServiceThreadsManager"},
service_thread_barrier{2}, system{system_} {}
explicit Impl(Core::System& system_, KernelCore& kernel_) : system{system_} {}
void SetMulticore(bool is_multi) {
is_multicore = is_multi;
@@ -84,6 +84,7 @@ struct KernelCore::Impl {
InitializeShutdownThreads();
InitializePhysicalCores();
InitializePreemption(kernel);
InitializeGlobalData(kernel);
// Initialize the Dynamic Slab Heaps.
{
@@ -96,19 +97,17 @@ struct KernelCore::Impl {
InitializeHackSharedMemory();
RegisterHostThread(nullptr);
default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread");
}
void InitializeCores() {
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
cores[core_id]->Initialize((*current_process).Is64BitProcess());
system.Memory().SetCurrentPageTable(*current_process, core_id);
cores[core_id]->Initialize((*application_process).Is64BitProcess());
system.Memory().SetCurrentPageTable(*application_process, core_id);
}
}
void CloseCurrentProcess() {
KProcess* old_process = current_process.exchange(nullptr);
void CloseApplicationProcess() {
KProcess* old_process = application_process.exchange(nullptr);
if (old_process == nullptr) {
return;
}
@@ -138,11 +137,6 @@ struct KernelCore::Impl {
preemption_event = nullptr;
for (auto& iter : named_ports) {
iter.second->Close();
}
named_ports.clear();
exclusive_monitor.reset();
// Cleanup persistent kernel objects
@@ -182,7 +176,7 @@ struct KernelCore::Impl {
}
}
CloseCurrentProcess();
CloseApplicationProcess();
// Track kernel objects that were not freed on shutdown
{
@@ -194,6 +188,8 @@ struct KernelCore::Impl {
}
}
object_name_global_data.reset();
// Ensure that the object list container is finalized and properly shutdown.
global_object_list_container->Finalize();
global_object_list_container.reset();
@@ -203,8 +199,9 @@ struct KernelCore::Impl {
}
void CloseServices() {
// Ensures all service threads gracefully shutdown.
ClearServiceThreads();
// Ensures all servers gracefully shutdown.
std::scoped_lock lk{server_lock};
server_managers.clear();
}
void InitializePhysicalCores() {
@@ -363,27 +360,29 @@ struct KernelCore::Impl {
}
}
void MakeCurrentProcess(KProcess* process) {
current_process = process;
void InitializeGlobalData(KernelCore& kernel) {
object_name_global_data = std::make_unique<KObjectNameGlobalData>(kernel);
}
static inline thread_local u32 host_thread_id = UINT32_MAX;
void MakeApplicationProcess(KProcess* process) {
application_process = process;
}
/// Gets the host thread ID for the caller, allocating a new one if this is the first time
u32 GetHostThreadId(std::size_t core_id) {
if (host_thread_id == UINT32_MAX) {
// The first four slots are reserved for CPU core threads
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
host_thread_id = static_cast<u32>(core_id);
}
static inline thread_local u8 host_thread_id = UINT8_MAX;
/// Sets the host thread ID for the caller.
u32 SetHostThreadId(std::size_t core_id) {
// This should only be called during core init.
ASSERT(host_thread_id == UINT8_MAX);
// The first four slots are reserved for CPU core threads
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
host_thread_id = static_cast<u8>(core_id);
return host_thread_id;
}
/// Gets the host thread ID for the caller, allocating a new one if this is the first time
u32 GetHostThreadId() {
if (host_thread_id == UINT32_MAX) {
host_thread_id = next_host_thread_id++;
}
/// Gets the host thread ID for the caller
u32 GetHostThreadId() const {
return host_thread_id;
}
@@ -391,23 +390,19 @@ struct KernelCore::Impl {
KThread* GetHostDummyThread(KThread* existing_thread) {
auto initialize = [this](KThread* thread) {
ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess());
thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId()));
thread->SetName(fmt::format("DummyThread:{}", next_host_thread_id++));
return thread;
};
thread_local KThread raw_thread{system.Kernel()};
thread_local KThread* thread = nullptr;
if (thread == nullptr) {
thread = (existing_thread == nullptr) ? initialize(&raw_thread) : existing_thread;
}
thread_local KThread* thread = existing_thread ? existing_thread : initialize(&raw_thread);
return thread;
}
/// Registers a CPU core thread by allocating a host thread ID for it
void RegisterCoreThread(std::size_t core_id) {
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
const auto this_id = GetHostThreadId(core_id);
const auto this_id = SetHostThreadId(core_id);
if (!is_multicore) {
single_core_thread_id = this_id;
}
@@ -415,7 +410,6 @@ struct KernelCore::Impl {
/// Registers a new host thread by allocating a host thread ID for it
void RegisterHostThread(KThread* existing_thread) {
[[maybe_unused]] const auto this_id = GetHostThreadId();
[[maybe_unused]] const auto dummy_thread = GetHostDummyThread(existing_thread);
}
@@ -445,11 +439,9 @@ struct KernelCore::Impl {
static inline thread_local KThread* current_thread{nullptr};
KThread* GetCurrentEmuThread() {
const auto thread_id = GetCurrentHostThreadID();
if (thread_id >= Core::Hardware::NUM_CPU_CORES) {
return GetHostDummyThread(nullptr);
if (!current_thread) {
current_thread = GetHostDummyThread(nullptr);
}
return current_thread;
}
@@ -762,55 +754,6 @@ struct KernelCore::Impl {
"HidBus:SharedMemory");
}
KClientPort* CreateNamedServicePort(std::string name) {
auto search = service_interface_factory.find(name);
if (search == service_interface_factory.end()) {
UNIMPLEMENTED();
return {};
}
return &search->second(system.ServiceManager(), system);
}
void RegisterNamedServiceHandler(std::string name, KServerPort* server_port) {
auto search = service_interface_handlers.find(name);
if (search == service_interface_handlers.end()) {
return;
}
search->second(system.ServiceManager(), server_port);
}
Kernel::ServiceThread& CreateServiceThread(KernelCore& kernel, const std::string& name) {
auto* ptr = new ServiceThread(kernel, name);
service_threads_manager.QueueWork(
[this, ptr]() { service_threads.emplace(ptr, std::unique_ptr<ServiceThread>(ptr)); });
return *ptr;
}
void ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
auto* ptr = &service_thread;
if (ptr == default_service_thread) {
// Nothing to do here, the service is using default_service_thread, which will be
// released on shutdown.
return;
}
service_threads_manager.QueueWork([this, ptr]() { service_threads.erase(ptr); });
}
void ClearServiceThreads() {
service_threads_manager.QueueWork([this] {
service_threads.clear();
default_service_thread = nullptr;
service_thread_barrier.Sync();
});
service_thread_barrier.Sync();
}
std::mutex registered_objects_lock;
std::mutex registered_in_use_objects_lock;
@@ -821,7 +764,7 @@ struct KernelCore::Impl {
// Lists all processes that exist in the current session.
std::vector<KProcess*> process_list;
std::atomic<KProcess*> current_process{};
std::atomic<KProcess*> application_process{};
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
std::unique_ptr<Kernel::KHardwareTimer> hardware_timer;
@@ -838,14 +781,14 @@ struct KernelCore::Impl {
std::unique_ptr<KAutoObjectWithListContainer> global_object_list_container;
/// Map of named ports managed by the kernel, which can be retrieved using
/// the ConnectToPort SVC.
std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
std::unordered_map<std::string, ServiceInterfaceHandlerFn> service_interface_handlers;
NamedPortTable named_ports;
std::unique_ptr<KObjectNameGlobalData> object_name_global_data;
std::unordered_set<KAutoObject*> registered_objects;
std::unordered_set<KAutoObject*> registered_in_use_objects;
std::mutex server_lock;
std::vector<std::unique_ptr<Service::ServerManager>> server_managers;
std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
std::array<std::unique_ptr<Kernel::PhysicalCore>, Core::Hardware::NUM_CPU_CORES> cores;
@@ -880,12 +823,6 @@ struct KernelCore::Impl {
// Memory layout
std::unique_ptr<KMemoryLayout> memory_layout;
// Threads used for services
std::unordered_map<ServiceThread*, std::unique_ptr<ServiceThread>> service_threads;
ServiceThread* default_service_thread{};
Common::ThreadWorker service_threads_manager;
Common::Barrier service_thread_barrier;
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads{};
std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
@@ -941,20 +878,20 @@ void KernelCore::AppendNewProcess(KProcess* process) {
impl->process_list.push_back(process);
}
void KernelCore::MakeCurrentProcess(KProcess* process) {
impl->MakeCurrentProcess(process);
void KernelCore::MakeApplicationProcess(KProcess* process) {
impl->MakeApplicationProcess(process);
}
KProcess* KernelCore::CurrentProcess() {
return impl->current_process;
KProcess* KernelCore::ApplicationProcess() {
return impl->application_process;
}
const KProcess* KernelCore::CurrentProcess() const {
return impl->current_process;
const KProcess* KernelCore::ApplicationProcess() const {
return impl->application_process;
}
void KernelCore::CloseCurrentProcess() {
impl->CloseCurrentProcess();
void KernelCore::CloseApplicationProcess() {
impl->CloseApplicationProcess();
}
const std::vector<KProcess*>& KernelCore::GetProcessList() const {
@@ -1002,7 +939,7 @@ const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const {
}
Kernel::KScheduler* KernelCore::CurrentScheduler() {
u32 core_id = impl->GetCurrentHostThreadID();
const u32 core_id = impl->GetCurrentHostThreadID();
if (core_id >= Core::Hardware::NUM_CPU_CORES) {
// This is expected when called from not a guest thread
return {};
@@ -1049,23 +986,6 @@ void KernelCore::PrepareReschedule(std::size_t id) {
// TODO: Reimplement, this
}
void KernelCore::RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory) {
impl->service_interface_factory.emplace(std::move(name), factory);
}
void KernelCore::RegisterInterfaceForNamedService(std::string name,
ServiceInterfaceHandlerFn&& handler) {
impl->service_interface_handlers.emplace(std::move(name), handler);
}
KClientPort* KernelCore::CreateNamedServicePort(std::string name) {
return impl->CreateNamedServicePort(std::move(name));
}
void KernelCore::RegisterNamedServiceHandler(std::string name, KServerPort* server_port) {
impl->RegisterNamedServiceHandler(std::move(name), server_port);
}
void KernelCore::RegisterKernelObject(KAutoObject* object) {
std::scoped_lock lk{impl->registered_objects_lock};
impl->registered_objects.insert(object);
@@ -1086,8 +1006,19 @@ void KernelCore::UnregisterInUseObject(KAutoObject* object) {
impl->registered_in_use_objects.erase(object);
}
bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const {
return port != impl->named_ports.cend();
void KernelCore::RunServer(std::unique_ptr<Service::ServerManager>&& server_manager) {
auto* manager = server_manager.get();
{
std::scoped_lock lk{impl->server_lock};
if (impl->is_shutting_down) {
return;
}
impl->server_managers.emplace_back(std::move(server_manager));
}
manager->LoopProcess();
}
u32 KernelCore::CreateNewObjectID() {
@@ -1126,6 +1057,87 @@ void KernelCore::RegisterHostThread(KThread* existing_thread) {
}
}
static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process,
std::string&& thread_name, std::function<void()>&& func) {
// Reserve a new thread from the process resource limit.
KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax);
ASSERT(thread_reservation.Succeeded());
// Initialize the thread.
KThread* thread = KThread::Create(kernel);
ASSERT(R_SUCCEEDED(KThread::InitializeDummyThread(thread, process)));
// Commit the thread reservation.
thread_reservation.Commit();
return std::jthread(
[&kernel, thread, thread_name{std::move(thread_name)}, func{std::move(func)}] {
// Set the thread name.
Common::SetCurrentThreadName(thread_name.c_str());
// Register the thread.
kernel.RegisterHostThread(thread);
// Run the callback.
func();
// Close the thread.
// This will free the process if it is the last reference.
thread->Close();
});
}
std::jthread KernelCore::RunOnHostCoreProcess(std::string&& process_name,
std::function<void()> func) {
// Make a new process.
KProcess* process = KProcess::Create(*this);
ASSERT(R_SUCCEEDED(KProcess::Initialize(process, System(), "", KProcess::ProcessType::Userland,
GetSystemResourceLimit())));
// Ensure that we don't hold onto any extra references.
SCOPE_EXIT({ process->Close(); });
// Run the host thread.
return RunHostThreadFunc(*this, process, std::move(process_name), std::move(func));
}
std::jthread KernelCore::RunOnHostCoreThread(std::string&& thread_name,
std::function<void()> func) {
// Get the current process.
KProcess* process = GetCurrentProcessPointer(*this);
// Run the host thread.
return RunHostThreadFunc(*this, process, std::move(thread_name), std::move(func));
}
void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function<void()> func) {
constexpr s32 ServiceThreadPriority = 16;
constexpr s32 ServiceThreadCore = 3;
// Make a new process.
KProcess* process = KProcess::Create(*this);
ASSERT(R_SUCCEEDED(KProcess::Initialize(process, System(), "", KProcess::ProcessType::Userland,
GetSystemResourceLimit())));
// Ensure that we don't hold onto any extra references.
SCOPE_EXIT({ process->Close(); });
// Reserve a new thread from the process resource limit.
KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax);
ASSERT(thread_reservation.Succeeded());
// Initialize the thread.
KThread* thread = KThread::Create(*this);
ASSERT(R_SUCCEEDED(KThread::InitializeServiceThread(
System(), thread, std::move(func), ServiceThreadPriority, ServiceThreadCore, process)));
// Commit the thread reservation.
thread_reservation.Commit();
// Begin running the thread.
ASSERT(R_SUCCEEDED(thread->Run()));
}
u32 KernelCore::GetCurrentHostThreadID() const {
return impl->GetCurrentHostThreadID();
}
@@ -1138,6 +1150,10 @@ void KernelCore::SetCurrentEmuThread(KThread* thread) {
impl->SetCurrentEmuThread(thread);
}
KObjectNameGlobalData& KernelCore::ObjectNameGlobalData() {
return *impl->object_name_global_data;
}
KMemoryManager& KernelCore::MemoryManager() {
return *impl->memory_manager;
}
@@ -1202,12 +1218,12 @@ const Kernel::KSharedMemory& KernelCore::GetHidBusSharedMem() const {
return *impl->hidbus_shared_mem;
}
void KernelCore::Suspend(bool suspended) {
void KernelCore::SuspendApplication(bool suspended) {
const bool should_suspend{exception_exited || suspended};
const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable;
//! This refers to the application process, not the current process.
KScopedAutoObject<KProcess> process = CurrentProcess();
// Get the application process.
KScopedAutoObject<KProcess> process = ApplicationProcess();
if (process.IsNull()) {
return;
}
@@ -1218,8 +1234,8 @@ void KernelCore::Suspend(bool suspended) {
// Wait for process execution to stop.
bool must_wait{should_suspend};
// KernelCore::Suspend must be called from locked context, or we
// could race another call to SetActivity, interfering with waiting.
// KernelCore::SuspendApplication must be called from locked context,
// or we could race another call to SetActivity, interfering with waiting.
while (must_wait) {
KScopedSchedulerLock sl{*this};
@@ -1253,9 +1269,9 @@ bool KernelCore::IsShuttingDown() const {
return impl->IsShuttingDown();
}
void KernelCore::ExceptionalExit() {
void KernelCore::ExceptionalExitApplication() {
exception_exited = true;
Suspend(true);
SuspendApplication(true);
}
void KernelCore::EnterSVCProfile() {
@@ -1266,18 +1282,6 @@ void KernelCore::ExitSVCProfile() {
MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]);
}
Kernel::ServiceThread& KernelCore::CreateServiceThread(const std::string& name) {
return impl->CreateServiceThread(*this, name);
}
Kernel::ServiceThread& KernelCore::GetDefaultServiceThread() const {
return *impl->default_service_thread;
}
void KernelCore::ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
impl->ReleaseServiceThread(service_thread);
}
Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() {
return impl->slab_resource_counts;
}

View File

@@ -9,6 +9,8 @@
#include <string>
#include <unordered_map>
#include <vector>
#include "common/polyfill_thread.h"
#include "core/hardware_properties.h"
#include "core/hle/kernel/k_auto_object.h"
#include "core/hle/kernel/k_slab_heap.h"
@@ -24,6 +26,10 @@ class CoreTiming;
struct EventType;
} // namespace Core::Timing
namespace Service {
class ServerManager;
}
namespace Service::SM {
class ServiceManager;
}
@@ -44,6 +50,8 @@ class KHardwareTimer;
class KLinkedListNode;
class KMemoryLayout;
class KMemoryManager;
class KObjectName;
class KObjectNameGlobalData;
class KPageBuffer;
class KPageBufferSlabHeap;
class KPort;
@@ -63,13 +71,6 @@ class KTransferMemory;
class KWorkerTaskManager;
class KCodeMemory;
class PhysicalCore;
class ServiceThread;
class Synchronization;
using ServiceInterfaceFactory =
std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>;
using ServiceInterfaceHandlerFn = std::function<void(Service::SM::ServiceManager&, KServerPort*)>;
namespace Init {
struct KSlabResourceCounts;
@@ -78,15 +79,8 @@ struct KSlabResourceCounts;
template <typename T>
class KSlabHeap;
using EmuThreadHandle = uintptr_t;
constexpr EmuThreadHandle EmuThreadHandleInvalid{};
constexpr EmuThreadHandle EmuThreadHandleReserved{1ULL << 63};
/// Represents a single instance of the kernel.
class KernelCore {
private:
using NamedPortTable = std::unordered_map<std::string, KClientPort*>;
public:
/// Constructs an instance of the kernel using the given System
/// instance as a context for any necessary system-related state,
@@ -131,17 +125,17 @@ public:
/// Adds the given shared pointer to an internal list of active processes.
void AppendNewProcess(KProcess* process);
/// Makes the given process the new current process.
void MakeCurrentProcess(KProcess* process);
/// Makes the given process the new application process.
void MakeApplicationProcess(KProcess* process);
/// Retrieves a pointer to the current process.
KProcess* CurrentProcess();
/// Retrieves a pointer to the application process.
KProcess* ApplicationProcess();
/// Retrieves a const pointer to the current process.
const KProcess* CurrentProcess() const;
/// Retrieves a const pointer to the application process.
const KProcess* ApplicationProcess() const;
/// Closes the current process.
void CloseCurrentProcess();
/// Closes the application process.
void CloseApplicationProcess();
/// Retrieves the list of processes.
const std::vector<KProcess*>& GetProcessList() const;
@@ -194,18 +188,6 @@ public:
void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
/// Registers a named HLE service, passing a factory used to open a port to that service.
void RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory);
/// Registers a setup function for the named HLE service.
void RegisterInterfaceForNamedService(std::string name, ServiceInterfaceHandlerFn&& handler);
/// Opens a port to a service previously registered with RegisterNamedService.
KClientPort* CreateNamedServicePort(std::string name);
/// Accepts a session on a port created by CreateNamedServicePort.
void RegisterNamedServiceHandler(std::string name, KServerPort* server_port);
/// Registers all kernel objects with the global emulation state, this is purely for tracking
/// leaks after emulation has been shutdown.
void RegisterKernelObject(KAutoObject* object);
@@ -222,8 +204,8 @@ public:
/// destroyed during the current emulation session.
void UnregisterInUseObject(KAutoObject* object);
/// Determines whether or not the given port is a valid named port.
bool IsValidNamedPort(NamedPortTable::const_iterator port) const;
// Runs the given server manager until shutdown.
void RunServer(std::unique_ptr<Service::ServerManager>&& server_manager);
/// Gets the current host_thread/guest_thread pointer.
KThread* GetCurrentEmuThread() const;
@@ -240,6 +222,15 @@ public:
/// Register the current thread as a non CPU core thread.
void RegisterHostThread(KThread* existing_thread = nullptr);
void RunOnGuestCoreProcess(std::string&& process_name, std::function<void()> func);
std::jthread RunOnHostCoreProcess(std::string&& process_name, std::function<void()> func);
std::jthread RunOnHostCoreThread(std::string&& thread_name, std::function<void()> func);
/// Gets global data for KObjectName.
KObjectNameGlobalData& ObjectNameGlobalData();
/// Gets the virtual memory manager for the kernel.
KMemoryManager& MemoryManager();
@@ -288,11 +279,11 @@ public:
/// Gets the shared memory object for HIDBus services.
const Kernel::KSharedMemory& GetHidBusSharedMem() const;
/// Suspend/unsuspend all processes.
void Suspend(bool suspend);
/// Suspend/unsuspend application process.
void SuspendApplication(bool suspend);
/// Exceptional exit all processes.
void ExceptionalExit();
/// Exceptional exit application process.
void ExceptionalExitApplication();
/// Notify emulated CPU cores to shut down.
void ShutdownCores();
@@ -305,33 +296,6 @@ public:
void ExitSVCProfile();
/**
* Creates a host thread to execute HLE service requests, which are used to execute service
* routines asynchronously. While these are allocated per ServerSession, these need to be owned
* and managed outside of ServerSession to avoid a circular dependency. In general, most
* services can just use the default service thread, and not need their own host service thread.
* See GetDefaultServiceThread.
* @param name String name for the ServerSession creating this thread, used for debug
* purposes.
* @returns A reference to the newly created service thread.
*/
Kernel::ServiceThread& CreateServiceThread(const std::string& name);
/**
* Gets the default host service thread, which executes HLE service requests. Unless service
* requests need to block on the host, the default service thread should be used in favor of
* creating a new service thread.
* @returns A reference to the default service thread.
*/
Kernel::ServiceThread& GetDefaultServiceThread() const;
/**
* Releases a HLE service thread, instructing KernelCore to free it. This should be called when
* the ServerSession associated with the thread is destroyed.
* @param service_thread Service thread to release.
*/
void ReleaseServiceThread(Kernel::ServiceThread& service_thread);
/// Workaround for single-core mode when preempting threads while idle.
bool IsPhantomModeForSingleCore() const;
void SetIsPhantomModeForSingleCore(bool value);
@@ -372,6 +336,8 @@ public:
return slab_heap_container->page_buffer;
} else if constexpr (std::is_same_v<T, KThreadLocalPage>) {
return slab_heap_container->thread_local_page;
} else if constexpr (std::is_same_v<T, KObjectName>) {
return slab_heap_container->object_name;
} else if constexpr (std::is_same_v<T, KSessionRequest>) {
return slab_heap_container->session_request;
} else if constexpr (std::is_same_v<T, KSecureSystemResource>) {
@@ -443,6 +409,7 @@ private:
KSlabHeap<KDeviceAddressSpace> device_address_space;
KSlabHeap<KPageBuffer> page_buffer;
KSlabHeap<KThreadLocalPage> thread_local_page;
KSlabHeap<KObjectName> object_name;
KSlabHeap<KSessionRequest> session_request;
KSlabHeap<KSecureSystemResource> secure_system_resource;
KSlabHeap<KEventInfo> event_info;

View File

@@ -1,206 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <functional>
#include <map>
#include <mutex>
#include <thread>
#include <vector>
#include "common/polyfill_thread.h"
#include "common/scope_exit.h"
#include "common/thread.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_scoped_resource_reservation.h"
#include "core/hle/kernel/k_session.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/service_thread.h"
namespace Kernel {
class ServiceThread::Impl final {
public:
explicit Impl(KernelCore& kernel, const std::string& service_name);
~Impl();
void WaitAndProcessImpl();
void SessionClosed(KServerSession* server_session,
std::shared_ptr<SessionRequestManager> manager);
void LoopProcess();
void RegisterServerSession(KServerSession* session,
std::shared_ptr<SessionRequestManager> manager);
private:
KernelCore& kernel;
const std::string m_service_name;
std::jthread m_host_thread{};
std::mutex m_session_mutex{};
std::map<KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions{};
KEvent* m_wakeup_event{};
KThread* m_thread{};
std::atomic<bool> m_shutdown_requested{};
};
void ServiceThread::Impl::WaitAndProcessImpl() {
// Create local list of waitable sessions.
std::vector<KSynchronizationObject*> objs;
std::vector<std::shared_ptr<SessionRequestManager>> managers;
{
// Lock to get the set.
std::scoped_lock lk{m_session_mutex};
// Reserve the needed quantity.
objs.reserve(m_sessions.size() + 1);
managers.reserve(m_sessions.size());
// Copy to our local list.
for (const auto& [session, manager] : m_sessions) {
objs.push_back(session);
managers.push_back(manager);
}
// Insert the wakeup event at the end.
objs.push_back(&m_wakeup_event->GetReadableEvent());
}
// Wait on the list of sessions.
s32 index{-1};
Result rc = KSynchronizationObject::Wait(kernel, &index, objs.data(),
static_cast<s32>(objs.size()), -1);
ASSERT(!rc.IsFailure());
// If this was the wakeup event, clear it and finish.
if (index >= static_cast<s64>(objs.size() - 1)) {
m_wakeup_event->Clear();
return;
}
// This event is from a server session.
auto* server_session = static_cast<KServerSession*>(objs[index]);
auto& manager = managers[index];
// Fetch the HLE request context.
std::shared_ptr<HLERequestContext> context;
rc = server_session->ReceiveRequest(&context, manager);
// If the session was closed, handle that.
if (rc == ResultSessionClosed) {
SessionClosed(server_session, manager);
// Finish.
return;
}
// TODO: handle other cases
ASSERT(rc == ResultSuccess);
// Perform the request.
Result service_rc = manager->CompleteSyncRequest(server_session, *context);
// Reply to the client.
rc = server_session->SendReplyHLE();
if (rc == ResultSessionClosed || service_rc == IPC::ERR_REMOTE_PROCESS_DEAD) {
SessionClosed(server_session, manager);
return;
}
// TODO: handle other cases
ASSERT(rc == ResultSuccess);
ASSERT(service_rc == ResultSuccess);
}
void ServiceThread::Impl::SessionClosed(KServerSession* server_session,
std::shared_ptr<SessionRequestManager> manager) {
{
// Lock to get the set.
std::scoped_lock lk{m_session_mutex};
// Erase the session.
ASSERT(m_sessions.erase(server_session) == 1);
}
// Close our reference to the server session.
server_session->Close();
}
void ServiceThread::Impl::LoopProcess() {
Common::SetCurrentThreadName(m_service_name.c_str());
kernel.RegisterHostThread(m_thread);
while (!m_shutdown_requested.load()) {
WaitAndProcessImpl();
}
}
void ServiceThread::Impl::RegisterServerSession(KServerSession* server_session,
std::shared_ptr<SessionRequestManager> manager) {
// Open the server session.
server_session->Open();
{
// Lock to get the set.
std::scoped_lock lk{m_session_mutex};
// Insert the session and manager.
m_sessions[server_session] = manager;
}
// Signal the wakeup event.
m_wakeup_event->Signal();
}
ServiceThread::Impl::~Impl() {
// Shut down the processing thread.
m_shutdown_requested.store(true);
m_wakeup_event->Signal();
m_host_thread.join();
// Close all remaining sessions.
for (const auto& [server_session, manager] : m_sessions) {
server_session->Close();
}
// Destroy remaining managers.
m_sessions.clear();
// Close event.
m_wakeup_event->GetReadableEvent().Close();
m_wakeup_event->Close();
// Close thread.
m_thread->Close();
}
ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name)
: kernel{kernel_}, m_service_name{service_name} {
// Initialize event.
m_wakeup_event = KEvent::Create(kernel);
m_wakeup_event->Initialize(nullptr);
// Initialize thread.
m_thread = KThread::Create(kernel);
ASSERT(KThread::InitializeDummyThread(m_thread, nullptr).IsSuccess());
// Start thread.
m_host_thread = std::jthread([this] { LoopProcess(); });
}
ServiceThread::ServiceThread(KernelCore& kernel, const std::string& name)
: impl{std::make_unique<Impl>(kernel, name)} {}
ServiceThread::~ServiceThread() = default;
void ServiceThread::RegisterServerSession(KServerSession* session,
std::shared_ptr<SessionRequestManager> manager) {
impl->RegisterServerSession(session, manager);
}
} // namespace Kernel

View File

@@ -1,29 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include <string>
namespace Kernel {
class HLERequestContext;
class KernelCore;
class KSession;
class SessionRequestManager;
class ServiceThread final {
public:
explicit ServiceThread(KernelCore& kernel, const std::string& name);
~ServiceThread();
void RegisterServerSession(KServerSession* session,
std::shared_ptr<SessionRequestManager> manager);
private:
class Impl;
std::unique_ptr<Impl> impl;
};
} // namespace Kernel

View File

@@ -4426,7 +4426,7 @@ void Call(Core::System& system, u32 imm) {
auto& kernel = system.Kernel();
kernel.EnterSVCProfile();
if (system.CurrentProcess()->Is64BitProcess()) {
if (GetCurrentProcess(system.Kernel()).Is64BitProcess()) {
Call64(system, imm);
} else {
Call32(system, imm);

View File

@@ -16,18 +16,19 @@ Result SetThreadActivity(Core::System& system, Handle thread_handle,
thread_activity);
// Validate the activity.
constexpr auto IsValidThreadActivity = [](ThreadActivity activity) {
static constexpr auto IsValidThreadActivity = [](ThreadActivity activity) {
return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused;
};
R_UNLESS(IsValidThreadActivity(thread_activity), ResultInvalidEnumValue);
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Check that the activity is being set on a non-current thread for the current process.
R_UNLESS(thread->GetOwnerProcess() == system.Kernel().CurrentProcess(), ResultInvalidHandle);
R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(system.Kernel()),
ResultInvalidHandle);
R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(system.Kernel()), ResultBusy);
// Set the activity.

View File

@@ -72,7 +72,7 @@ Result WaitForAddress(Core::System& system, VAddr address, ArbitrationType arb_t
timeout = timeout_ns;
}
return system.Kernel().CurrentProcess()->WaitAddressArbiter(address, arb_type, value, timeout);
return GetCurrentProcess(system.Kernel()).WaitAddressArbiter(address, arb_type, value, timeout);
}
// Signals to an address (via Address Arbiter)
@@ -95,8 +95,8 @@ Result SignalToAddress(Core::System& system, VAddr address, SignalType signal_ty
return ResultInvalidEnumValue;
}
return system.Kernel().CurrentProcess()->SignalAddressArbiter(address, signal_type, value,
count);
return GetCurrentProcess(system.Kernel())
.SignalAddressArbiter(address, signal_type, value, count);
}
Result WaitForAddress64(Core::System& system, VAddr address, ArbitrationType arb_type, s32 value,

View File

@@ -38,7 +38,7 @@ Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 ad
// Get the process from its handle.
KScopedAutoObject process =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Verify the region is within range.

View File

@@ -46,7 +46,7 @@ Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t
R_UNLESS(code_mem != nullptr, ResultOutOfResource);
// Verify that the region is in range.
R_UNLESS(system.CurrentProcess()->PageTable().Contains(address, size),
R_UNLESS(GetCurrentProcess(system.Kernel()).PageTable().Contains(address, size),
ResultInvalidCurrentMemory);
// Initialize the code memory.
@@ -56,7 +56,7 @@ Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t
KCodeMemory::Register(kernel, code_mem);
// Add the code memory to the handle table.
R_TRY(system.CurrentProcess()->GetHandleTable().Add(out, code_mem));
R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(out, code_mem));
code_mem->Close();
@@ -79,8 +79,9 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
// Get the code memory from its handle.
KScopedAutoObject code_mem =
system.CurrentProcess()->GetHandleTable().GetObject<KCodeMemory>(code_memory_handle);
KScopedAutoObject code_mem = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KCodeMemory>(code_memory_handle);
R_UNLESS(code_mem.IsNotNull(), ResultInvalidHandle);
// NOTE: Here, Atmosphere extends the SVC to allow code memory operations on one's own process.
@@ -90,9 +91,10 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
switch (operation) {
case CodeMemoryOperation::Map: {
// Check that the region is in range.
R_UNLESS(
system.CurrentProcess()->PageTable().CanContain(address, size, KMemoryState::CodeOut),
ResultInvalidMemoryRegion);
R_UNLESS(GetCurrentProcess(system.Kernel())
.PageTable()
.CanContain(address, size, KMemoryState::CodeOut),
ResultInvalidMemoryRegion);
// Check the memory permission.
R_UNLESS(IsValidMapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission);
@@ -102,9 +104,10 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
} break;
case CodeMemoryOperation::Unmap: {
// Check that the region is in range.
R_UNLESS(
system.CurrentProcess()->PageTable().CanContain(address, size, KMemoryState::CodeOut),
ResultInvalidMemoryRegion);
R_UNLESS(GetCurrentProcess(system.Kernel())
.PageTable()
.CanContain(address, size, KMemoryState::CodeOut),
ResultInvalidMemoryRegion);
// Check the memory permission.
R_UNLESS(IsValidUnmapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission);

View File

@@ -43,8 +43,8 @@ Result WaitProcessWideKeyAtomic(Core::System& system, VAddr address, VAddr cv_ke
}
// Wait on the condition variable.
return system.Kernel().CurrentProcess()->WaitConditionVariable(
address, Common::AlignDown(cv_key, sizeof(u32)), tag, timeout);
return GetCurrentProcess(system.Kernel())
.WaitConditionVariable(address, Common::AlignDown(cv_key, sizeof(u32)), tag, timeout);
}
/// Signal process wide key
@@ -52,8 +52,8 @@ void SignalProcessWideKey(Core::System& system, VAddr cv_key, s32 count) {
LOG_TRACE(Kernel_SVC, "called, cv_key=0x{:X}, count=0x{:08X}", cv_key, count);
// Signal the condition variable.
return system.Kernel().CurrentProcess()->SignalConditionVariable(
Common::AlignDown(cv_key, sizeof(u32)), count);
return GetCurrentProcess(system.Kernel())
.SignalConditionVariable(Common::AlignDown(cv_key, sizeof(u32)), count);
}
Result WaitProcessWideKeyAtomic64(Core::System& system, uint64_t address, uint64_t cv_key,

View File

@@ -37,15 +37,16 @@ Result CreateDeviceAddressSpace(Core::System& system, Handle* out, uint64_t das_
KDeviceAddressSpace::Register(system.Kernel(), das);
// Add to the handle table.
R_TRY(system.CurrentProcess()->GetHandleTable().Add(out, das));
R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(out, das));
R_SUCCEED();
}
Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle) {
// Get the device address space.
KScopedAutoObject das =
system.CurrentProcess()->GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
KScopedAutoObject das = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Attach.
@@ -54,8 +55,9 @@ Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Ha
Result DetachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle) {
// Get the device address space.
KScopedAutoObject das =
system.CurrentProcess()->GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
KScopedAutoObject das = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Detach.
@@ -94,13 +96,14 @@ Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Han
R_UNLESS(reserved == 0, ResultInvalidEnumValue);
// Get the device address space.
KScopedAutoObject das =
system.CurrentProcess()->GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
KScopedAutoObject das = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Get the process.
KScopedAutoObject process =
system.CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Validate that the process address is within range.
@@ -134,13 +137,14 @@ Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Han
R_UNLESS(reserved == 0, ResultInvalidEnumValue);
// Get the device address space.
KScopedAutoObject das =
system.CurrentProcess()->GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
KScopedAutoObject das = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Get the process.
KScopedAutoObject process =
system.CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Validate that the process address is within range.
@@ -165,13 +169,14 @@ Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle p
ResultInvalidCurrentMemory);
// Get the device address space.
KScopedAutoObject das =
system.CurrentProcess()->GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
KScopedAutoObject das = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Get the process.
KScopedAutoObject process =
system.CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Validate that the process address is within range.

View File

@@ -15,7 +15,7 @@ Result SignalEvent(Core::System& system, Handle event_handle) {
LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
// Get the current handle table.
const KHandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const KHandleTable& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Get the event.
KScopedAutoObject event = handle_table.GetObject<KEvent>(event_handle);
@@ -28,7 +28,7 @@ Result ClearEvent(Core::System& system, Handle event_handle) {
LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
// Get the current handle table.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Try to clear the writable event.
{
@@ -56,10 +56,10 @@ Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
// Get the kernel reference and handle table.
auto& kernel = system.Kernel();
auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
// Reserve a new event from the process resource limit
KScopedResourceReservation event_reservation(kernel.CurrentProcess(),
KScopedResourceReservation event_reservation(GetCurrentProcessPointer(kernel),
LimitableResource::EventCountMax);
R_UNLESS(event_reservation.Succeeded(), ResultLimitReached);
@@ -68,7 +68,7 @@ Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
R_UNLESS(event != nullptr, ResultOutOfResource);
// Initialize the event.
event->Initialize(kernel.CurrentProcess());
event->Initialize(GetCurrentProcessPointer(kernel));
// Commit the thread reservation.
event_reservation.Commit();

View File

@@ -44,7 +44,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
return ResultInvalidEnumValue;
}
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(handle);
if (process.IsNull()) {
LOG_ERROR(Kernel_SVC, "Process is not valid! info_id={}, info_sub_id={}, handle={:08X}",
@@ -126,6 +126,11 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
*result = process->GetTotalPhysicalMemoryUsedWithoutSystemResource();
return ResultSuccess;
case InfoType::IsApplication:
LOG_WARNING(Kernel_SVC, "(STUBBED) Assuming process is application");
*result = true;
return ResultSuccess;
case InfoType::FreeThreadCount:
*result = process->GetFreeThreadCount();
return ResultSuccess;
@@ -154,7 +159,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
return ResultInvalidCombination;
}
KProcess* const current_process = system.Kernel().CurrentProcess();
KProcess* const current_process = GetCurrentProcessPointer(system.Kernel());
KHandleTable& handle_table = current_process->GetHandleTable();
const auto resource_limit = current_process->GetResourceLimit();
if (!resource_limit) {
@@ -183,7 +188,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
return ResultInvalidCombination;
}
*result = system.Kernel().CurrentProcess()->GetRandomEntropy(info_sub_id);
*result = GetCurrentProcess(system.Kernel()).GetRandomEntropy(info_sub_id);
return ResultSuccess;
case InfoType::InitialProcessIdRange:
@@ -200,9 +205,9 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
return ResultInvalidCombination;
}
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(
static_cast<Handle>(handle));
KScopedAutoObject thread = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KThread>(static_cast<Handle>(handle));
if (thread.IsNull()) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}",
static_cast<Handle>(handle));
@@ -249,7 +254,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
R_UNLESS(info_sub_id == 0, ResultInvalidCombination);
// Get the handle table.
KProcess* current_process = system.Kernel().CurrentProcess();
KProcess* current_process = GetCurrentProcessPointer(system.Kernel());
KHandleTable& handle_table = current_process->GetHandleTable();
// Get a new handle for the current process.

View File

@@ -12,11 +12,9 @@ namespace Kernel::Svc {
/// Makes a blocking IPC call to a service.
Result SendSyncRequest(Core::System& system, Handle handle) {
auto& kernel = system.Kernel();
// Get the client session from its handle.
KScopedAutoObject session =
kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KClientSession>(handle);
R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
@@ -40,7 +38,7 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha
Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles,
Handle reply_target, s64 timeout_ns) {
auto& kernel = system.Kernel();
auto& handle_table = GetCurrentThread(kernel).GetOwnerProcess()->GetHandleTable();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
R_UNLESS(system.Memory().IsValidVirtualAddressRange(

View File

@@ -24,7 +24,7 @@ Result ArbitrateLock(Core::System& system, Handle thread_handle, VAddr address,
return ResultInvalidAddress;
}
return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag);
return GetCurrentProcess(system.Kernel()).WaitForAddress(thread_handle, address, tag);
}
/// Unlock a mutex
@@ -43,7 +43,7 @@ Result ArbitrateUnlock(Core::System& system, VAddr address) {
return ResultInvalidAddress;
}
return system.Kernel().CurrentProcess()->SignalToAddress(address);
return GetCurrentProcess(system.Kernel()).SignalToAddress(address);
}
Result ArbitrateLock64(Core::System& system, Handle thread_handle, uint64_t address, uint32_t tag) {

View File

@@ -113,7 +113,7 @@ Result SetMemoryPermission(Core::System& system, VAddr address, u64 size, Memory
R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission);
// Validate that the region is in range for the current process.
auto& page_table = system.Kernel().CurrentProcess()->PageTable();
auto& page_table = GetCurrentProcess(system.Kernel()).PageTable();
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
// Set the memory attribute.
@@ -137,7 +137,7 @@ Result SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mas
R_UNLESS((mask | attr | SupportedMask) == SupportedMask, ResultInvalidCombination);
// Validate that the region is in range for the current process.
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()};
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
// Set the memory attribute.
@@ -149,7 +149,7 @@ Result MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size)
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size);
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()};
if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
result.IsError()) {
@@ -164,7 +164,7 @@ Result UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 siz
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size);
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()};
if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
result.IsError()) {

View File

@@ -16,7 +16,7 @@ Result SetHeapSize(Core::System& system, VAddr* out_address, u64 size) {
R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize);
// Set the heap size.
R_TRY(system.Kernel().CurrentProcess()->PageTable().SetHeapSize(out_address, size));
R_TRY(GetCurrentProcess(system.Kernel()).PageTable().SetHeapSize(out_address, size));
return ResultSuccess;
}
@@ -45,7 +45,7 @@ Result MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
return ResultInvalidMemoryRegion;
}
KProcess* const current_process{system.Kernel().CurrentProcess()};
KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
auto& page_table{current_process->PageTable()};
if (current_process->GetSystemResourceSize() == 0) {
@@ -94,7 +94,7 @@ Result UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
return ResultInvalidMemoryRegion;
}
KProcess* const current_process{system.Kernel().CurrentProcess()};
KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
auto& page_table{current_process->PageTable()};
if (current_process->GetSystemResourceSize() == 0) {

View File

@@ -5,62 +5,47 @@
#include "core/core.h"
#include "core/hle/kernel/k_client_port.h"
#include "core/hle/kernel/k_client_session.h"
#include "core/hle/kernel/k_object_name.h"
#include "core/hle/kernel/k_port.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
namespace Kernel::Svc {
/// Connect to an OS service given the port name, returns the handle to the port to out
Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) {
auto& memory = system.Memory();
if (!memory.IsValidVirtualAddress(port_name_address)) {
LOG_ERROR(Kernel_SVC,
"Port Name Address is not a valid virtual address, port_name_address=0x{:016X}",
port_name_address);
return ResultNotFound;
}
Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr user_name) {
// Copy the provided name from user memory to kernel memory.
auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax);
static constexpr std::size_t PortNameMaxLength = 11;
// Read 1 char beyond the max allowed port name to detect names that are too long.
const std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1);
if (port_name.size() > PortNameMaxLength) {
LOG_ERROR(Kernel_SVC, "Port name is too long, expected {} but got {}", PortNameMaxLength,
port_name.size());
return ResultOutOfRange;
}
std::array<char, KObjectName::NameLengthMax> name{};
std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
LOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
// Validate that the name is valid.
R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange);
// Get the current handle table.
auto& kernel = system.Kernel();
auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Find the client port.
auto port = kernel.CreateNamedServicePort(port_name);
if (!port) {
LOG_ERROR(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
return ResultNotFound;
}
auto port = KObjectName::Find<KClientPort>(system.Kernel(), name.data());
R_UNLESS(port.IsNotNull(), ResultNotFound);
// Reserve a handle for the port.
// NOTE: Nintendo really does write directly to the output handle here.
R_TRY(handle_table.Reserve(out));
auto handle_guard = SCOPE_GUARD({ handle_table.Unreserve(*out); });
ON_RESULT_FAILURE {
handle_table.Unreserve(*out);
};
// Create a session.
KClientSession* session{};
KClientSession* session;
R_TRY(port->CreateSession(std::addressof(session)));
kernel.RegisterNamedServiceHandler(port_name, &port->GetParent()->GetServerPort());
// Register the session in the table, close the extra reference.
handle_table.Register(*out, session);
session->Close();
// We succeeded.
handle_guard.Cancel();
return ResultSuccess;
R_SUCCEED();
}
Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,
@@ -74,10 +59,60 @@ Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) {
R_THROW(ResultNotImplemented);
}
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t name,
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name,
int32_t max_sessions) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
// Copy the provided name from user memory to kernel memory.
auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax);
// Copy the provided name from user memory to kernel memory.
std::array<char, KObjectName::NameLengthMax> name{};
std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
// Validate that sessions and name are valid.
R_UNLESS(max_sessions >= 0, ResultOutOfRange);
R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange);
if (max_sessions > 0) {
// Get the current handle table.
auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Create a new port.
KPort* port = KPort::Create(system.Kernel());
R_UNLESS(port != nullptr, ResultOutOfResource);
// Initialize the new port.
port->Initialize(max_sessions, false, "");
// Register the port.
KPort::Register(system.Kernel(), port);
// Ensure that our only reference to the port is in the handle table when we're done.
SCOPE_EXIT({
port->GetClientPort().Close();
port->GetServerPort().Close();
});
// Register the handle in the table.
R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort())));
ON_RESULT_FAILURE {
handle_table.Remove(*out_server_handle);
};
// Create a new object name.
R_TRY(KObjectName::NewFromName(system.Kernel(), std::addressof(port->GetClientPort()),
name.data()));
} else /* if (max_sessions == 0) */ {
// Ensure that this else case is correct.
ASSERT(max_sessions == 0);
// If we're closing, there's no server handle.
*out_server_handle = InvalidHandle;
// Delete the object.
R_TRY(KObjectName::Delete<KClientPort>(system.Kernel(), name.data()));
}
R_SUCCEED();
}
Result ConnectToNamedPort64(Core::System& system, Handle* out_handle, uint64_t name) {

View File

@@ -9,7 +9,7 @@ namespace Kernel::Svc {
/// Exits the current process
void ExitProcess(Core::System& system) {
auto* current_process = system.Kernel().CurrentProcess();
auto* current_process = GetCurrentProcessPointer(system.Kernel());
LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID());
ASSERT_MSG(current_process->GetState() == KProcess::State::Running,
@@ -23,9 +23,9 @@ Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle);
// Get the object from the handle table.
KScopedAutoObject obj =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KAutoObject>(
static_cast<Handle>(handle));
KScopedAutoObject obj = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KAutoObject>(static_cast<Handle>(handle));
R_UNLESS(obj.IsNotNull(), ResultInvalidHandle);
// Get the process from the object.
@@ -63,10 +63,10 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, VAddr out_pr
return ResultOutOfRange;
}
const auto& kernel = system.Kernel();
auto& kernel = system.Kernel();
const auto total_copy_size = out_process_ids_size * sizeof(u64);
if (out_process_ids_size > 0 && !kernel.CurrentProcess()->PageTable().IsInsideAddressSpace(
if (out_process_ids_size > 0 && !GetCurrentProcess(kernel).PageTable().IsInsideAddressSpace(
out_process_ids, total_copy_size)) {
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
out_process_ids, out_process_ids + total_copy_size);
@@ -92,7 +92,7 @@ Result GetProcessInfo(Core::System& system, s64* out, Handle process_handle,
ProcessInfoType info_type) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, info_type);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
if (process.IsNull()) {
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",

View File

@@ -45,7 +45,7 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, V
// Get the process from its handle.
KScopedAutoObject process =
system.CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Validate that the address is in range.
@@ -71,7 +71,7 @@ Result MapProcessMemory(Core::System& system, VAddr dst_address, Handle process_
R_UNLESS((src_address < src_address + size), ResultInvalidCurrentMemory);
// Get the processes.
KProcess* dst_process = system.CurrentProcess();
KProcess* dst_process = GetCurrentProcessPointer(system.Kernel());
KScopedAutoObject src_process =
dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(process_handle);
R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
@@ -114,7 +114,7 @@ Result UnmapProcessMemory(Core::System& system, VAddr dst_address, Handle proces
R_UNLESS((src_address < src_address + size), ResultInvalidCurrentMemory);
// Get the processes.
KProcess* dst_process = system.CurrentProcess();
KProcess* dst_process = GetCurrentProcessPointer(system.Kernel());
KScopedAutoObject src_process =
dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(process_handle);
R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
@@ -174,7 +174,7 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst
return ResultInvalidCurrentMemory;
}
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
if (process.IsNull()) {
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
@@ -242,7 +242,7 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d
return ResultInvalidCurrentMemory;
}
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
if (process.IsNull()) {
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",

View File

@@ -22,7 +22,7 @@ Result QueryMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out
Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
Handle process_handle, uint64_t address) {
LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
if (process.IsNull()) {
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",

View File

@@ -27,7 +27,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) {
KResourceLimit::Register(kernel, resource_limit);
// Add the limit to the handle table.
R_TRY(kernel.CurrentProcess()->GetHandleTable().Add(out_handle, resource_limit));
R_TRY(GetCurrentProcess(kernel).GetHandleTable().Add(out_handle, resource_limit));
return ResultSuccess;
}
@@ -41,9 +41,9 @@ Result GetResourceLimitLimitValue(Core::System& system, s64* out_limit_value,
R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue);
// Get the resource limit.
auto& kernel = system.Kernel();
KScopedAutoObject resource_limit =
kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle);
KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KResourceLimit>(resource_limit_handle);
R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle);
// Get the limit value.
@@ -61,9 +61,9 @@ Result GetResourceLimitCurrentValue(Core::System& system, s64* out_current_value
R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue);
// Get the resource limit.
auto& kernel = system.Kernel();
KScopedAutoObject resource_limit =
kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle);
KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KResourceLimit>(resource_limit_handle);
R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle);
// Get the current value.
@@ -81,9 +81,9 @@ Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_ha
R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue);
// Get the resource limit.
auto& kernel = system.Kernel();
KScopedAutoObject resource_limit =
kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle);
KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KResourceLimit>(resource_limit_handle);
R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle);
// Set the limit value.

View File

@@ -13,7 +13,7 @@ namespace {
template <typename T>
Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, u64 name) {
auto& process = *system.CurrentProcess();
auto& process = GetCurrentProcess(system.Kernel());
auto& handle_table = process.GetHandleTable();
// Declare the session we're going to allocate.

View File

@@ -42,7 +42,7 @@ Result MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address,
R_UNLESS(IsValidSharedMemoryPermission(map_perm), ResultInvalidNewMemoryPermission);
// Get the current process.
auto& process = *system.Kernel().CurrentProcess();
auto& process = GetCurrentProcess(system.Kernel());
auto& page_table = process.PageTable();
// Get the shared memory.
@@ -75,7 +75,7 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr addres
R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
// Get the current process.
auto& process = *system.Kernel().CurrentProcess();
auto& process = GetCurrentProcess(system.Kernel());
auto& page_table = process.PageTable();
// Get the shared memory.

View File

@@ -14,7 +14,7 @@ Result CloseHandle(Core::System& system, Handle handle) {
LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
// Remove the handle.
R_UNLESS(system.Kernel().CurrentProcess()->GetHandleTable().Remove(handle),
R_UNLESS(GetCurrentProcess(system.Kernel()).GetHandleTable().Remove(handle),
ResultInvalidHandle);
return ResultSuccess;
@@ -25,7 +25,7 @@ Result ResetSignal(Core::System& system, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
// Get the current handle table.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Try to reset as readable event.
{
@@ -59,7 +59,7 @@ Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_addre
auto& kernel = system.Kernel();
std::vector<KSynchronizationObject*> objs(num_handles);
const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
Handle* handles = system.Memory().GetPointer<Handle>(handles_address);
// Copy user handles.
@@ -91,7 +91,7 @@ Result CancelSynchronization(Core::System& system, Handle handle) {
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Cancel the thread's wait.
@@ -106,7 +106,7 @@ void SynchronizePreemptionState(Core::System& system) {
KScopedSchedulerLock sl{kernel};
// If the current thread is pinned, unpin it.
KProcess* cur_process = system.Kernel().CurrentProcess();
KProcess* cur_process = GetCurrentProcessPointer(kernel);
const auto core_id = GetCurrentCoreId(kernel);
if (cur_process->GetPinnedThread(core_id) == GetCurrentThreadPointer(kernel)) {

View File

@@ -28,7 +28,7 @@ Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point,
// Adjust core id, if it's the default magic.
auto& kernel = system.Kernel();
auto& process = *kernel.CurrentProcess();
auto& process = GetCurrentProcess(kernel);
if (core_id == IdealCoreUseProcessValue) {
core_id = process.GetIdealCoreId();
}
@@ -53,9 +53,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point,
}
// Reserve a new thread from the process resource limit (waiting up to 100ms).
KScopedResourceReservation thread_reservation(
kernel.CurrentProcess(), LimitableResource::ThreadCountMax, 1,
system.CoreTiming().GetGlobalTimeNs().count() + 100000000);
KScopedResourceReservation thread_reservation(&process, LimitableResource::ThreadCountMax, 1,
system.CoreTiming().GetGlobalTimeNs().count() +
100000000);
if (!thread_reservation.Succeeded()) {
LOG_ERROR(Kernel_SVC, "Could not reserve a new thread");
return ResultLimitReached;
@@ -97,7 +97,7 @@ Result StartThread(Core::System& system, Handle thread_handle) {
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Try to start the thread.
@@ -156,11 +156,11 @@ Result GetThreadContext3(Core::System& system, VAddr out_context, Handle thread_
// Get the thread from its handle.
KScopedAutoObject thread =
kernel.CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
GetCurrentProcess(kernel).GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Require the handle be to a non-current thread in the current process.
const auto* current_process = kernel.CurrentProcess();
const auto* current_process = GetCurrentProcessPointer(kernel);
R_UNLESS(current_process == thread->GetOwnerProcess(), ResultInvalidId);
// Verify that the thread isn't terminated.
@@ -211,7 +211,7 @@ Result GetThreadPriority(Core::System& system, s32* out_priority, Handle handle)
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Get the thread's priority.
@@ -222,7 +222,7 @@ Result GetThreadPriority(Core::System& system, s32* out_priority, Handle handle)
/// Sets the priority for the specified thread
Result SetThreadPriority(Core::System& system, Handle thread_handle, s32 priority) {
// Get the current process.
KProcess& process = *system.Kernel().CurrentProcess();
KProcess& process = GetCurrentProcess(system.Kernel());
// Validate the priority.
R_UNLESS(HighestThreadPriority <= priority && priority <= LowestThreadPriority,
@@ -253,7 +253,7 @@ Result GetThreadList(Core::System& system, s32* out_num_threads, VAddr out_threa
return ResultOutOfRange;
}
auto* const current_process = system.Kernel().CurrentProcess();
auto* const current_process = GetCurrentProcessPointer(system.Kernel());
const auto total_copy_size = out_thread_ids_size * sizeof(u64);
if (out_thread_ids_size > 0 &&
@@ -284,7 +284,7 @@ Result GetThreadCoreMask(Core::System& system, s32* out_core_id, u64* out_affini
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Get the core mask.
@@ -297,11 +297,11 @@ Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id
u64 affinity_mask) {
// Determine the core id/affinity mask.
if (core_id == IdealCoreUseProcessValue) {
core_id = system.Kernel().CurrentProcess()->GetIdealCoreId();
core_id = GetCurrentProcess(system.Kernel()).GetIdealCoreId();
affinity_mask = (1ULL << core_id);
} else {
// Validate the affinity mask.
const u64 process_core_mask = system.Kernel().CurrentProcess()->GetCoreMask();
const u64 process_core_mask = GetCurrentProcess(system.Kernel()).GetCoreMask();
R_UNLESS((affinity_mask | process_core_mask) == process_core_mask, ResultInvalidCoreId);
R_UNLESS(affinity_mask != 0, ResultInvalidCombination);
@@ -316,7 +316,7 @@ Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Set the core mask.
@@ -329,7 +329,7 @@ Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id
Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) {
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Get the thread's id.

View File

@@ -39,11 +39,11 @@ Result CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u6
R_UNLESS(IsValidTransferMemoryPermission(map_perm), ResultInvalidNewMemoryPermission);
// Get the current process and handle table.
auto& process = *kernel.CurrentProcess();
auto& process = GetCurrentProcess(kernel);
auto& handle_table = process.GetHandleTable();
// Reserve a new transfer memory from the process resource limit.
KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(),
KScopedResourceReservation trmem_reservation(&process,
LimitableResource::TransferMemoryCountMax);
R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached);

View File

@@ -592,7 +592,7 @@ void Call(Core::System& system, u32 imm) {
auto& kernel = system.Kernel();
kernel.EnterSVCProfile();
if (system.CurrentProcess()->Is64BitProcess()) {
if (GetCurrentProcess(system.Kernel()).Is64BitProcess()) {
Call64(system, imm);
} else {
Call32(system, imm);

View File

@@ -25,6 +25,7 @@
#include "core/hle/service/acc/errors.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/glue/glue_manager.h"
#include "core/hle/service/server_manager.h"
#include "core/loader/loader.h"
namespace Service::Account {
@@ -762,7 +763,7 @@ Result Module::Interface::InitializeApplicationInfoBase() {
// processes emulated. As we don't actually have pid support we should assume we're just using
// our own process
const auto launch_property =
system.GetARPManager().GetLaunchProperty(system.GetCurrentProcessProgramID());
system.GetARPManager().GetLaunchProperty(system.GetApplicationProcessProgramID());
if (launch_property.Failed()) {
LOG_ERROR(Service_ACC, "Failed to get launch property");
@@ -806,7 +807,7 @@ void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx
bool is_locked = false;
if (res != Loader::ResultStatus::Success) {
const FileSys::PatchManager pm{system.GetCurrentProcessProgramID(),
const FileSys::PatchManager pm{system.GetApplicationProcessProgramID(),
system.GetFileSystemController(),
system.GetContentProvider()};
const auto nacp_unique = pm.GetControlMetadata().first;
@@ -942,18 +943,20 @@ Module::Interface::Interface(std::shared_ptr<Module> module_,
Module::Interface::~Interface() = default;
void InstallInterfaces(Core::System& system) {
void LoopProcess(Core::System& system) {
auto module = std::make_shared<Module>();
auto profile_manager = std::make_shared<ProfileManager>();
auto server_manager = std::make_unique<ServerManager>(system);
std::make_shared<ACC_AA>(module, profile_manager, system)
->InstallAsService(system.ServiceManager());
std::make_shared<ACC_SU>(module, profile_manager, system)
->InstallAsService(system.ServiceManager());
std::make_shared<ACC_U0>(module, profile_manager, system)
->InstallAsService(system.ServiceManager());
std::make_shared<ACC_U1>(module, profile_manager, system)
->InstallAsService(system.ServiceManager());
server_manager->RegisterNamedService("acc:aa",
std::make_shared<ACC_AA>(module, profile_manager, system));
server_manager->RegisterNamedService("acc:su",
std::make_shared<ACC_SU>(module, profile_manager, system));
server_manager->RegisterNamedService("acc:u0",
std::make_shared<ACC_U0>(module, profile_manager, system));
server_manager->RegisterNamedService("acc:u1",
std::make_shared<ACC_U1>(module, profile_manager, system));
ServerManager::RunServer(std::move(server_manager));
}
} // namespace Service::Account

View File

@@ -67,7 +67,6 @@ public:
};
};
/// Registers all ACC services with the specified service manager.
void InstallInterfaces(Core::System& system);
void LoopProcess(Core::System& system);
} // namespace Service::Account

View File

@@ -24,7 +24,6 @@
#include "core/hle/service/am/idle.h"
#include "core/hle/service/am/omm.h"
#include "core/hle/service/am/spsm.h"
#include "core/hle/service/am/tcap.h"
#include "core/hle/service/apm/apm_controller.h"
#include "core/hle/service/apm/apm_interface.h"
#include "core/hle/service/bcat/backend/backend.h"
@@ -33,6 +32,7 @@
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/nvflinger/nvflinger.h"
#include "core/hle/service/pm/pm.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/sm/sm.h"
#include "core/hle/service/vi/vi.h"
#include "core/memory.h"
@@ -79,7 +79,7 @@ IWindowController::IWindowController(Core::System& system_)
IWindowController::~IWindowController() = default;
void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
const u64 process_id = system.CurrentProcess()->GetProcessID();
const u64 process_id = system.ApplicationProcess()->GetProcessID();
LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id);
@@ -1252,7 +1252,7 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex
}
auto transfer_mem =
system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
if (transfer_mem.IsNull()) {
LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
@@ -1286,7 +1286,7 @@ void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx)
}
auto transfer_mem =
system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
if (transfer_mem.IsNull()) {
LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
@@ -1465,11 +1465,12 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
const auto backend = BCAT::CreateBackendFromSettings(system, [this](u64 tid) {
return system.GetFileSystemController().GetBCATDirectory(tid);
});
const auto build_id_full = system.GetCurrentProcessBuildID();
const auto build_id_full = system.GetApplicationProcessBuildID();
u64 build_id{};
std::memcpy(&build_id, build_id_full.data(), sizeof(u64));
auto data = backend->GetLaunchParameter({system.GetCurrentProcessProgramID(), build_id});
auto data =
backend->GetLaunchParameter({system.GetApplicationProcessProgramID(), build_id});
if (data.has_value()) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
@@ -1521,7 +1522,7 @@ void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
FileSys::SaveDataAttribute attribute{};
attribute.title_id = system.GetCurrentProcessProgramID();
attribute.title_id = system.GetApplicationProcessProgramID();
attribute.user_id = user_id;
attribute.type = FileSys::SaveDataType::SaveData;
const auto res = system.GetFileSystemController().CreateSaveData(
@@ -1551,7 +1552,7 @@ void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) {
std::array<u8, 0x10> version_string{};
const auto res = [this] {
const auto title_id = system.GetCurrentProcessProgramID();
const auto title_id = system.GetApplicationProcessProgramID();
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
system.GetContentProvider()};
@@ -1570,7 +1571,7 @@ void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) {
const auto& version = res.first->GetVersionString();
std::copy(version.begin(), version.end(), version_string.begin());
} else {
constexpr char default_version[]{"1.0.0"};
static constexpr char default_version[]{"1.0.0"};
std::memcpy(version_string.data(), default_version, sizeof(default_version));
}
@@ -1588,7 +1589,7 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
u32 supported_languages = 0;
const auto res = [this] {
const auto title_id = system.GetCurrentProcessProgramID();
const auto title_id = system.GetApplicationProcessProgramID();
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
system.GetContentProvider()};
@@ -1696,7 +1697,8 @@ void IApplicationFunctions::ExtendSaveData(Kernel::HLERequestContext& ctx) {
static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
system.GetFileSystemController().WriteSaveDataSize(
type, system.GetCurrentProcessProgramID(), user_id, {new_normal_size, new_journal_size});
type, system.GetApplicationProcessProgramID(), user_id,
{new_normal_size, new_journal_size});
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
@@ -1720,7 +1722,7 @@ void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) {
user_id[0]);
const auto size = system.GetFileSystemController().ReadSaveDataSize(
type, system.GetCurrentProcessProgramID(), user_id);
type, system.GetApplicationProcessProgramID(), user_id);
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess);
@@ -1827,18 +1829,21 @@ void IApplicationFunctions::PrepareForJit(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
Core::System& system) {
void LoopProcess(NVFlinger::NVFlinger& nvflinger, Core::System& system) {
auto message_queue = std::make_shared<AppletMessageQueue>(system);
// Needed on game boot
message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
std::make_shared<AppletAE>(nvflinger, message_queue, system)->InstallAsService(service_manager);
std::make_shared<AppletOE>(nvflinger, message_queue, system)->InstallAsService(service_manager);
std::make_shared<IdleSys>(system)->InstallAsService(service_manager);
std::make_shared<OMM>(system)->InstallAsService(service_manager);
std::make_shared<SPSM>(system)->InstallAsService(service_manager);
std::make_shared<TCAP>(system)->InstallAsService(service_manager);
auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService(
"appletAE", std::make_shared<AppletAE>(nvflinger, message_queue, system));
server_manager->RegisterNamedService(
"appletOE", std::make_shared<AppletOE>(nvflinger, message_queue, system));
server_manager->RegisterNamedService("idle:sys", std::make_shared<IdleSys>(system));
server_manager->RegisterNamedService("omm", std::make_shared<OMM>(system));
server_manager->RegisterNamedService("spsm", std::make_shared<SPSM>(system));
ServerManager::RunServer(std::move(server_manager));
}
IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)

View File

@@ -396,8 +396,6 @@ public:
~IProcessWindingController() override;
};
/// Registers all AM services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
Core::System& system);
void LoopProcess(NVFlinger::NVFlinger& nvflinger, Core::System& system);
} // namespace Service::AM

View File

@@ -166,7 +166,7 @@ void Error::Execute() {
}
const auto callback = [this] { DisplayCompleted(); };
const auto title_id = system.GetCurrentProcessProgramID();
const auto title_id = system.GetApplicationProcessProgramID();
const auto& reporter{system.GetReporter()};
switch (mode) {

View File

@@ -186,7 +186,7 @@ void PhotoViewer::Execute() {
const auto callback = [this] { ViewFinished(); };
switch (mode) {
case PhotoViewerAppletMode::CurrentApp:
frontend.ShowPhotosForApplication(system.GetCurrentProcessProgramID(), callback);
frontend.ShowPhotosForApplication(system.GetApplicationProcessProgramID(), callback);
break;
case PhotoViewerAppletMode::AllApps:
frontend.ShowAllPhotos(callback);

View File

@@ -393,7 +393,7 @@ void WebBrowser::InitializeOffline() {
switch (document_kind) {
case DocumentKind::OfflineHtmlPage:
default:
title_id = system.GetCurrentProcessProgramID();
title_id = system.GetApplicationProcessProgramID();
nca_type = FileSys::ContentRecordType::HtmlDocument;
additional_paths = "html-document";
break;

View File

@@ -1,22 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/am/tcap.h"
namespace Service::AM {
TCAP::TCAP(Core::System& system_) : ServiceFramework{system_, "tcap"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetContinuousHighSkinTemperatureEvent"},
{1, nullptr, "SetOperationMode"},
{2, nullptr, "LoadAndApplySettings"},
};
// clang-format on
RegisterHandlers(functions);
}
TCAP::~TCAP() = default;
} // namespace Service::AM

View File

@@ -1,20 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::AM {
class TCAP final : public ServiceFramework<TCAP> {
public:
explicit TCAP(Core::System& system_);
~TCAP() override;
};
} // namespace Service::AM

View File

@@ -17,6 +17,7 @@
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/aoc/aoc_u.h"
#include "core/hle/service/server_manager.h"
#include "core/loader/loader.h"
namespace Service::AOC {
@@ -155,7 +156,7 @@ void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
const auto current = system.GetCurrentProcessProgramID();
const auto current = system.GetApplicationProcessProgramID();
const auto& disabled = Settings::values.disabled_addons[current];
if (std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end()) {
@@ -182,7 +183,7 @@ void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count,
process_id);
const auto current = system.GetCurrentProcessProgramID();
const auto current = system.GetApplicationProcessProgramID();
std::vector<u32> out;
const auto& disabled = Settings::values.disabled_addons[current];
@@ -228,7 +229,7 @@ void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
const auto title_id = system.GetCurrentProcessProgramID();
const auto title_id = system.GetApplicationProcessProgramID();
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
system.GetContentProvider()};
@@ -311,8 +312,10 @@ void AOC_U::CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ct
rb.PushIpcInterface<IPurchaseEventManager>(system);
}
void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
std::make_shared<AOC_U>(system)->InstallAsService(service_manager);
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService("aoc:u", std::make_shared<AOC_U>(system));
ServerManager::RunServer(std::move(server_manager));
}
} // namespace Service::AOC

View File

@@ -40,7 +40,6 @@ private:
Kernel::KEvent* aoc_change_event;
};
/// Registers all AOC services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
void LoopProcess(Core::System& system);
} // namespace Service::AOC

View File

@@ -4,22 +4,24 @@
#include "core/core.h"
#include "core/hle/service/apm/apm.h"
#include "core/hle/service/apm/apm_interface.h"
#include "core/hle/service/server_manager.h"
namespace Service::APM {
Module::Module() = default;
Module::~Module() = default;
void InstallInterfaces(Core::System& system) {
auto module_ = std::make_shared<Module>();
std::make_shared<APM>(system, module_, system.GetAPMController(), "apm")
->InstallAsService(system.ServiceManager());
std::make_shared<APM>(system, module_, system.GetAPMController(), "apm:p")
->InstallAsService(system.ServiceManager());
std::make_shared<APM>(system, module_, system.GetAPMController(), "apm:am")
->InstallAsService(system.ServiceManager());
std::make_shared<APM_Sys>(system, system.GetAPMController())
->InstallAsService(system.ServiceManager());
void LoopProcess(Core::System& system) {
auto module = std::make_shared<Module>();
auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService(
"apm", std::make_shared<APM>(system, module, system.GetAPMController(), "apm"));
server_manager->RegisterNamedService(
"apm:am", std::make_shared<APM>(system, module, system.GetAPMController(), "apm:am"));
server_manager->RegisterNamedService(
"apm:sys", std::make_shared<APM_Sys>(system, system.GetAPMController()));
ServerManager::RunServer(std::move(server_manager));
}
} // namespace Service::APM

View File

@@ -15,7 +15,6 @@ public:
~Module();
};
/// Registers all AM services with the specified service manager.
void InstallInterfaces(Core::System& system);
void LoopProcess(Core::System& system);
} // namespace Service::APM

View File

@@ -56,7 +56,7 @@ void Controller::SetPerformanceConfiguration(PerformanceMode mode,
}
void Controller::SetFromCpuBoostMode(CpuBoostMode mode) {
constexpr std::array<PerformanceConfiguration, 3> BOOST_MODE_TO_CONFIG_MAP{{
static constexpr std::array<PerformanceConfiguration, 3> BOOST_MODE_TO_CONFIG_MAP{{
PerformanceConfiguration::Config7,
PerformanceConfiguration::Config13,
PerformanceConfiguration::Config15,

View File

@@ -1,21 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/audio/auddbg.h"
namespace Service::Audio {
AudDbg::AudDbg(Core::System& system_, const char* name) : ServiceFramework{system_, name} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "RequestSuspendForDebug"},
{1, nullptr, "RequestResumeForDebug"},
};
// clang-format on
RegisterHandlers(functions);
}
AudDbg::~AudDbg() = default;
} // namespace Service::Audio

View File

@@ -1,20 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::Audio {
class AudDbg final : public ServiceFramework<AudDbg> {
public:
explicit AudDbg(Core::System& system_, const char* name);
~AudDbg() override;
};
} // namespace Service::Audio

View File

@@ -1,23 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/audio/audin_a.h"
namespace Service::Audio {
AudInA::AudInA(Core::System& system_) : ServiceFramework{system_, "audin:a"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "RequestSuspend"},
{1, nullptr, "RequestResume"},
{2, nullptr, "GetProcessMasterVolume"},
{3, nullptr, "SetProcessMasterVolume"},
};
// clang-format on
RegisterHandlers(functions);
}
AudInA::~AudInA() = default;
} // namespace Service::Audio

View File

@@ -1,20 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::Audio {
class AudInA final : public ServiceFramework<AudInA> {
public:
explicit AudInA(Core::System& system_);
~AudInA() override;
};
} // namespace Service::Audio

View File

@@ -203,9 +203,8 @@ private:
};
AudInU::AudInU(Core::System& system_)
: ServiceFramework{system_, "audin:u", ServiceThreadType::CreateNew},
service_context{system_, "AudInU"}, impl{std::make_unique<AudioCore::AudioIn::Manager>(
system_)} {
: ServiceFramework{system_, "audin:u"}, service_context{system_, "AudInU"},
impl{std::make_unique<AudioCore::AudioIn::Manager>(system_)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &AudInU::ListAudioIns, "ListAudioIns"},

View File

@@ -1,40 +1,31 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/hle/service/audio/audctl.h"
#include "core/hle/service/audio/auddbg.h"
#include "core/hle/service/audio/audin_a.h"
#include "core/hle/service/audio/audin_u.h"
#include "core/hle/service/audio/audio.h"
#include "core/hle/service/audio/audout_a.h"
#include "core/hle/service/audio/audout_u.h"
#include "core/hle/service/audio/audrec_a.h"
#include "core/hle/service/audio/audrec_u.h"
#include "core/hle/service/audio/audren_a.h"
#include "core/hle/service/audio/audren_u.h"
#include "core/hle/service/audio/codecctl.h"
#include "core/hle/service/audio/hwopus.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"
namespace Service::Audio {
void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
std::make_shared<AudCtl>(system)->InstallAsService(service_manager);
std::make_shared<AudOutA>(system)->InstallAsService(service_manager);
std::make_shared<AudOutU>(system)->InstallAsService(service_manager);
std::make_shared<AudInA>(system)->InstallAsService(service_manager);
std::make_shared<AudInU>(system)->InstallAsService(service_manager);
std::make_shared<AudRecA>(system)->InstallAsService(service_manager);
std::make_shared<AudRecU>(system)->InstallAsService(service_manager);
std::make_shared<AudRenA>(system)->InstallAsService(service_manager);
std::make_shared<AudRenU>(system)->InstallAsService(service_manager);
std::make_shared<CodecCtl>(system)->InstallAsService(service_manager);
std::make_shared<HwOpus>(system)->InstallAsService(service_manager);
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
std::make_shared<AudDbg>(system, "audin:d")->InstallAsService(service_manager);
std::make_shared<AudDbg>(system, "audout:d")->InstallAsService(service_manager);
std::make_shared<AudDbg>(system, "audrec:d")->InstallAsService(service_manager);
std::make_shared<AudDbg>(system, "audren:d")->InstallAsService(service_manager);
server_manager->RegisterNamedService("audctl", std::make_shared<AudCtl>(system));
server_manager->RegisterNamedService("audout:u", std::make_shared<AudOutU>(system));
server_manager->RegisterNamedService("audin:u", std::make_shared<AudInU>(system));
server_manager->RegisterNamedService("audrec:a", std::make_shared<AudRecA>(system));
server_manager->RegisterNamedService("audrec:u", std::make_shared<AudRecU>(system));
server_manager->RegisterNamedService("audren:u", std::make_shared<AudRenU>(system));
server_manager->RegisterNamedService("hwopus", std::make_shared<HwOpus>(system));
ServerManager::RunServer(std::move(server_manager));
}
} // namespace Service::Audio

View File

@@ -13,7 +13,6 @@ class ServiceManager;
namespace Service::Audio {
/// Registers all Audio services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
void LoopProcess(Core::System& system);
} // namespace Service::Audio

View File

@@ -1,25 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/audio/audout_a.h"
namespace Service::Audio {
AudOutA::AudOutA(Core::System& system_) : ServiceFramework{system_, "audout:a"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "RequestSuspend"},
{1, nullptr, "RequestResume"},
{2, nullptr, "GetProcessMasterVolume"},
{3, nullptr, "SetProcessMasterVolume"},
{4, nullptr, "GetProcessRecordVolume"},
{5, nullptr, "SetProcessRecordVolume"},
};
// clang-format on
RegisterHandlers(functions);
}
AudOutA::~AudOutA() = default;
} // namespace Service::Audio

View File

@@ -1,20 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::Audio {
class AudOutA final : public ServiceFramework<AudOutA> {
public:
explicit AudOutA(Core::System& system_);
~AudOutA() override;
};
} // namespace Service::Audio

View File

@@ -26,9 +26,8 @@ public:
explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager,
size_t session_id, const std::string& device_name,
const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioOut", ServiceThreadType::CreateNew},
service_context{system_, "IAudioOut"}, event{service_context.CreateEvent(
"AudioOutEvent")},
: ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
event{service_context.CreateEvent("AudioOutEvent")},
impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} {
// clang-format off
@@ -221,9 +220,8 @@ private:
};
AudOutU::AudOutU(Core::System& system_)
: ServiceFramework{system_, "audout:u", ServiceThreadType::CreateNew},
service_context{system_, "AudOutU"}, impl{std::make_unique<AudioCore::AudioOut::Manager>(
system_)} {
: ServiceFramework{system_, "audout:u"}, service_context{system_, "AudOutU"},
impl{std::make_unique<AudioCore::AudioOut::Manager>(system_)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &AudOutU::ListAudioOuts, "ListAudioOuts"},

View File

@@ -1,27 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/audio/audren_a.h"
namespace Service::Audio {
AudRenA::AudRenA(Core::System& system_) : ServiceFramework{system_, "audren:a"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "RequestSuspend"},
{1, nullptr, "RequestResume"},
{2, nullptr, "GetProcessMasterVolume"},
{3, nullptr, "SetProcessMasterVolume"},
{4, nullptr, "RegisterAppletResourceUserId"},
{5, nullptr, "UnregisterAppletResourceUserId"},
{6, nullptr, "GetProcessRecordVolume"},
{7, nullptr, "SetProcessRecordVolume"},
};
// clang-format on
RegisterHandlers(functions);
}
AudRenA::~AudRenA() = default;
} // namespace Service::Audio

View File

@@ -1,20 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::Audio {
class AudRenA final : public ServiceFramework<AudRenA> {
public:
explicit AudRenA(Core::System& system_);
~AudRenA() override;
};
} // namespace Service::Audio

View File

@@ -35,10 +35,9 @@ public:
AudioCore::AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, u64 applet_resource_user_id, s32 session_id)
: ServiceFramework{system_, "IAudioRenderer", ServiceThreadType::CreateNew},
service_context{system_, "IAudioRenderer"}, rendered_event{service_context.CreateEvent(
"IAudioRendererEvent")},
manager{manager_}, impl{std::make_unique<Renderer>(system_, manager, rendered_event)} {
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
impl{std::make_unique<Renderer>(system_, manager, rendered_event)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
@@ -243,10 +242,8 @@ class IAudioDevice final : public ServiceFramework<IAudioDevice> {
public:
explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
u32 device_num)
: ServiceFramework{system_, "IAudioDevice", ServiceThreadType::CreateNew},
service_context{system_, "IAudioDevice"}, impl{std::make_unique<AudioDevice>(
system_, applet_resource_user_id,
revision)},
: ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
static const FunctionInfo functions[] = {
{0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
@@ -421,7 +418,7 @@ private:
};
AudRenU::AudRenU(Core::System& system_)
: ServiceFramework{system_, "audren:u", ServiceThreadType::CreateNew},
: ServiceFramework{system_, "audren:u"},
service_context{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} {
// clang-format off
static const FunctionInfo functions[] = {
@@ -455,7 +452,7 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
return;
}
const auto& handle_table{system.CurrentProcess()->GetHandleTable()};
const auto& handle_table{system.ApplicationProcess()->GetHandleTable()};
auto process{handle_table.GetObject<Kernel::KProcess>(process_handle)};
auto transfer_memory{
process->GetHandleTable().GetObject<Kernel::KTransferMemory>(transfer_memory_handle)};

View File

@@ -1,29 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/audio/codecctl.h"
namespace Service::Audio {
CodecCtl::CodecCtl(Core::System& system_) : ServiceFramework{system_, "codecctl"} {
static const FunctionInfo functions[] = {
{0, nullptr, "Initialize"},
{1, nullptr, "Finalize"},
{2, nullptr, "Sleep"},
{3, nullptr, "Wake"},
{4, nullptr, "SetVolume"},
{5, nullptr, "GetVolumeMax"},
{6, nullptr, "GetVolumeMin"},
{7, nullptr, "SetActiveTarget"},
{8, nullptr, "GetActiveTarget"},
{9, nullptr, "BindHeadphoneMicJackInterrupt"},
{10, nullptr, "IsHeadphoneMicJackInserted"},
{11, nullptr, "ClearHeadphoneMicJackInterrupt"},
{12, nullptr, "IsRequested"},
};
RegisterHandlers(functions);
}
CodecCtl::~CodecCtl() = default;
} // namespace Service::Audio

View File

@@ -1,20 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::Audio {
class CodecCtl final : public ServiceFramework<CodecCtl> {
public:
explicit CodecCtl(Core::System& system_);
~CodecCtl() override;
};
} // namespace Service::Audio

View File

@@ -15,6 +15,7 @@
#include "core/hle/service/bcat/bcat.h"
#include "core/hle/service/bcat/bcat_module.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/server_manager.h"
namespace Service::BCAT {
@@ -176,8 +177,8 @@ private:
void RequestSyncDeliveryCache(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_BCAT, "called");
backend.Synchronize({system.GetCurrentProcessProgramID(),
GetCurrentBuildID(system.GetCurrentProcessBuildID())},
backend.Synchronize({system.GetApplicationProcessProgramID(),
GetCurrentBuildID(system.GetApplicationProcessBuildID())},
GetProgressBackend(SyncType::Normal));
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -193,8 +194,8 @@ private:
LOG_DEBUG(Service_BCAT, "called, name={}", name);
backend.SynchronizeDirectory({system.GetCurrentProcessProgramID(),
GetCurrentBuildID(system.GetCurrentProcessBuildID())},
backend.SynchronizeDirectory({system.GetApplicationProcessProgramID(),
GetCurrentBuildID(system.GetApplicationProcessBuildID())},
name, GetProgressBackend(SyncType::Directory));
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -554,7 +555,7 @@ private:
void Module::Interface::CreateDeliveryCacheStorageService(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_BCAT, "called");
const auto title_id = system.GetCurrentProcessProgramID();
const auto title_id = system.GetApplicationProcessProgramID();
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IDeliveryCacheStorageService>(system, fsc.GetBCATDirectory(title_id));
@@ -585,16 +586,23 @@ Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> modu
Module::Interface::~Interface() = default;
void InstallInterfaces(Core::System& system) {
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
auto module = std::make_shared<Module>();
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:a")
->InstallAsService(system.ServiceManager());
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:m")
->InstallAsService(system.ServiceManager());
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:u")
->InstallAsService(system.ServiceManager());
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:s")
->InstallAsService(system.ServiceManager());
server_manager->RegisterNamedService(
"bcat:a",
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:a"));
server_manager->RegisterNamedService(
"bcat:m",
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:m"));
server_manager->RegisterNamedService(
"bcat:u",
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:u"));
server_manager->RegisterNamedService(
"bcat:s",
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:s"));
ServerManager::RunServer(std::move(server_manager));
}
} // namespace Service::BCAT

View File

@@ -39,8 +39,7 @@ public:
};
};
/// Registers all BCAT services with the specified service manager.
void InstallInterfaces(Core::System& system);
void LoopProcess(Core::System& system);
} // namespace BCAT

View File

@@ -4,8 +4,8 @@
#include <memory>
#include "core/hle/service/bpc/bpc.h"
#include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
namespace Service::BPC {
@@ -54,9 +54,12 @@ public:
}
};
void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
std::make_shared<BPC>(system)->InstallAsService(sm);
std::make_shared<BPC_R>(system)->InstallAsService(sm);
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService("bpc", std::make_shared<BPC>(system));
server_manager->RegisterNamedService("bpc:r", std::make_shared<BPC_R>(system));
ServerManager::RunServer(std::move(server_manager));
}
} // namespace Service::BPC

Some files were not shown because too many files have changed in this diff Show More