diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/core_cpu.cpp | 3 | ||||
-rw-r--r-- | src/core/core_cpu.h | 2 | ||||
-rw-r--r-- | src/core/core_timing.cpp | 2 | ||||
-rw-r--r-- | src/core/file_sys/partition_filesystem.h | 2 | ||||
-rw-r--r-- | src/core/file_sys/program_metadata.h | 2 | ||||
-rw-r--r-- | src/core/file_sys/vfs.h | 20 | ||||
-rw-r--r-- | src/core/file_sys/vfs_offset.h | 3 | ||||
-rw-r--r-- | src/core/file_sys/vfs_vector.h | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 32 | ||||
-rw-r--r-- | src/core/hle/service/audio/audren_u.cpp | 44 | ||||
-rw-r--r-- | src/core/hle/service/audio/audren_u.h | 1 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid.cpp | 17 | ||||
-rw-r--r-- | src/core/hle/service/service.h | 2 | ||||
-rw-r--r-- | src/core/loader/loader.cpp | 2 | ||||
-rw-r--r-- | src/core/loader/loader.h | 2 |
16 files changed, 107 insertions, 33 deletions
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index 46a522fcd..9b306faf6 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp @@ -14,6 +14,7 @@ #include "core/core_timing.h" #include "core/hle/kernel/scheduler.h" #include "core/hle/kernel/thread.h" +#include "core/hle/lock.h" #include "core/settings.h" namespace Core { @@ -125,6 +126,8 @@ void Cpu::Reschedule() { } reschedule_pending = false; + // Lock the global kernel mutex when we manipulate the HLE state + std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); scheduler->Reschedule(); } diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h index 976952903..56cdae194 100644 --- a/src/core/core_cpu.h +++ b/src/core/core_cpu.h @@ -79,7 +79,7 @@ private: std::shared_ptr<CpuBarrier> cpu_barrier; std::shared_ptr<Kernel::Scheduler> scheduler; - bool reschedule_pending{}; + std::atomic<bool> reschedule_pending = false; size_t core_index; }; diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index d3bb6f818..f977d1b32 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -135,11 +135,9 @@ void ClearPendingEvents() { void ScheduleEvent(s64 cycles_into_future, const EventType* event_type, u64 userdata) { ASSERT(event_type != nullptr); s64 timeout = GetTicks() + cycles_into_future; - // If this event needs to be scheduled before the next advance(), force one early if (!is_global_timer_sane) ForceExceptionCheck(cycles_into_future); - event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type}); std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); } diff --git a/src/core/file_sys/partition_filesystem.h b/src/core/file_sys/partition_filesystem.h index 7c7a75816..be7bc32a8 100644 --- a/src/core/file_sys/partition_filesystem.h +++ b/src/core/file_sys/partition_filesystem.h @@ -13,7 +13,7 @@ #include "core/file_sys/vfs.h" namespace Loader { -enum class ResultStatus; +enum class ResultStatus : u16; } namespace FileSys { diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h index 06a7315db..74a91052b 100644 --- a/src/core/file_sys/program_metadata.h +++ b/src/core/file_sys/program_metadata.h @@ -13,7 +13,7 @@ #include "partition_filesystem.h" namespace Loader { -enum class ResultStatus; +enum class ResultStatus : u16; } namespace FileSys { diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h index 141a053ce..78a63c59b 100644 --- a/src/core/file_sys/vfs.h +++ b/src/core/file_sys/vfs.h @@ -15,9 +15,9 @@ namespace FileSys { -struct VfsFilesystem; -struct VfsFile; -struct VfsDirectory; +class VfsDirectory; +class VfsFile; +class VfsFilesystem; // Convenience typedefs to use Vfs* interfaces using VirtualFilesystem = std::shared_ptr<VfsFilesystem>; @@ -34,8 +34,9 @@ enum class VfsEntryType { // A class representing an abstract filesystem. A default implementation given the root VirtualDir // is provided for convenience, but if the Vfs implementation has any additional state or // functionality, they will need to override. -struct VfsFilesystem : NonCopyable { - VfsFilesystem(VirtualDir root); +class VfsFilesystem : NonCopyable { +public: + explicit VfsFilesystem(VirtualDir root); virtual ~VfsFilesystem(); // Gets the friendly name for the filesystem. @@ -81,7 +82,8 @@ protected: }; // A class representing a file in an abstract filesystem. -struct VfsFile : NonCopyable { +class VfsFile : NonCopyable { +public: virtual ~VfsFile(); // Retrieves the file name. @@ -179,7 +181,8 @@ struct VfsFile : NonCopyable { }; // A class representing a directory in an abstract filesystem. -struct VfsDirectory : NonCopyable { +class VfsDirectory : NonCopyable { +public: virtual ~VfsDirectory(); // Retrives the file located at path as if the current directory was root. Returns nullptr if @@ -295,7 +298,8 @@ protected: // A convenience partial-implementation of VfsDirectory that stubs out methods that should only work // if writable. This is to avoid redundant empty methods everywhere. -struct ReadOnlyVfsDirectory : public VfsDirectory { +class ReadOnlyVfsDirectory : public VfsDirectory { +public: bool IsWritable() const override; bool IsReadable() const override; std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override; diff --git a/src/core/file_sys/vfs_offset.h b/src/core/file_sys/vfs_offset.h index 235970dc5..cb92d1570 100644 --- a/src/core/file_sys/vfs_offset.h +++ b/src/core/file_sys/vfs_offset.h @@ -15,7 +15,8 @@ namespace FileSys { // Similar to seeking to an offset. // If the file is writable, operations that would write past the end of the offset file will expand // the size of this wrapper. -struct OffsetVfsFile : public VfsFile { +class OffsetVfsFile : public VfsFile { +public: OffsetVfsFile(std::shared_ptr<VfsFile> file, size_t size, size_t offset = 0, std::string new_name = "", VirtualDir new_parent = nullptr); diff --git a/src/core/file_sys/vfs_vector.h b/src/core/file_sys/vfs_vector.h index ba469647b..b3b468233 100644 --- a/src/core/file_sys/vfs_vector.h +++ b/src/core/file_sys/vfs_vector.h @@ -10,7 +10,8 @@ namespace FileSys { // An implementation of VfsDirectory that maintains two vectors for subdirectories and files. // Vector data is supplied upon construction. -struct VectorVfsDirectory : public VfsDirectory { +class VectorVfsDirectory : public VfsDirectory { +public: explicit VectorVfsDirectory(std::vector<VirtualFile> files = {}, std::vector<VirtualDir> dirs = {}, VirtualDir parent = nullptr, std::string name = ""); diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 5db2db687..5818cc06d 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -706,8 +706,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); auto owner = g_handle_table.Get<Thread>(owner_handle); ASSERT(owner); - ASSERT(thread->status != ThreadStatus::Running); - thread->status = ThreadStatus::WaitMutex; + ASSERT(thread->status == ThreadStatus::WaitMutex); thread->wakeup_callback = nullptr; owner->AddMutexWaiter(thread); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index b9022feae..a1a7867ce 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -23,6 +23,7 @@ #include "core/hle/kernel/object.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/thread.h" +#include "core/hle/lock.h" #include "core/hle/result.h" #include "core/memory.h" @@ -104,6 +105,10 @@ void ExitCurrentThread() { */ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { const auto proper_handle = static_cast<Handle>(thread_handle); + + // Lock the global kernel mutex when we enter the kernel HLE. + std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); + SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>(proper_handle); if (thread == nullptr) { LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle); @@ -155,8 +160,10 @@ void Thread::WakeAfterDelay(s64 nanoseconds) { if (nanoseconds == -1) return; - CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(nanoseconds), ThreadWakeupEventType, - callback_handle); + // This function might be called from any thread so we have to be cautious and use the + // thread-safe version of ScheduleEvent. + CoreTiming::ScheduleEventThreadsafe(CoreTiming::nsToCycles(nanoseconds), ThreadWakeupEventType, + callback_handle); } void Thread::CancelWakeupTimer() { @@ -419,12 +426,33 @@ VAddr Thread::GetCommandBufferAddress() const { } void Thread::AddMutexWaiter(SharedPtr<Thread> thread) { + if (thread->lock_owner == this) { + // If the thread is already waiting for this thread to release the mutex, ensure that the + // waiters list is consistent and return without doing anything. + auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread); + ASSERT(itr != wait_mutex_threads.end()); + return; + } + + // A thread can't wait on two different mutexes at the same time. + ASSERT(thread->lock_owner == nullptr); + + // Ensure that the thread is not already in the list of mutex waiters + auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread); + ASSERT(itr == wait_mutex_threads.end()); + thread->lock_owner = this; wait_mutex_threads.emplace_back(std::move(thread)); UpdatePriority(); } void Thread::RemoveMutexWaiter(SharedPtr<Thread> thread) { + ASSERT(thread->lock_owner == this); + + // Ensure that the thread is in the list of mutex waiters + auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread); + ASSERT(itr != wait_mutex_threads.end()); + boost::remove_erase(wait_mutex_threads, thread); thread->lock_owner = nullptr; UpdatePriority(); diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index f99304de5..9e75eb3a6 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -20,9 +20,9 @@ public: explicit IAudioRenderer(AudioCore::AudioRendererParameter audren_params) : ServiceFramework("IAudioRenderer") { static const FunctionInfo functions[] = { - {0, nullptr, "GetAudioRendererSampleRate"}, - {1, nullptr, "GetAudioRendererSampleCount"}, - {2, nullptr, "GetAudioRendererMixBufferCount"}, + {0, &IAudioRenderer::GetAudioRendererSampleRate, "GetAudioRendererSampleRate"}, + {1, &IAudioRenderer::GetAudioRendererSampleCount, "GetAudioRendererSampleCount"}, + {2, &IAudioRenderer::GetAudioRendererMixBufferCount, "GetAudioRendererMixBufferCount"}, {3, nullptr, "GetAudioRendererState"}, {4, &IAudioRenderer::RequestUpdateAudioRenderer, "RequestUpdateAudioRenderer"}, {5, &IAudioRenderer::StartAudioRenderer, "StartAudioRenderer"}, @@ -45,6 +45,27 @@ private: system_event->Signal(); } + void GetAudioRendererSampleRate(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(renderer->GetSampleRate()); + LOG_DEBUG(Service_Audio, "called"); + } + + void GetAudioRendererSampleCount(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(renderer->GetSampleCount()); + LOG_DEBUG(Service_Audio, "called"); + } + + void GetAudioRendererMixBufferCount(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(renderer->GetMixBufferCount()); + LOG_DEBUG(Service_Audio, "called"); + } + void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) { ctx.WriteBuffer(renderer->UpdateAudioRenderer(ctx.ReadBuffer())); IPC::ResponseBuilder rb{ctx, 2}; @@ -169,7 +190,8 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") { {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"}, {2, &AudRenU::GetAudioDevice, "GetAudioDevice"}, {3, nullptr, "OpenAudioRendererAuto"}, - {4, nullptr, "GetAudioDeviceServiceWithRevisionInfo"}, + {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, + "GetAudioDeviceServiceWithRevisionInfo"}, }; RegisterHandlers(functions); } @@ -189,7 +211,7 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; auto params = rp.PopRaw<AudioCore::AudioRendererParameter>(); - u64 buffer_sz = Common::AlignUp(4 * params.unknown_8, 0x40); + u64 buffer_sz = Common::AlignUp(4 * params.mix_buffer_count, 0x40); buffer_sz += params.unknown_c * 1024; buffer_sz += 0x940 * (params.unknown_c + 1); buffer_sz += 0x3F0 * params.voice_count; @@ -197,7 +219,7 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { buffer_sz += Common::AlignUp(8 * params.voice_count, 0x10); buffer_sz += Common::AlignUp((0x3C0 * (params.sink_count + params.unknown_c) + 4 * params.sample_count) * - (params.unknown_8 + 6), + (params.mix_buffer_count + 6), 0x40); if (IsFeatureSupported(AudioFeatures::Splitter, params.revision)) { @@ -253,6 +275,16 @@ void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_Audio, "called"); } +void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<Audio::IAudioDevice>(); + + LOG_WARNING(Service_Audio, "(STUBBED) called"); // TODO(ogniK): Figure out what is different + // based on the current revision +} + bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const { u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap switch (feature) { diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index 14907f8ae..8600ac6e4 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h @@ -22,6 +22,7 @@ private: void OpenAudioRenderer(Kernel::HLERequestContext& ctx); void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); void GetAudioDevice(Kernel::HLERequestContext& ctx); + void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx); enum class AudioFeatures : u32 { Splitter, diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index dcdfa0e19..970942d3f 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -291,6 +291,7 @@ private: class Hid final : public ServiceFramework<Hid> { public: Hid() : ServiceFramework("hid") { + // clang-format off static const FunctionInfo functions[] = { {0, &Hid::CreateAppletResource, "CreateAppletResource"}, {1, &Hid::ActivateDebugPad, "ActivateDebugPad"}, @@ -333,15 +334,13 @@ public: {102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"}, {103, &Hid::ActivateNpad, "ActivateNpad"}, {104, nullptr, "DeactivateNpad"}, - {106, &Hid::AcquireNpadStyleSetUpdateEventHandle, - "AcquireNpadStyleSetUpdateEventHandle"}, - {107, nullptr, "DisconnectNpad"}, + {106, &Hid::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"}, + {107, &Hid::DisconnectNpad, "DisconnectNpad"}, {108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"}, {109, nullptr, "ActivateNpadWithRevision"}, {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"}, {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, - {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, - "SetNpadJoyAssignmentModeSingleByDefault"}, + {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"}, {123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"}, {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"}, {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"}, @@ -398,6 +397,8 @@ public: {1000, nullptr, "SetNpadCommunicationMode"}, {1001, nullptr, "GetNpadCommunicationMode"}, }; + // clang-format on + RegisterHandlers(functions); event = Kernel::Event::Create(Kernel::ResetType::OneShot, "hid:EventHandle"); @@ -496,6 +497,12 @@ private: LOG_WARNING(Service_HID, "(STUBBED) called"); } + void DisconnectNpad(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_HID, "(STUBBED) called"); + } + void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 8a294c0f2..cd9c74f3d 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -23,7 +23,7 @@ class HLERequestContext; } // namespace Kernel namespace FileSys { -struct VfsFilesystem; +class VfsFilesystem; } namespace Service { diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 2f5bfc67c..1f2f31535 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -126,7 +126,7 @@ constexpr std::array<const char*, 36> RESULT_MESSAGES{ }; std::string GetMessageForResultStatus(ResultStatus status) { - return GetMessageForResultStatus(static_cast<size_t>(status)); + return GetMessageForResultStatus(static_cast<u16>(status)); } std::string GetMessageForResultStatus(u16 status) { diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index cfdadbee3..285363549 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -56,7 +56,7 @@ FileType GuessFromFilename(const std::string& name); std::string GetFileTypeString(FileType type); /// Return type for functions in Loader namespace -enum class ResultStatus { +enum class ResultStatus : u16 { Success, ErrorAlreadyLoaded, ErrorNotImplemented, |