summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorZephyron <zephyron@citron-emu.org>2025-01-26 14:21:36 +1000
committerZephyron <zephyron@citron-emu.org>2025-01-26 14:21:36 +1000
commita5d62fa4ec854174ddbb279e9f826ecc3bc470f0 (patch)
tree6042cf08f9d023ff45f3c994265b0c59806ecfa9 /src/core
parenta6063bbd64ffe5ab823c7f0f75fe3eddb4ad2e90 (diff)
nvnflinger: Implement reference counting for binder objects
Implements proper reference counting for binder objects based on the official documentation. This adds both weak and strong reference counting support to the IBinder interface and its implementations (BufferQueueProducer and BufferQueueConsumer). The implementation follows the documented behavior where: - type 0 affects weak references - type 1 affects strong references - During initialization: {addval=1, type=0} followed by {addval=1, type=1} - For onFirstRef: {addval=1, type=1} - For onLastStrongRef: {addval=-1, type=1} Reference counters are implemented using std::atomic to ensure thread safety. REFS: switchbrew.org/wiki/Nvnflinger_services#AdjustRefcount
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/service/nvnflinger/binder.h18
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.h11
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_producer.h11
-rw-r--r--src/core/hle/service/nvnflinger/hos_binder_driver.cpp17
4 files changed, 56 insertions, 1 deletions
diff --git a/src/core/hle/service/nvnflinger/binder.h b/src/core/hle/service/nvnflinger/binder.h
index 124accb94..f9f326e3b 100644
--- a/src/core/hle/service/nvnflinger/binder.h
+++ b/src/core/hle/service/nvnflinger/binder.h
@@ -26,6 +26,24 @@ public:
virtual void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply,
u32 flags) = 0;
virtual Kernel::KReadableEvent* GetNativeHandle(u32 type_id) = 0;
+
+ virtual void AdjustWeakRefcount(s32 addval) = 0;
+ virtual void AdjustStrongRefcount(s32 addval) = 0;
+};
+
+class Binder {
+public:
+ void AdjustWeakRefcount(s32 addval) {
+ m_weak_ref_count += addval;
+ }
+
+ void AdjustStrongRefcount(s32 addval) {
+ m_strong_ref_count += addval;
+ }
+
+private:
+ std::atomic<s32> m_weak_ref_count{};
+ std::atomic<s32> m_strong_ref_count{};
};
} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
index a9226f1c3..7549ebe96 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
+++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h
@@ -8,6 +8,7 @@
#include <chrono>
#include <memory>
+#include <atomic>
#include "common/common_types.h"
#include "core/hle/service/nvnflinger/binder.h"
@@ -36,9 +37,19 @@ public:
Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override;
+ void AdjustWeakRefcount(s32 addval) override {
+ m_weak_ref_count += addval;
+ }
+
+ void AdjustStrongRefcount(s32 addval) override {
+ m_strong_ref_count += addval;
+ }
+
private:
std::shared_ptr<BufferQueueCore> core;
BufferQueueDefs::SlotsType& slots;
+ std::atomic<s32> m_weak_ref_count{};
+ std::atomic<s32> m_strong_ref_count{};
};
} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h
index 048523514..6df0b9014 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h
+++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h
@@ -9,6 +9,7 @@
#include <condition_variable>
#include <memory>
#include <mutex>
+#include <atomic>
#include "common/common_funcs.h"
#include "core/hle/service/nvdrv/nvdata.h"
@@ -52,6 +53,14 @@ public:
Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override;
+ void AdjustWeakRefcount(s32 addval) override {
+ m_weak_ref_count += addval;
+ }
+
+ void AdjustStrongRefcount(s32 addval) override {
+ m_strong_ref_count += addval;
+ }
+
public:
Status RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf);
Status SetBufferCount(s32 buffer_count);
@@ -87,6 +96,8 @@ private:
std::condition_variable_any callback_condition;
Service::Nvidia::NvCore::NvMap& nvmap;
+ std::atomic<s32> m_weak_ref_count{};
+ std::atomic<s32> m_strong_ref_count{};
};
} // namespace Service::android
diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp
index 8629a2e89..8b1ac3ed8 100644
--- a/src/core/hle/service/nvnflinger/hos_binder_driver.cpp
+++ b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp
@@ -5,6 +5,7 @@
#include "core/hle/service/nvnflinger/binder.h"
#include "core/hle/service/nvnflinger/hos_binder_driver.h"
#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
+#include <atomic>
namespace Service::Nvnflinger {
@@ -40,7 +41,21 @@ Result IHOSBinderDriver::TransactParcel(s32 binder_id, u32 transaction_id,
}
Result IHOSBinderDriver::AdjustRefcount(s32 binder_id, s32 addval, s32 type) {
- LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={}, type={}", binder_id, addval, type);
+ LOG_DEBUG(Service_VI, "called id={}, addval={}, type={}", binder_id, addval, type);
+
+ const auto binder = m_server->TryGetBinder(binder_id);
+ R_SUCCEED_IF(binder == nullptr);
+
+ // type 0 = weak reference, type 1 = strong reference
+ if (type == 0) {
+ binder->AdjustWeakRefcount(addval);
+ } else if (type == 1) {
+ binder->AdjustStrongRefcount(addval);
+ } else {
+ LOG_ERROR(Service_VI, "Invalid refcount type {}", type);
+ R_THROW(Kernel::ResultInvalidArgument);
+ }
+
R_SUCCEED();
}