Loading media/codec2/vndk/include/C2SurfaceSyncObj.h +10 −0 Original line number Diff line number Diff line Loading @@ -122,6 +122,11 @@ struct C2SyncVariables { */ void invalidate(); /** * If a dead process holds the lock, clear the lock. */ void clearLockIfNecessary(); C2SyncVariables() {} private: Loading @@ -140,6 +145,11 @@ private: */ int wait(); /** * try lock for the specified duration. */ bool tryLockFor(size_t ms); std::atomic<uint32_t> mLock; std::atomic<uint32_t> mCond; int32_t mMaxDequeueCount; Loading media/codec2/vndk/platform/C2BqBuffer.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -802,6 +802,13 @@ public: if (oldVar) { oldVar->invalidate(); } // invalidate pending lock from a dead process if any if (syncVar) { syncVar->clearLockIfNecessary(); } if (oldVar) { oldVar->clearLockIfNecessary(); } } private: Loading media/codec2/vndk/platform/C2SurfaceSyncObj.cpp +74 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,33 @@ #include <chrono> #include <C2SurfaceSyncObj.h> namespace { static inline void timespec_add_ms(timespec& ts, size_t ms) { constexpr int kNanoSecondsPerSec = 1000000000; ts.tv_sec += ms / 1000; ts.tv_nsec += (ms % 1000) * 1000000; if (ts.tv_nsec >= kNanoSecondsPerSec) { ts.tv_sec++; ts.tv_nsec -= kNanoSecondsPerSec; } } /* * lhs < rhs: return <0 * lhs == rhs: return 0 * lhs > rhs: return >0 */ static inline int timespec_compare(const timespec& lhs, const timespec& rhs) { if (lhs.tv_sec < rhs.tv_sec) { return -1; } if (lhs.tv_sec > rhs.tv_sec) { return 1; } return lhs.tv_nsec - rhs.tv_nsec; } } const native_handle_t C2SurfaceSyncMemory::HandleSyncMem::cHeader = { C2SurfaceSyncMemory::HandleSyncMem::version, C2SurfaceSyncMemory::HandleSyncMem::numFds, Loading Loading @@ -289,6 +316,21 @@ void C2SyncVariables::invalidate() { (void) syscall(__NR_futex, &mCond, FUTEX_REQUEUE, INT_MAX, (void *)INT_MAX, &mLock, 0); } void C2SyncVariables::clearLockIfNecessary() { // Note: After waiting for 30ms without acquiring the lock, // we will consider the lock is dangling. // Since the lock duration is very brief to manage the counter, // waiting for 30ms should be more than enough. constexpr size_t kTestLockDurationMs = 30; bool locked = tryLockFor(kTestLockDurationMs); unlock(); if (!locked) { ALOGW("A dead process might be holding the lock"); } } int C2SyncVariables::signal() { mCond++; Loading @@ -313,3 +355,35 @@ int C2SyncVariables::wait() { } return 0; } bool C2SyncVariables::tryLockFor(size_t ms) { uint32_t old = FUTEX_UNLOCKED; if (mLock.compare_exchange_strong(old, FUTEX_LOCKED_UNCONTENDED)) { return true; } if (old == FUTEX_LOCKED_UNCONTENDED) { old = mLock.exchange(FUTEX_LOCKED_CONTENDED); } struct timespec wait{ static_cast<time_t>(ms / 1000), static_cast<long>((ms % 1000) * 1000000)}; struct timespec end; clock_gettime(CLOCK_REALTIME, &end); timespec_add_ms(end, ms); while (old != FUTEX_UNLOCKED) { // case of EINTR being returned; (void)syscall(__NR_futex, &mLock, FUTEX_WAIT, FUTEX_LOCKED_CONTENDED, &wait, NULL, 0); old = mLock.exchange(FUTEX_LOCKED_CONTENDED); struct timespec now; clock_gettime(CLOCK_REALTIME, &now); if (timespec_compare(now, end) >= 0) { break; } } return old == FUTEX_UNLOCKED; } Loading
media/codec2/vndk/include/C2SurfaceSyncObj.h +10 −0 Original line number Diff line number Diff line Loading @@ -122,6 +122,11 @@ struct C2SyncVariables { */ void invalidate(); /** * If a dead process holds the lock, clear the lock. */ void clearLockIfNecessary(); C2SyncVariables() {} private: Loading @@ -140,6 +145,11 @@ private: */ int wait(); /** * try lock for the specified duration. */ bool tryLockFor(size_t ms); std::atomic<uint32_t> mLock; std::atomic<uint32_t> mCond; int32_t mMaxDequeueCount; Loading
media/codec2/vndk/platform/C2BqBuffer.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -802,6 +802,13 @@ public: if (oldVar) { oldVar->invalidate(); } // invalidate pending lock from a dead process if any if (syncVar) { syncVar->clearLockIfNecessary(); } if (oldVar) { oldVar->clearLockIfNecessary(); } } private: Loading
media/codec2/vndk/platform/C2SurfaceSyncObj.cpp +74 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,33 @@ #include <chrono> #include <C2SurfaceSyncObj.h> namespace { static inline void timespec_add_ms(timespec& ts, size_t ms) { constexpr int kNanoSecondsPerSec = 1000000000; ts.tv_sec += ms / 1000; ts.tv_nsec += (ms % 1000) * 1000000; if (ts.tv_nsec >= kNanoSecondsPerSec) { ts.tv_sec++; ts.tv_nsec -= kNanoSecondsPerSec; } } /* * lhs < rhs: return <0 * lhs == rhs: return 0 * lhs > rhs: return >0 */ static inline int timespec_compare(const timespec& lhs, const timespec& rhs) { if (lhs.tv_sec < rhs.tv_sec) { return -1; } if (lhs.tv_sec > rhs.tv_sec) { return 1; } return lhs.tv_nsec - rhs.tv_nsec; } } const native_handle_t C2SurfaceSyncMemory::HandleSyncMem::cHeader = { C2SurfaceSyncMemory::HandleSyncMem::version, C2SurfaceSyncMemory::HandleSyncMem::numFds, Loading Loading @@ -289,6 +316,21 @@ void C2SyncVariables::invalidate() { (void) syscall(__NR_futex, &mCond, FUTEX_REQUEUE, INT_MAX, (void *)INT_MAX, &mLock, 0); } void C2SyncVariables::clearLockIfNecessary() { // Note: After waiting for 30ms without acquiring the lock, // we will consider the lock is dangling. // Since the lock duration is very brief to manage the counter, // waiting for 30ms should be more than enough. constexpr size_t kTestLockDurationMs = 30; bool locked = tryLockFor(kTestLockDurationMs); unlock(); if (!locked) { ALOGW("A dead process might be holding the lock"); } } int C2SyncVariables::signal() { mCond++; Loading @@ -313,3 +355,35 @@ int C2SyncVariables::wait() { } return 0; } bool C2SyncVariables::tryLockFor(size_t ms) { uint32_t old = FUTEX_UNLOCKED; if (mLock.compare_exchange_strong(old, FUTEX_LOCKED_UNCONTENDED)) { return true; } if (old == FUTEX_LOCKED_UNCONTENDED) { old = mLock.exchange(FUTEX_LOCKED_CONTENDED); } struct timespec wait{ static_cast<time_t>(ms / 1000), static_cast<long>((ms % 1000) * 1000000)}; struct timespec end; clock_gettime(CLOCK_REALTIME, &end); timespec_add_ms(end, ms); while (old != FUTEX_UNLOCKED) { // case of EINTR being returned; (void)syscall(__NR_futex, &mLock, FUTEX_WAIT, FUTEX_LOCKED_CONTENDED, &wait, NULL, 0); old = mLock.exchange(FUTEX_LOCKED_CONTENDED); struct timespec now; clock_gettime(CLOCK_REALTIME, &now); if (timespec_compare(now, end) >= 0) { break; } } return old == FUTEX_UNLOCKED; }