Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 825ea94a authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Codec2 vndk: clear pending lock by a dead client process" into main am:...

Merge "Codec2 vndk: clear pending lock by a dead client process" into main am: b72144c5 am: 2d69ac78

Original change: https://android-review.googlesource.com/c/platform/frameworks/av/+/2853014



Change-Id: If0fe777601df3b8e89f2354cb46b925188850a24
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents fe795dc9 2d69ac78
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -122,6 +122,11 @@ struct C2SyncVariables {
     */
     */
    void invalidate();
    void invalidate();


    /**
     * If a dead process holds the lock, clear the lock.
     */
    void clearLockIfNecessary();

    C2SyncVariables() {}
    C2SyncVariables() {}


private:
private:
@@ -140,6 +145,11 @@ private:
     */
     */
    int wait();
    int wait();


    /**
     * try lock for the specified duration.
     */
    bool tryLockFor(size_t ms);

    std::atomic<uint32_t> mLock;
    std::atomic<uint32_t> mLock;
    std::atomic<uint32_t> mCond;
    std::atomic<uint32_t> mCond;
    int32_t mMaxDequeueCount;
    int32_t mMaxDequeueCount;
+7 −0
Original line number Original line Diff line number Diff line
@@ -802,6 +802,13 @@ public:
        if (oldVar) {
        if (oldVar) {
            oldVar->invalidate();
            oldVar->invalidate();
        }
        }
        // invalidate pending lock from a dead process if any
        if (syncVar) {
            syncVar->clearLockIfNecessary();
        }
        if (oldVar) {
            oldVar->clearLockIfNecessary();
        }
    }
    }


private:
private:
+74 −0
Original line number Original line Diff line number Diff line
@@ -26,6 +26,33 @@
#include <chrono>
#include <chrono>
#include <C2SurfaceSyncObj.h>
#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 = {
const native_handle_t C2SurfaceSyncMemory::HandleSyncMem::cHeader = {
    C2SurfaceSyncMemory::HandleSyncMem::version,
    C2SurfaceSyncMemory::HandleSyncMem::version,
    C2SurfaceSyncMemory::HandleSyncMem::numFds,
    C2SurfaceSyncMemory::HandleSyncMem::numFds,
@@ -289,6 +316,21 @@ void C2SyncVariables::invalidate() {
    (void) syscall(__NR_futex, &mCond, FUTEX_REQUEUE, INT_MAX, (void *)INT_MAX, &mLock, 0);
    (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() {
int C2SyncVariables::signal() {
    mCond++;
    mCond++;


@@ -313,3 +355,35 @@ int C2SyncVariables::wait() {
    }
    }
    return 0;
    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;
}