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
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 681f557..ef5bb8d 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -94,8 +94,9 @@
                                             // parameter
                                             // 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()
+#define CBLK_FUTEX_WAKE 1               // if event flag bit is set, then a deferred wake is pending
 
 private:
 
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index f034164..4b7f368 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -207,15 +207,15 @@
             ts = NULL;
             break;
         }
-        int32_t old = android_atomic_dec(&cblk->mFutex);
-        if (old <= 0) {
+        int32_t old = android_atomic_and(~CBLK_FUTEX_WAKE, &cblk->mFutex);
+        if (!(old & CBLK_FUTEX_WAKE)) {
             int rc;
             if (measure && !beforeIsValid) {
                 clock_gettime(CLOCK_MONOTONIC, &before);
                 beforeIsValid = true;
             }
             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
             if (measure) {
                 struct timespec after;
@@ -484,9 +484,8 @@
     }
     if (!mDeferWake && 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_inc(&cblk->mFutex);
-        if (old == -1) {
+        int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
+        if (!(old & CBLK_FUTEX_WAKE)) {
             (void) __futex_syscall3(&cblk->mFutex,
                     mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1);
         }