diff --git a/.gitignore b/.gitignore
index 61d9e32e1..c331f9e70 100644
--- a/.gitignore
+++ b/.gitignore
@@ -414,3 +414,6 @@ FodyWeavers.xsd
# for macOS
**/.DS_Store
+
+# JetBrains
+.idea
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 47cfd8595..e135794ec 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -208,30 +208,38 @@ set(GNM_LIB src/core/libraries/gnmdriver/gnmdriver.cpp
src/core/libraries/gnmdriver/gnm_error.h
)
-set(KERNEL_LIB src/core/libraries/kernel/event_flag/event_flag.cpp
- src/core/libraries/kernel/event_flag/event_flag.h
- src/core/libraries/kernel/event_flag/event_flag_obj.cpp
- src/core/libraries/kernel/event_flag/event_flag_obj.h
+set(KERNEL_LIB src/core/libraries/kernel/threads/condvar.cpp
+ src/core/libraries/kernel/threads/event_flag.cpp
+ src/core/libraries/kernel/threads/exception.cpp
+ src/core/libraries/kernel/threads/exception.h
+ src/core/libraries/kernel/threads/mutex.cpp
+ src/core/libraries/kernel/threads/pthread_attr.cpp
+ src/core/libraries/kernel/threads/pthread_clean.cpp
+ src/core/libraries/kernel/threads/pthread.cpp
+ src/core/libraries/kernel/threads/pthread_spec.cpp
src/core/libraries/kernel/threads/rwlock.cpp
src/core/libraries/kernel/threads/semaphore.cpp
- src/core/libraries/kernel/threads/keys.cpp
- src/core/libraries/kernel/threads/threads.h
- src/core/libraries/kernel/cpu_management.cpp
- src/core/libraries/kernel/cpu_management.h
- src/core/libraries/kernel/event_queue.cpp
- src/core/libraries/kernel/event_queue.h
- src/core/libraries/kernel/event_queues.cpp
- src/core/libraries/kernel/event_queues.h
+ src/core/libraries/kernel/threads/sleepq.cpp
+ src/core/libraries/kernel/threads/sleepq.h
+ src/core/libraries/kernel/threads/stack.cpp
+ src/core/libraries/kernel/threads/tcb.cpp
+ src/core/libraries/kernel/threads/pthread.h
+ src/core/libraries/kernel/threads/thread_state.cpp
+ src/core/libraries/kernel/threads/thread_state.h
+ src/core/libraries/kernel/process.cpp
+ src/core/libraries/kernel/process.h
+ src/core/libraries/kernel/equeue.cpp
+ src/core/libraries/kernel/equeue.h
src/core/libraries/kernel/file_system.cpp
src/core/libraries/kernel/file_system.h
- src/core/libraries/kernel/libkernel.cpp
- src/core/libraries/kernel/libkernel.h
- src/core/libraries/kernel/memory_management.cpp
- src/core/libraries/kernel/memory_management.h
- src/core/libraries/kernel/thread_management.cpp
- src/core/libraries/kernel/thread_management.h
- src/core/libraries/kernel/time_management.cpp
- src/core/libraries/kernel/time_management.h
+ src/core/libraries/kernel/kernel.cpp
+ src/core/libraries/kernel/kernel.h
+ src/core/libraries/kernel/memory.cpp
+ src/core/libraries/kernel/memory.h
+ src/core/libraries/kernel/threads.cpp
+ src/core/libraries/kernel/threads.h
+ src/core/libraries/kernel/time.cpp
+ src/core/libraries/kernel/time.h
)
set(NETWORK_LIBS src/core/libraries/network/http.cpp
@@ -453,7 +461,10 @@ set(COMMON src/common/logging/backend.cpp
src/common/signal_context.h
src/common/signal_context.cpp
src/common/singleton.h
+ src/common/slab_heap.h
src/common/slot_vector.h
+ src/common/spin_lock.cpp
+ src/common/spin_lock.h
src/common/string_util.cpp
src/common/string_util.h
src/common/thread.cpp
@@ -541,6 +552,8 @@ set(CORE src/core/aerolib/stubs.cpp
src/core/platform.h
src/core/signals.cpp
src/core/signals.h
+ src/core/thread.cpp
+ src/core/thread.h
src/core/tls.cpp
src/core/tls.h
src/core/virtual_memory.cpp
@@ -921,7 +934,10 @@ if (ENABLE_QT_GUI)
set_target_properties(shadps4 PROPERTIES
# WIN32_EXECUTABLE ON
MACOSX_BUNDLE ON
- MACOSX_BUNDLE_ICON_FILE shadPS4.icns)
+ MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/dist/MacOSBundleInfo.plist.in"
+ MACOSX_BUNDLE_ICON_FILE "shadPS4.icns"
+ MACOSX_BUNDLE_SHORT_VERSION_STRING "0.4.1"
+ )
set_source_files_properties(src/images/shadPS4.icns PROPERTIES
MACOSX_PACKAGE_LOCATION Resources)
diff --git a/REUSE.toml b/REUSE.toml
index 405156231..7b2862e53 100644
--- a/REUSE.toml
+++ b/REUSE.toml
@@ -7,6 +7,7 @@ path = [
".github/FUNDING.yml",
".github/shadps4.png",
".gitmodules",
+ "dist/MacOSBundleInfo.plist.in",
"dist/net.shadps4.shadPS4.desktop",
"dist/net.shadps4.shadPS4_metadata.pot",
"dist/net.shadps4.shadPS4.metainfo.xml",
diff --git a/dist/MacOSBundleInfo.plist.in b/dist/MacOSBundleInfo.plist.in
new file mode 100644
index 000000000..70cbfb4ab
--- /dev/null
+++ b/dist/MacOSBundleInfo.plist.in
@@ -0,0 +1,46 @@
+
+
+
+
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ APPL
+
+ CFBundleName
+ shadps4
+ CFBundleIdentifier
+ com.shadps4-emu.shadps4
+ CFBundleExecutable
+ shadps4
+
+ CFBundleVersion
+ 1.0.0
+ CFBundleShortVersionString
+ ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
+
+ LSMinimumSystemVersion
+ ${CMAKE_OSX_DEPLOYMENT_TARGET}
+ LSApplicationCategoryType
+ public.app-category.games
+ GCSupportsGameMode
+
+
+ NSHumanReadableCopyright
+
+
+ CFBundleIconFile
+ ${MACOSX_BUNDLE_ICON_FILE}
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleAllowMixedLocalizations
+
+
+ NSPrincipalClass
+ NSApplication
+
+ NSSupportsAutomaticGraphicsSwitching
+
+
+
diff --git a/src/common/debug.h b/src/common/debug.h
index 596ad7b84..091c6191d 100644
--- a/src/common/debug.h
+++ b/src/common/debug.h
@@ -41,7 +41,7 @@ enum MarkersPalette : int {
#define RENDERER_TRACE ZoneScopedC(RendererMarkerColor)
#define HLE_TRACE ZoneScopedC(HleMarkerColor)
-#define TRACE_HINT(str) ZoneText(str.c_str(), str.size())
+#define TRACE_HINT(str) ZoneText(str.data(), str.size())
#define TRACE_WARN(msg) \
[](const auto& msg) { TracyMessageC(msg.c_str(), msg.size(), tracy::Color::DarkOrange); }(msg);
diff --git a/src/common/slab_heap.h b/src/common/slab_heap.h
new file mode 100644
index 000000000..7648ebea3
--- /dev/null
+++ b/src/common/slab_heap.h
@@ -0,0 +1,163 @@
+// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include
+#include "common/assert.h"
+#include "common/spin_lock.h"
+
+namespace Common {
+
+class SlabHeapImpl {
+public:
+ struct Node {
+ Node* next{};
+ };
+
+public:
+ constexpr SlabHeapImpl() = default;
+
+ void Initialize() {
+ ASSERT(m_head == nullptr);
+ }
+
+ Node* GetHead() const {
+ return m_head;
+ }
+
+ void* Allocate() {
+ m_lock.lock();
+
+ Node* ret = m_head;
+ if (ret != nullptr) {
+ m_head = ret->next;
+ }
+
+ m_lock.unlock();
+ return ret;
+ }
+
+ void Free(void* obj) {
+ m_lock.lock();
+
+ Node* node = static_cast(obj);
+ node->next = m_head;
+ m_head = node;
+
+ m_lock.unlock();
+ }
+
+private:
+ std::atomic m_head{};
+ Common::SpinLock m_lock;
+};
+
+class SlabHeapBase : protected SlabHeapImpl {
+private:
+ size_t m_obj_size{};
+ uintptr_t m_peak{};
+ uintptr_t m_start{};
+ uintptr_t m_end{};
+
+public:
+ constexpr SlabHeapBase() = default;
+
+ bool Contains(uintptr_t address) const {
+ return m_start <= address && address < m_end;
+ }
+
+ void Initialize(size_t obj_size, void* memory, size_t memory_size) {
+ // Ensure we don't initialize a slab using null memory.
+ ASSERT(memory != nullptr);
+
+ // Set our object size.
+ m_obj_size = obj_size;
+
+ // Initialize the base allocator.
+ SlabHeapImpl::Initialize();
+
+ // Set our tracking variables.
+ const size_t num_obj = (memory_size / obj_size);
+ m_start = reinterpret_cast(memory);
+ m_end = m_start + num_obj * obj_size;
+ m_peak = m_start;
+
+ // Free the objects.
+ u8* cur = reinterpret_cast(m_end);
+
+ for (size_t i = 0; i < num_obj; i++) {
+ cur -= obj_size;
+ SlabHeapImpl::Free(cur);
+ }
+ }
+
+ size_t GetSlabHeapSize() const {
+ return (m_end - m_start) / this->GetObjectSize();
+ }
+
+ size_t GetObjectSize() const {
+ return m_obj_size;
+ }
+
+ void* Allocate() {
+ void* obj = SlabHeapImpl::Allocate();
+ return obj;
+ }
+
+ void Free(void* obj) {
+ // Don't allow freeing an object that wasn't allocated from this heap.
+ const bool contained = this->Contains(reinterpret_cast(obj));
+ ASSERT(contained);
+ SlabHeapImpl::Free(obj);
+ }
+
+ size_t GetObjectIndex(const void* obj) const {
+ return (reinterpret_cast(obj) - m_start) / this->GetObjectSize();
+ }
+
+ size_t GetPeakIndex() const {
+ return this->GetObjectIndex(reinterpret_cast(m_peak));
+ }
+
+ uintptr_t GetSlabHeapAddress() const {
+ return m_start;
+ }
+
+ size_t GetNumRemaining() const {
+ // Only calculate the number of remaining objects under debug configuration.
+ return 0;
+ }
+};
+
+template
+class SlabHeap final : public SlabHeapBase {
+private:
+ using BaseHeap = SlabHeapBase;
+
+public:
+ constexpr SlabHeap() = default;
+
+ void Initialize(void* memory, size_t memory_size) {
+ BaseHeap::Initialize(sizeof(T), memory, memory_size);
+ }
+
+ T* Allocate() {
+ T* obj = static_cast(BaseHeap::Allocate());
+
+ if (obj != nullptr) [[likely]] {
+ std::construct_at(obj);
+ }
+ return obj;
+ }
+
+ void Free(T* obj) {
+ BaseHeap::Free(obj);
+ }
+
+ size_t GetObjectIndex(const T* obj) const {
+ return BaseHeap::GetObjectIndex(obj);
+ }
+};
+
+} // namespace Common
diff --git a/src/common/slot_vector.h b/src/common/slot_vector.h
index 36e647971..d4ac51361 100644
--- a/src/common/slot_vector.h
+++ b/src/common/slot_vector.h
@@ -3,10 +3,7 @@
#pragma once
-#include
-#include
#include
-#include
#include
#include
#include "common/assert.h"
diff --git a/src/common/spin_lock.cpp b/src/common/spin_lock.cpp
new file mode 100755
index 000000000..9d4cfe36b
--- /dev/null
+++ b/src/common/spin_lock.cpp
@@ -0,0 +1,53 @@
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/spin_lock.h"
+
+#if _MSC_VER
+#include
+#if _M_AMD64
+#define __x86_64__ 1
+#endif
+#if _M_ARM64
+#define __aarch64__ 1
+#endif
+#else
+#if __x86_64__
+#include
+#endif
+#endif
+
+namespace {
+
+void ThreadPause() {
+#if __x86_64__
+ _mm_pause();
+#elif __aarch64__ && _MSC_VER
+ __yield();
+#elif __aarch64__
+ asm("yield");
+#endif
+}
+
+} // Anonymous namespace
+
+namespace Common {
+
+void SpinLock::lock() {
+ while (lck.test_and_set(std::memory_order_acquire)) {
+ ThreadPause();
+ }
+}
+
+void SpinLock::unlock() {
+ lck.clear(std::memory_order_release);
+}
+
+bool SpinLock::try_lock() {
+ if (lck.test_and_set(std::memory_order_acquire)) {
+ return false;
+ }
+ return true;
+}
+
+} // namespace Common
diff --git a/src/common/spin_lock.h b/src/common/spin_lock.h
new file mode 100755
index 000000000..3229a8c6a
--- /dev/null
+++ b/src/common/spin_lock.h
@@ -0,0 +1,33 @@
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include
+
+namespace Common {
+
+/**
+ * SpinLock class
+ * a lock similar to mutex that forces a thread to spin wait instead calling the
+ * supervisor. Should be used on short sequences of code.
+ */
+class SpinLock {
+public:
+ SpinLock() = default;
+
+ SpinLock(const SpinLock&) = delete;
+ SpinLock& operator=(const SpinLock&) = delete;
+
+ SpinLock(SpinLock&&) = delete;
+ SpinLock& operator=(SpinLock&&) = delete;
+
+ void lock();
+ void unlock();
+ [[nodiscard]] bool try_lock();
+
+private:
+ std::atomic_flag lck = ATOMIC_FLAG_INIT;
+};
+
+} // namespace Common
diff --git a/src/core/address_space.cpp b/src/core/address_space.cpp
index 8ba99e32d..24f5e9f87 100644
--- a/src/core/address_space.cpp
+++ b/src/core/address_space.cpp
@@ -1,13 +1,14 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include