[09/16] winecoreaudio: Lift mutex lock/unlock out of wodHelper_PlayPtrNext to caller.

Ken Thomases ken at codeweavers.com
Thu Dec 21 03:49:07 CST 2006


The render callback was the only caller and it was already holding the mutex.
It had to release it just to call PlayPtrNext and then immediately grab it
again.  So instead, it now just holds it across the call.

This allows for the elimination of the nextPtr variable.  Its only purpose
was to communicate the need to call PlayPtrNext from inside the critical
section to the outside.  Now just call PlayPtrNext directly.

While I was there, I moved the setting of needNotify flag so it is only set
when a wave header has been exhausted.  This eliminates unnecessary and
expensive calls to wodHelper_NotifyCompletions.

These changes made it so that the entire while(dataNeeded) loop body was
guarded by the mutex.  Instead of grabbing it and releasing it on each pass
through the loop, just hold it around the loop.  This doesn't introduce a
risk of starving other threads, because the loop is of bounded duration and
doesn't do anything "slow".
---
  dlls/winmm/winecoreaudio/audio.c |   27 +++++++++------------------
  1 files changed, 9 insertions(+), 18 deletions(-)
-------------- next part --------------
diff --git a/dlls/winmm/winecoreaudio/audio.c b/dlls/winmm/winecoreaudio/audio.c
index d11712f..4c99760 100644
--- a/dlls/winmm/winecoreaudio/audio.c
+++ b/dlls/winmm/winecoreaudio/audio.c
@@ -897,14 +897,13 @@ static void wodHelper_CheckForLoopBegin(
 * 				wodHelper_PlayPtrNext	        [internal]
 *
 * Advance the play pointer to the next waveheader, looping if required.
+* This is called with the WAVEOUT lock held.
 * Call from AudioUnit IO thread can't use Wine debug channels.
 */
 static void wodHelper_PlayPtrNext(WINE_WAVEOUT* wwo)
 {
     BOOL didLoopBack = FALSE;
 
-    pthread_mutex_lock(&wwo->lock);
-    
     wwo->dwPartialOffset = 0;
     if ((wwo->lpPlayPtr->dwFlags & WHDR_ENDLOOP) && wwo->lpLoopPtr)
     {
@@ -931,8 +930,6 @@ static void wodHelper_PlayPtrNext(WINE_W
         else
             wodHelper_CheckForLoopBegin(wwo);
     }
-    
-    pthread_mutex_unlock(&wwo->lock);
 }
 
 /* if force is TRUE then notify the client that all the headers were completed
@@ -1407,16 +1404,15 @@ OSStatus CoreAudio_woAudioUnitIOProc(voi
 {
     UInt32 buffer;
     WINE_WAVEOUT *wwo = (WINE_WAVEOUT *) inRefCon;
-    int nextPtr = 0;
     int needNotify = 0;
 
     unsigned int dataNeeded = ioData->mBuffers[0].mDataByteSize;
     unsigned int dataProvided = 0;
 
+    pthread_mutex_lock(&wwo->lock);
+
     while (dataNeeded > 0)
     {
-        pthread_mutex_lock(&wwo->lock);
-
         if (wwo->state == WINE_WS_PLAYING && wwo->lpPlayPtr)
         {
             unsigned int available = wwo->lpPlayPtr->dwBufferLength - wwo->dwPartialOffset;
@@ -1439,9 +1435,10 @@ OSStatus CoreAudio_woAudioUnitIOProc(voi
             }
 
             if (available == 0)
-                nextPtr = 1;
-
-            needNotify = 1;
+            {
+                wodHelper_PlayPtrNext(wwo);
+                needNotify = 1;
+            }
         }
         else
         {
@@ -1449,16 +1446,10 @@ OSStatus CoreAudio_woAudioUnitIOProc(voi
             dataProvided += dataNeeded;
             dataNeeded = 0;
         }
-
-        pthread_mutex_unlock(&wwo->lock);
-
-        if (nextPtr)
-        {
-            wodHelper_PlayPtrNext(wwo);
-            nextPtr = 0;
-        }
     }
 
+    pthread_mutex_unlock(&wwo->lock);
+
     /* We only fill buffer 0.  Set any others that might be requested to 0. */
     for (buffer = 1; buffer < ioData->mNumberBuffers; buffer++)
     {


More information about the wine-patches mailing list