[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