Commit 867024da authored by KO Myung-Hun's avatar KO Myung-Hun Committed by Rémi Denis-Courmont

os2: thread: implement vlc_cond_signal() correctly

Signed-off-by: default avatarRémi Denis-Courmont <remi@remlab.net>
parent c8c7d545
...@@ -111,9 +111,12 @@ typedef struct ...@@ -111,9 +111,12 @@ typedef struct
typedef struct typedef struct
{ {
HEV hev; HEV hev;
unsigned waiters;
HEV hevAck;
unsigned signaled;
unsigned clock; unsigned clock;
} vlc_cond_t; } vlc_cond_t;
#define VLC_STATIC_COND { 0, 0 } #define VLC_STATIC_COND { NULLHANDLE, 0, NULLHANDLE, 0, 0 }
#define LIBVLC_NEED_SEMAPHORE #define LIBVLC_NEED_SEMAPHORE
#define LIBVLC_NEED_RWLOCK #define LIBVLC_NEED_RWLOCK
typedef struct vlc_threadvar *vlc_threadvar_t; typedef struct vlc_threadvar *vlc_threadvar_t;
......
...@@ -45,6 +45,8 @@ ...@@ -45,6 +45,8 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/select.h> #include <sys/select.h>
#include <386/builtin.h>
static vlc_threadvar_t thread_key; static vlc_threadvar_t thread_key;
/** /**
...@@ -261,9 +263,12 @@ enum ...@@ -261,9 +263,12 @@ enum
static void vlc_cond_init_common (vlc_cond_t *p_condvar, unsigned clock) static void vlc_cond_init_common (vlc_cond_t *p_condvar, unsigned clock)
{ {
/* Create a manual-reset event (manual reset is needed for broadcast). */ if (DosCreateEventSem (NULL, &p_condvar->hev, 0, FALSE) ||
if (DosCreateEventSem (NULL, &p_condvar->hev, 0, FALSE)) DosCreateEventSem (NULL, &p_condvar->hevAck, 0, FALSE))
abort(); abort();
p_condvar->waiters = 0;
p_condvar->signaled = 0;
p_condvar->clock = clock; p_condvar->clock = clock;
} }
...@@ -280,6 +285,7 @@ void vlc_cond_init_daytime (vlc_cond_t *p_condvar) ...@@ -280,6 +285,7 @@ void vlc_cond_init_daytime (vlc_cond_t *p_condvar)
void vlc_cond_destroy (vlc_cond_t *p_condvar) void vlc_cond_destroy (vlc_cond_t *p_condvar)
{ {
DosCloseEventSem( p_condvar->hev ); DosCloseEventSem( p_condvar->hev );
DosCloseEventSem( p_condvar->hevAck );
} }
void vlc_cond_signal (vlc_cond_t *p_condvar) void vlc_cond_signal (vlc_cond_t *p_condvar)
...@@ -287,8 +293,28 @@ void vlc_cond_signal (vlc_cond_t *p_condvar) ...@@ -287,8 +293,28 @@ void vlc_cond_signal (vlc_cond_t *p_condvar)
if (!p_condvar->hev) if (!p_condvar->hev)
return; return;
/* This is suboptimal but works. */ if (!__atomic_cmpxchg32 (&p_condvar->waiters, 0, 0))
vlc_cond_broadcast (p_condvar); {
ULONG ulPost;
__atomic_xchg (&p_condvar->signaled, 1);
DosPostEventSem (p_condvar->hev);
DosWaitEventSem (p_condvar->hevAck, SEM_INDEFINITE_WAIT);
DosResetEventSem (p_condvar->hevAck, &ulPost);
while (ulPost-- > 0)
__atomic_decrement (&p_condvar->waiters);
/* Already timed out ? */
if (__atomic_cmpxchg32 (&p_condvar->waiters, 0, 0) &&
__atomic_cmpxchg32 (&p_condvar->signaled, 1, 1))
{
/* Clear signaled status */
__atomic_xchg (&p_condvar->signaled, 0);
DosResetEventSem (p_condvar->hev, &ulPost);
}
}
} }
void vlc_cond_broadcast (vlc_cond_t *p_condvar) void vlc_cond_broadcast (vlc_cond_t *p_condvar)
...@@ -296,39 +322,55 @@ void vlc_cond_broadcast (vlc_cond_t *p_condvar) ...@@ -296,39 +322,55 @@ void vlc_cond_broadcast (vlc_cond_t *p_condvar)
if (!p_condvar->hev) if (!p_condvar->hev)
return; return;
/* Wake all threads up (as the event HANDLE has manual reset) */ while (!__atomic_cmpxchg32 (&p_condvar->waiters, 0, 0))
DosPostEventSem( p_condvar->hev ); vlc_cond_signal (p_condvar);
} }
void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex) static int vlc_cond_wait_common (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
ULONG ulTimeout)
{ {
ULONG ulPost; ULONG ulPost;
ULONG rc; ULONG rc;
if (!p_condvar->hev) __atomic_increment (&p_condvar->waiters);
{ /* FIXME FIXME FIXME */
msleep (50000);
return;
}
do do
{ {
vlc_testcancel(); vlc_testcancel();
vlc_mutex_unlock (p_mutex); vlc_mutex_unlock (p_mutex);
rc = vlc_WaitForSingleObject( p_condvar->hev, SEM_INDEFINITE_WAIT );
do
{
rc = vlc_WaitForSingleObject( p_condvar->hev, ulTimeout );
if (rc == NO_ERROR)
DosResetEventSem (p_condvar->hev, &ulPost);
} while (rc == NO_ERROR &&
__atomic_cmpxchg32 (&p_condvar->signaled, 0, 1) == 0);
DosPostEventSem (p_condvar->hevAck);
vlc_mutex_lock (p_mutex); vlc_mutex_lock (p_mutex);
} while( rc == ERROR_INTERRUPT ); } while( rc == ERROR_INTERRUPT );
DosResetEventSem( p_condvar->hev, &ulPost ); return rc ? ETIMEDOUT : 0;
}
void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
{
if (!p_condvar->hev)
{ /* FIXME FIXME FIXME */
msleep (50000);
return;
}
vlc_cond_wait_common (p_condvar, p_mutex, SEM_INDEFINITE_WAIT);
} }
int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex, int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
mtime_t deadline) mtime_t deadline)
{ {
ULONG ulTimeout; ULONG ulTimeout;
ULONG ulPost;
ULONG rc;
if (!p_condvar->hev) if (!p_condvar->hev)
{ /* FIXME FIXME FIXME */ { /* FIXME FIXME FIXME */
...@@ -336,10 +378,6 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex, ...@@ -336,10 +378,6 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
return 0; return 0;
} }
do
{
vlc_testcancel();
mtime_t total; mtime_t total;
switch (p_condvar->clock) switch (p_condvar->clock)
{ {
...@@ -363,14 +401,7 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex, ...@@ -363,14 +401,7 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
ulTimeout = ( total > 0x7fffffff ) ? 0x7fffffff : total; ulTimeout = ( total > 0x7fffffff ) ? 0x7fffffff : total;
vlc_mutex_unlock (p_mutex); return vlc_cond_wait_common (p_condvar, p_mutex, ulTimeout);
rc = vlc_WaitForSingleObject( p_condvar->hev, ulTimeout );
vlc_mutex_lock (p_mutex);
} while( rc == ERROR_INTERRUPT );
DosResetEventSem( p_condvar->hev, &ulPost );
return rc ? ETIMEDOUT : 0;
} }
/*** Thread-specific variables (TLS) ***/ /*** Thread-specific variables (TLS) ***/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment