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

Commit 0d09a9be authored by Glenn Kasten's avatar Glenn Kasten
Browse files

Use mFutex as an event flag rather than semaphore

An event flag can be more fault-tolerant in case of loss of synchronization,
as it cannot overflow.  It also allows more bits to be used in the future.
See http://en.wikipedia.org/wiki/Event_flag

Change-Id: I01ca25d951eb263124da54bb4738f0d94ec4a48b
parent a2cf13c7
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -94,8 +94,9 @@ struct audio_track_cblk_t
                                            // parameter
                                            // parameter
                                            // renamed to "_" to detect incorrect use
                                            // renamed to "_" to detect incorrect use


    volatile    int32_t     mFutex;     // semaphore: down (P) by client,
    volatile    int32_t     mFutex;     // event flag: down (P) by client,
                                        // up (V) by server or binderDied() or interrupt()
                                        // up (V) by server or binderDied() or interrupt()
#define CBLK_FUTEX_WAKE 1               // if event flag bit is set, then a deferred wake is pending


private:
private:


+5 −6
Original line number Original line Diff line number Diff line
@@ -207,15 +207,15 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques
            ts = NULL;
            ts = NULL;
            break;
            break;
        }
        }
        int32_t old = android_atomic_dec(&cblk->mFutex);
        int32_t old = android_atomic_and(~CBLK_FUTEX_WAKE, &cblk->mFutex);
        if (old <= 0) {
        if (!(old & CBLK_FUTEX_WAKE)) {
            int rc;
            int rc;
            if (measure && !beforeIsValid) {
            if (measure && !beforeIsValid) {
                clock_gettime(CLOCK_MONOTONIC, &before);
                clock_gettime(CLOCK_MONOTONIC, &before);
                beforeIsValid = true;
                beforeIsValid = true;
            }
            }
            int ret = __futex_syscall4(&cblk->mFutex,
            int ret = __futex_syscall4(&cblk->mFutex,
                    mClientInServer ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, old - 1, ts);
                    mClientInServer ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, old & ~CBLK_FUTEX_WAKE, ts);
            // update total elapsed time spent waiting
            // update total elapsed time spent waiting
            if (measure) {
            if (measure) {
                struct timespec after;
                struct timespec after;
@@ -484,9 +484,8 @@ void ServerProxy::releaseBuffer(Buffer* buffer)
    }
    }
    if (!mDeferWake && mAvailToClient + stepCount >= minimum) {
    if (!mDeferWake && mAvailToClient + stepCount >= minimum) {
        ALOGV("mAvailToClient=%u stepCount=%u minimum=%u", mAvailToClient, stepCount, minimum);
        ALOGV("mAvailToClient=%u stepCount=%u minimum=%u", mAvailToClient, stepCount, minimum);
        // could client be sleeping, or not need this increment and counter overflows?
        int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
        int32_t old = android_atomic_inc(&cblk->mFutex);
        if (!(old & CBLK_FUTEX_WAKE)) {
        if (old == -1) {
            (void) __futex_syscall3(&cblk->mFutex,
            (void) __futex_syscall3(&cblk->mFutex,
                    mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1);
                    mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1);
        }
        }