[MPlayer-dev-eng] [PATCH] Support CineForm DirectShow codec

Steinar H. Gunderson sgunderson at bigfoot.com
Sun Feb 21 16:54:44 CET 2010


On Tue, Feb 09, 2010 at 07:26:24PM +0100, Steinar H. Gunderson wrote:
> What _can_ be done is to still have a single mutex, use it to protect the lock
> count/owner only (ie., don't actually hold the mutex after
> EnterCriticalSection has completed), and then if the mutex is not free, wait
> for a signal to be sent. This is pretty much the same as the semaphore
> implementation today, IIRC, and should work. It will almost certainly be
> slower and more tricky to get right than just using a recursive mutex,
> though, but I don't know if that's an issue.

Here's an implementation. It's only very lightly tested, but appears to be
correct to me -- cs->lock_count and cs->id are always accessed under
cs->mutex only. (It doesn't fix the unsynchronized accesses to mlist, but we
can take those in a separate patch.)

diff -ur orig/mplayer-export-2010-02-21/loader/win32.c mplayer-export-2010-02-21/loader/win32.c
--- orig/mplayer-export-2010-02-21/loader/win32.c	2010-02-19 11:22:29.000000000 +0100
+++ mplayer-export-2010-02-21/loader/win32.c	2010-02-21 16:43:49.000000000 +0100
@@ -348,7 +348,8 @@
 {
     pthread_t id;
     pthread_mutex_t mutex;
-    int locked;
+    pthread_cond_t unlocked;
+    int lock_count;
     long deadbeef;
 };
 
@@ -1329,7 +1330,8 @@
 	    return;
 	}
 	pthread_mutex_init(&cs->mutex, NULL);
-	cs->locked = 0;
+	pthread_cond_init(&cs->unlocked, NULL);
+	cs->lock_count = 0;
 	critsecs_list[i].cs_win = c;
 	critsecs_list[i].cs_unix = cs;
 	dbgprintf("InitializeCriticalSection -> itemno=%d, cs_win=%p, cs_unix=%p\n",
@@ -1340,7 +1342,8 @@
 	struct CRITSECT* cs = mreq_private(sizeof(struct CRITSECT) + sizeof(CRITICAL_SECTION),
 					   0, AREATYPE_CRITSECT);
 	pthread_mutex_init(&cs->mutex, NULL);
-	cs->locked=0;
+	pthread_cond_init(&cs->unlocked, NULL);
+	cs->lock_count = 0;
         cs->deadbeef = 0xdeadbeef;
 	*(void**)c = cs;
     }
@@ -1372,12 +1375,17 @@
 #endif
 	dbgprintf("Win32 Warning: Accessed uninitialized Critical Section (%p)!\n", c);
     }
-    if(cs->locked)
-	if(cs->id==pthread_self())
-	    return;
     pthread_mutex_lock(&(cs->mutex));
-    cs->locked=1;
-    cs->id=pthread_self();
+    if (cs->lock_count > 0 && cs->id == pthread_self()) {
+        cs->lock_count++;
+    } else {
+        while (cs->lock_count != 0) {
+            pthread_cond_wait(&(cs->unlocked), &(cs->mutex));
+        }
+        cs->lock_count = 1;
+        cs->id = pthread_self();
+    }
+    pthread_mutex_unlock(&(cs->mutex));
     return;
 }
 static void WINAPI expLeaveCriticalSection(CRITICAL_SECTION* c)
@@ -1394,13 +1402,16 @@
 	dbgprintf("Win32 Warning: Leaving uninitialized Critical Section %p!!\n", c);
 	return;
     }
-    if (cs->locked)
-    {
-	cs->locked=0;
-	pthread_mutex_unlock(&(cs->mutex));
-    }
-    else
+    pthread_mutex_lock(&(cs->mutex));
+    if (cs->lock_count == 0) {
 	dbgprintf("Win32 Warning: Unlocking unlocked Critical Section %p!!\n", c);
+    } else {
+        cs->lock_count--;
+    }
+    if (cs->lock_count == 0) {
+        pthread_cond_signal(&(cs->unlocked));
+    }
+    pthread_mutex_unlock(&(cs->mutex));
     return;
 }
 
@@ -1422,14 +1433,16 @@
 	return;
     }
 
-    if (cs->locked)
+    pthread_mutex_lock(&(cs->mutex));
+    if (cs->lock_count > 0)
     {
-	dbgprintf("Win32 Warning: Deleting unlocked Critical Section %p!!\n", c);
-	pthread_mutex_unlock(&(cs->mutex));
+	dbgprintf("Win32 Warning: Deleting locked Critical Section %p!!\n", c);
     }
+    pthread_mutex_unlock(&(cs->mutex));
 
 #ifndef GARBAGE
     pthread_mutex_destroy(&(cs->mutex));
+    pthread_cond_destroy(&(cs->unlocked));
     // released by GarbageCollector in my_relase otherwise
 #endif
     my_release(cs);

/* Steinar */
-- 
Homepage: http://www.sesse.net/



More information about the MPlayer-dev-eng mailing list