Browse Source

threads: add vlc_cond_timedwait_daytime()

This separates waiting on UTC deadline from waiting on monotonic clock.
That way, storing the reference clock in vlc_cond_t is no longer
necessary. There was only one single condition variable using the UTC
clock (in VLM), so vlc_cond_t.clock was rather wasteful.
pull/46/head
Rémi Denis-Courmont 10 years ago
parent
commit
0ef03f60c0
  1. 59
      include/vlc_threads.h
  2. 71
      src/android/thread.c
  3. 82
      src/darwin/thread.c
  4. 2
      src/input/vlm.c
  5. 1
      src/libvlccore.sym
  6. 69
      src/os2/thread.c
  7. 10
      src/posix/thread.c
  8. 58
      src/win32/thread.c

59
include/vlc_threads.h

@ -72,9 +72,8 @@ typedef struct
{ {
HANDLE semaphore; HANDLE semaphore;
LONG waiters; LONG waiters;
unsigned clock;
} vlc_cond_t; } vlc_cond_t;
#define VLC_STATIC_COND { NULL, 0, 0 } #define VLC_STATIC_COND { NULL, 0 }
typedef HANDLE vlc_sem_t; typedef HANDLE vlc_sem_t;
#define LIBVLC_NEED_RWLOCK #define LIBVLC_NEED_RWLOCK
typedef struct vlc_threadvar *vlc_threadvar_t; typedef struct vlc_threadvar *vlc_threadvar_t;
@ -124,9 +123,8 @@ typedef struct
unsigned waiters; unsigned waiters;
HEV hevAck; HEV hevAck;
unsigned signaled; unsigned signaled;
unsigned clock;
} vlc_cond_t; } vlc_cond_t;
#define VLC_STATIC_COND { NULLHANDLE, 0, NULLHANDLE, 0, 0 } #define VLC_STATIC_COND { NULLHANDLE, 0, NULLHANDLE, 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;
@ -174,14 +172,9 @@ static inline int vlc_poll (struct pollfd *fds, unsigned nfds, int timeout)
typedef struct vlc_thread *vlc_thread_t; typedef struct vlc_thread *vlc_thread_t;
#define VLC_THREAD_CANCELED NULL #define VLC_THREAD_CANCELED NULL
typedef pthread_mutex_t vlc_mutex_t; typedef pthread_mutex_t vlc_mutex_t;
#define VLC_STATIC_MUTEX PTHREAD_MUTEX_INITIALIZER #define VLC_STATIC_MUTEX PTHREAD_MUTEX_INITIALIZER
typedef struct typedef pthread_cond_t vlc_cond_t;
{ #define VLC_STATIC_COND PTHREAD_COND_INITIALIZER
pthread_cond_t cond;
unsigned clock;
} vlc_cond_t;
#define VLC_STATIC_COND { PTHREAD_COND_INITIALIZER, CLOCK_REALTIME }
typedef pthread_key_t vlc_threadvar_t; typedef pthread_key_t vlc_threadvar_t;
typedef struct vlc_timer *vlc_timer_t; typedef struct vlc_timer *vlc_timer_t;
@ -227,12 +220,8 @@ typedef pthread_t vlc_thread_t;
#define VLC_THREAD_CANCELED PTHREAD_CANCELED #define VLC_THREAD_CANCELED PTHREAD_CANCELED
typedef pthread_mutex_t vlc_mutex_t; typedef pthread_mutex_t vlc_mutex_t;
#define VLC_STATIC_MUTEX PTHREAD_MUTEX_INITIALIZER #define VLC_STATIC_MUTEX PTHREAD_MUTEX_INITIALIZER
typedef struct typedef pthread_cond_t vlc_cond_t;
{ #define VLC_STATIC_COND PTHREAD_COND_INITIALIZER
pthread_cond_t cond;
unsigned clock;
} vlc_cond_t;
#define VLC_STATIC_COND { PTHREAD_COND_INITIALIZER, 0 }
typedef semaphore_t vlc_sem_t; typedef semaphore_t vlc_sem_t;
typedef pthread_rwlock_t vlc_rwlock_t; typedef pthread_rwlock_t vlc_rwlock_t;
#define VLC_STATIC_RWLOCK PTHREAD_RWLOCK_INITIALIZER #define VLC_STATIC_RWLOCK PTHREAD_RWLOCK_INITIALIZER
@ -292,6 +281,12 @@ typedef pthread_cond_t vlc_cond_t;
/** /**
* Static initializer for (static) condition variable. * Static initializer for (static) condition variable.
*
* \note
* The condition variable will use the default clock, which is OS-dependent.
* Therefore, where timed waits are necessary the condition variable should
* always be initialized dynamically explicit instead of using this
* initializer.
*/ */
#define VLC_STATIC_COND PTHREAD_COND_INITIALIZER #define VLC_STATIC_COND PTHREAD_COND_INITIALIZER
@ -419,10 +414,13 @@ VLC_API void vlc_cond_init(vlc_cond_t *);
/** /**
* Initializes a condition variable (wall clock). * Initializes a condition variable (wall clock).
* *
* Contrary to vlc_cond_init(), the wall clock will be used as a reference for * This function initializes a condition variable for timed waiting using the
* the vlc_cond_timedwait() time-out parameter. * UTC wall clock time. The time reference is the same as with time() and with
* timespec_get() and TIME_UTC.
* vlc_cond_timedwait_daytime() must be instead of
* vlc_cond_timedwait() for actual waiting.
*/ */
VLC_API void vlc_cond_init_daytime(vlc_cond_t *); void vlc_cond_init_daytime(vlc_cond_t *);
/** /**
* Deinitializes a condition variable. * Deinitializes a condition variable.
@ -485,23 +483,26 @@ VLC_API void vlc_cond_wait(vlc_cond_t *cond, vlc_mutex_t *mutex);
* Waits on a condition variable up to a certain date. * Waits on a condition variable up to a certain date.
* *
* This works like vlc_cond_wait() but with an additional time-out. * This works like vlc_cond_wait() but with an additional time-out.
* The time-out is expressed as an absolute timestamp using the same arbitrary
* time reference as the mdate() and mwait() functions.
* *
* If the variable was initialized with vlc_cond_init(), the timeout has the * \param cond condition variable to wait on
* same arbitrary origin as mdate(). If the variable was initialized with * \param mutex mutex which is unlocked while waiting,
* vlc_cond_init_daytime(), or was statically initialized with * then locked again when waking up
* \ref VLC_STATIC_COND, the timeout is expressed from the Unix epoch (i.e.
* the wall clock).
*
* \param p_condvar condition variable to wait on
* \param p_mutex mutex which is unlocked while waiting,
* then locked again when waking up.
* \param deadline <b>absolute</b> timeout * \param deadline <b>absolute</b> timeout
* *
* \warning If the variable was initialized with vlc_cond_init_daytime(), or
* was statically initialized with \ref VLC_STATIC_COND, the time reference
* used by this function is unspecified (depending on the implementation, it
* might be the Unix epoch or the mdate() clock).
*
* \return 0 if the condition was signaled, an error code in case of timeout. * \return 0 if the condition was signaled, an error code in case of timeout.
*/ */
VLC_API int vlc_cond_timedwait(vlc_cond_t *cond, vlc_mutex_t *mutex, VLC_API int vlc_cond_timedwait(vlc_cond_t *cond, vlc_mutex_t *mutex,
mtime_t deadline); mtime_t deadline);
int vlc_cond_timedwait_daytime(vlc_cond_t *, vlc_mutex_t *, time_t);
/** /**
* Initializes a semaphore. * Initializes a semaphore.
* *

71
src/android/thread.c

@ -190,7 +190,7 @@ void vlc_threads_setup (libvlc_int_t *p_libvlc)
void vlc_cond_init (vlc_cond_t *condvar) void vlc_cond_init (vlc_cond_t *condvar)
{ {
#ifdef HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC_NP #ifdef HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC_NP
if (unlikely(pthread_cond_init (&condvar->cond, NULL))) if (unlikely(pthread_cond_init (condvar, NULL)))
abort (); abort ();
#else #else
pthread_condattr_t attr; pthread_condattr_t attr;
@ -198,34 +198,32 @@ void vlc_cond_init (vlc_cond_t *condvar)
pthread_condattr_init (&attr); pthread_condattr_init (&attr);
pthread_condattr_setclock (&attr, CLOCK_MONOTONIC); pthread_condattr_setclock (&attr, CLOCK_MONOTONIC);
if (unlikely(pthread_cond_init (&condvar->cond, &attr))) if (unlikely(pthread_cond_init (condvar, &attr)))
abort (); abort ();
#endif #endif
condvar->clock = CLOCK_MONOTONIC;
} }
void vlc_cond_init_daytime (vlc_cond_t *condvar) void vlc_cond_init_daytime (vlc_cond_t *condvar)
{ {
if (unlikely(pthread_cond_init (&condvar->cond, NULL))) if (unlikely(pthread_cond_init (condvar, NULL)))
abort (); abort ();
condvar->clock = CLOCK_REALTIME;
} }
void vlc_cond_destroy (vlc_cond_t *condvar) void vlc_cond_destroy (vlc_cond_t *condvar)
{ {
int val = pthread_cond_destroy (&condvar->cond); int val = pthread_cond_destroy (condvar);
VLC_THREAD_ASSERT ("destroying condition"); VLC_THREAD_ASSERT ("destroying condition");
} }
void vlc_cond_signal (vlc_cond_t *condvar) void vlc_cond_signal (vlc_cond_t *condvar)
{ {
int val = pthread_cond_signal (&condvar->cond); int val = pthread_cond_signal (condvar);
VLC_THREAD_ASSERT ("signaling condition variable"); VLC_THREAD_ASSERT ("signaling condition variable");
} }
void vlc_cond_broadcast (vlc_cond_t *condvar) void vlc_cond_broadcast (vlc_cond_t *condvar)
{ {
pthread_cond_broadcast (&condvar->cond); pthread_cond_broadcast (condvar);
} }
void vlc_cond_wait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex) void vlc_cond_wait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex)
@ -237,7 +235,7 @@ void vlc_cond_wait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex)
vlc_testcancel (); vlc_testcancel ();
if (vlc_mutex_trylock (&th->lock) == 0) if (vlc_mutex_trylock (&th->lock) == 0)
{ {
th->cond = &condvar->cond; th->cond = condvar;
vlc_mutex_unlock (&th->lock); vlc_mutex_unlock (&th->lock);
} }
else else
@ -250,7 +248,7 @@ void vlc_cond_wait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex)
} }
} }
int val = pthread_cond_wait (&condvar->cond, p_mutex); int val = pthread_cond_wait (condvar, p_mutex);
VLC_THREAD_ASSERT ("waiting on condition"); VLC_THREAD_ASSERT ("waiting on condition");
if (th != NULL) if (th != NULL)
@ -262,21 +260,21 @@ void vlc_cond_wait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex)
} }
} }
int vlc_cond_timedwait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex, typedef int (*vlc_cond_wait_cb)(pthread_cond_t *, pthread_mutex_t *,
mtime_t deadline) const struct timespec *);
static int vlc_cond_timedwait_common(vlc_cond_t *condvar, vlc_mutex_t *mutex,
const struct timespec *ts,
vlc_cond_wait_cb cb)
{ {
struct timespec ts = mtime_to_ts (deadline);
vlc_thread_t th = thread; vlc_thread_t th = thread;
#ifdef HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC_NP
int (*cb)(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
#endif
if (th != NULL) if (th != NULL)
{ {
vlc_testcancel (); vlc_testcancel ();
if (vlc_mutex_trylock (&th->lock) == 0) if (vlc_mutex_trylock (&th->lock) == 0)
{ {
th->cond = &condvar->cond; th->cond = condvar;
vlc_mutex_unlock (&th->lock); vlc_mutex_unlock (&th->lock);
} }
else else
@ -289,24 +287,7 @@ int vlc_cond_timedwait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex,
} }
} }
#ifdef HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC_NP int val = cb(condvar, p_mutex, ts);
switch (condvar->clock)
{
case CLOCK_REALTIME:
cb = pthread_cond_timedwait;
break;
case CLOCK_MONOTONIC:
cb = pthread_cond_timedwait_monotonic_np;
break;
default:
vlc_assert_unreachable ();
}
int val = cb (&condvar->cond, p_mutex, &ts);
#else
int val = pthread_cond_timedwait(&condvar->cond, p_mutex, &ts);
#endif
if (val != ETIMEDOUT) if (val != ETIMEDOUT)
VLC_THREAD_ASSERT ("timed-waiting on condition"); VLC_THREAD_ASSERT ("timed-waiting on condition");
@ -320,6 +301,26 @@ int vlc_cond_timedwait (vlc_cond_t *condvar, vlc_mutex_t *p_mutex,
return val; return val;
} }
int vlc_cond_timedwait(vlc_cond_t *cond, vlc_mutex_t *mutex, mtime_t deadline)
{
struct timespec ts = mtime_to_ts(deadline);
#ifdef HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC_NP
return vlc_cond_timedwait_common(cond, mutex, &ts,
pthread_cond_timedwait_monotonic_np);
#else
return vlc_cond_timedwait_common(cond, mutex, &ts, pthread_cond_timedwait);
#endif
}
int vlc_cond_timedwait_daytime(vlc_cond_t *cond, vlc_mutex_t *mutex,
time_t deadline)
{
struct timespec ts = { deadline, 0 };
return vlc_cond_timedwait_common(cond, mutex, &ts, pthread_cond_timedwait);
}
/* pthread */ /* pthread */
static void clean_detached_thread(void *data) static void clean_detached_thread(void *data)
{ {

82
src/darwin/thread.c

@ -193,30 +193,21 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
VLC_THREAD_ASSERT ("unlocking mutex"); VLC_THREAD_ASSERT ("unlocking mutex");
} }
enum
{
VLC_CLOCK_MONOTONIC = 0,
VLC_CLOCK_REALTIME,
};
void vlc_cond_init (vlc_cond_t *p_condvar) void vlc_cond_init (vlc_cond_t *p_condvar)
{ {
if (unlikely(pthread_cond_init (&p_condvar->cond, NULL))) if (unlikely(pthread_cond_init (p_condvar, NULL)))
abort (); abort ();
p_condvar->clock = VLC_CLOCK_MONOTONIC;
} }
void vlc_cond_init_daytime (vlc_cond_t *p_condvar) void vlc_cond_init_daytime (vlc_cond_t *p_condvar)
{ {
if (unlikely(pthread_cond_init (&p_condvar->cond, NULL))) if (unlikely(pthread_cond_init (p_condvar, NULL)))
abort (); abort ();
p_condvar->clock = VLC_CLOCK_REALTIME;
} }
void vlc_cond_destroy (vlc_cond_t *p_condvar) void vlc_cond_destroy (vlc_cond_t *p_condvar)
{ {
int val = pthread_cond_destroy (&p_condvar->cond); int val = pthread_cond_destroy (p_condvar);
/* due to a faulty pthread implementation within Darwin 11 and /* due to a faulty pthread implementation within Darwin 11 and
* later condition variables cannot be destroyed without * later condition variables cannot be destroyed without
@ -244,26 +235,48 @@ void vlc_cond_destroy (vlc_cond_t *p_condvar)
void vlc_cond_signal (vlc_cond_t *p_condvar) void vlc_cond_signal (vlc_cond_t *p_condvar)
{ {
int val = pthread_cond_signal (&p_condvar->cond); int val = pthread_cond_signal (p_condvar);
VLC_THREAD_ASSERT ("signaling condition variable"); VLC_THREAD_ASSERT ("signaling condition variable");
} }
void vlc_cond_broadcast (vlc_cond_t *p_condvar) void vlc_cond_broadcast (vlc_cond_t *p_condvar)
{ {
pthread_cond_broadcast (&p_condvar->cond); pthread_cond_broadcast (p_condvar);
} }
void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex) void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
{ {
int val = pthread_cond_wait (&p_condvar->cond, p_mutex); int val = pthread_cond_wait (p_condvar, p_mutex);
VLC_THREAD_ASSERT ("waiting on condition"); VLC_THREAD_ASSERT ("waiting on condition");
} }
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)
{ {
int val = 0; /* according to POSIX standards, cond_timedwait should be a cancellation point
* Of course, Darwin does not care */
pthread_testcancel();
/*
* mdate() is the monotonic clock, pthread_cond_timedwait expects
* origin of gettimeofday(). Use timedwait_relative_np() instead.
*/
mtime_t base = mdate();
deadline -= base;
if (deadline < 0)
deadline = 0;
struct timespec ts = mtime_to_ts(deadline);
int val = pthread_cond_timedwait_relative_np(p_condvar, p_mutex, &ts);
if (val != ETIMEDOUT)
VLC_THREAD_ASSERT ("timed-waiting on condition");
return val;
}
/* variant for vlc_cond_init_daytime */
int vlc_cond_timedwait_daytime (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
time_t deadline)
{
/* /*
* Note that both pthread_cond_timedwait_relative_np and pthread_cond_timedwait * Note that both pthread_cond_timedwait_relative_np and pthread_cond_timedwait
* convert the given timeout to a mach absolute deadline, with system startup * convert the given timeout to a mach absolute deadline, with system startup
@ -272,43 +285,22 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
* For more details, see: https://devforums.apple.com/message/931605 * For more details, see: https://devforums.apple.com/message/931605
*/ */
/* according to POSIX standards, cond_timedwait should be a cancellation point
* Of course, Darwin does not care */
pthread_testcancel(); pthread_testcancel();
if (p_condvar->clock == VLC_CLOCK_MONOTONIC) { /*
* FIXME: It is assumed, that in this case the system waits until the real
/* * time deadline is passed, even if the real time is adjusted in between.
* mdate() is the monotonic clock, pthread_cond_timedwait expects * This is not fulfilled, as described above.
* origin of gettimeofday(). Use timedwait_relative_np() instead. */
*/ struct timespec ts = mtime_to_ts(deadline);
mtime_t base = mdate(); int val = pthread_cond_timedwait(p_condvar, p_mutex, &ts);
deadline -= base;
if (deadline < 0)
deadline = 0;
struct timespec ts = mtime_to_ts(deadline);
val = pthread_cond_timedwait_relative_np(&p_condvar->cond, p_mutex, &ts);
} else {
/* variant for vlc_cond_init_daytime */
assert (p_condvar->clock == VLC_CLOCK_REALTIME);
/*
* FIXME: It is assumed, that in this case the system waits until the real
* time deadline is passed, even if the real time is adjusted in between.
* This is not fulfilled, as described above.
*/
struct timespec ts = mtime_to_ts(deadline);
val = pthread_cond_timedwait(&p_condvar->cond, p_mutex, &ts);
}
if (val != ETIMEDOUT) if (val != ETIMEDOUT)
VLC_THREAD_ASSERT ("timed-waiting on condition"); VLC_THREAD_ASSERT ("timed-waiting on condition");
return val; return val;
} }
/* Initialize a semaphore. */ /* Initialize a semaphore. */
void vlc_sem_init (vlc_sem_t *sem, unsigned value) void vlc_sem_init (vlc_sem_t *sem, unsigned value)
{ {

2
src/input/vlm.c

@ -395,7 +395,7 @@ static void* Manage( void* p_object )
while( !vlm->input_state_changed && !scheduled_command ) while( !vlm->input_state_changed && !scheduled_command )
{ {
if( nextschedule != 0 ) if( nextschedule != 0 )
scheduled_command = vlc_cond_timedwait( &vlm->wait_manage, &vlm->lock_manage, nextschedule * CLOCK_FREQ ) != 0; scheduled_command = vlc_cond_timedwait_daytime( &vlm->wait_manage, &vlm->lock_manage, nextschedule ) != 0;
else else
vlc_cond_wait( &vlm->wait_manage, &vlm->lock_manage ); vlc_cond_wait( &vlm->wait_manage, &vlm->lock_manage );
} }

1
src/libvlccore.sym

@ -517,7 +517,6 @@ VLC_Compiler
vlc_cond_broadcast vlc_cond_broadcast
vlc_cond_destroy vlc_cond_destroy
vlc_cond_init vlc_cond_init
vlc_cond_init_daytime
vlc_cond_signal vlc_cond_signal
vlc_cond_timedwait vlc_cond_timedwait
vlc_cond_wait vlc_cond_wait

69
src/os2/thread.c

@ -256,25 +256,6 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
} }
/*** Condition variables ***/ /*** Condition variables ***/
#undef CLOCK_REALTIME
#undef CLOCK_MONOTONIC
enum
{
CLOCK_REALTIME=0, /* must be zero for VLC_STATIC_COND */
CLOCK_MONOTONIC,
};
static void vlc_cond_init_common (vlc_cond_t *p_condvar, unsigned clock)
{
if (DosCreateEventSem (NULL, &p_condvar->hev, 0, FALSE) ||
DosCreateEventSem (NULL, &p_condvar->hevAck, 0, FALSE))
abort();
p_condvar->waiters = 0;
p_condvar->signaled = 0;
p_condvar->clock = clock;
}
typedef struct vlc_static_cond_t vlc_static_cond_t; typedef struct vlc_static_cond_t vlc_static_cond_t;
struct vlc_static_cond_t struct vlc_static_cond_t
@ -291,7 +272,7 @@ static void vlc_static_cond_init (vlc_cond_t *p_condvar)
if (p_condvar->hev == NULLHANDLE) if (p_condvar->hev == NULLHANDLE)
{ {
vlc_cond_init_common (p_condvar, p_condvar->clock); vlc_cond_init (p_condvar);
vlc_static_cond_t *new_static_condvar; vlc_static_cond_t *new_static_condvar;
@ -325,12 +306,17 @@ static void vlc_static_cond_destroy_all (void)
void vlc_cond_init (vlc_cond_t *p_condvar) void vlc_cond_init (vlc_cond_t *p_condvar)
{ {
vlc_cond_init_common (p_condvar, CLOCK_MONOTONIC); if (DosCreateEventSem (NULL, &p_condvar->hev, 0, FALSE) ||
DosCreateEventSem (NULL, &p_condvar->hevAck, 0, FALSE))
abort();
p_condvar->waiters = 0;
p_condvar->signaled = 0;
} }
void vlc_cond_init_daytime (vlc_cond_t *p_condvar) void vlc_cond_init_daytime (vlc_cond_t *p_condvar)
{ {
vlc_cond_init_common (p_condvar, CLOCK_REALTIME); vlc_cond_init (p_condvar);
} }
void vlc_cond_destroy (vlc_cond_t *p_condvar) void vlc_cond_destroy (vlc_cond_t *p_condvar)
@ -371,6 +357,8 @@ static int vlc_cond_wait_common (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
ULONG ulPost; ULONG ulPost;
ULONG rc; ULONG rc;
assert(p_condvar->hev != NULLHANDLE);
do do
{ {
vlc_testcancel(); vlc_testcancel();
@ -408,28 +396,29 @@ void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
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;
if (p_condvar->hev == NULLHANDLE) mtime_t total = mdate();
vlc_static_cond_init (p_condvar); total = (deadline - total) / 1000;
if( total < 0 )
total = 0;
ulTimeout = ( total > 0x7fffffff ) ? 0x7fffffff : total;
return vlc_cond_wait_common (p_condvar, p_mutex, ulTimeout);
}
int vlc_cond_timedwait_daytime (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
time_t deadline)
{
ULONG ulTimeout;
mtime_t total; mtime_t total;
switch (p_condvar->clock) struct timeval tv;
{
case CLOCK_REALTIME:
{
struct timeval tv;
gettimeofday (&tv, NULL);
total = CLOCK_FREQ * tv.tv_sec + gettimeofday (&tv, NULL);
CLOCK_FREQ * tv.tv_usec / 1000000L;
break; total = CLOCK_FREQ * tv.tv_sec +
} CLOCK_FREQ * tv.tv_usec / 1000000L;
default:
assert (p_condvar->clock == CLOCK_MONOTONIC);
total = mdate();
break;
}
total = (deadline - total) / 1000; total = (deadline - total) / 1000;
if( total < 0 ) if( total < 0 )
total = 0; total = 0;

10
src/posix/thread.c

@ -303,6 +303,16 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
return val; return val;
} }
int vlc_cond_timedwait_daytime (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
time_t deadline)
{
struct timespec ts = { deadline, 0 };
int val = pthread_cond_timedwait (p_condvar, p_mutex, &ts);
if (val != ETIMEDOUT)
VLC_THREAD_ASSERT ("timed-waiting on condition");
return val;
}
void vlc_sem_init (vlc_sem_t *sem, unsigned value) void vlc_sem_init (vlc_sem_t *sem, unsigned value)
{ {
if (unlikely(sem_init (sem, 0, value))) if (unlikely(sem_init (sem, 0, value)))

58
src/win32/thread.c

@ -195,29 +195,17 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
} }
/*** Condition variables ***/ /*** Condition variables ***/
enum void vlc_cond_init(vlc_cond_t *wait)
{
VLC_CLOCK_REALTIME=0, /* must be zero for VLC_STATIC_COND */
VLC_CLOCK_MONOTONIC,
};
static void vlc_cond_init_common(vlc_cond_t *wait, unsigned clock)
{ {
wait->semaphore = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL); wait->semaphore = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
if (unlikely(wait->semaphore == NULL)) if (unlikely(wait->semaphore == NULL))
abort(); abort();
wait->waiters = 0; wait->waiters = 0;
wait->clock = clock;
}
void vlc_cond_init (vlc_cond_t *p_condvar)
{
vlc_cond_init_common (p_condvar, VLC_CLOCK_MONOTONIC);
} }
void vlc_cond_init_daytime (vlc_cond_t *p_condvar) void vlc_cond_init_daytime (vlc_cond_t *p_condvar)
{ {
vlc_cond_init_common (p_condvar, VLC_CLOCK_REALTIME); vlc_cond_init (p_condvar);
} }
void vlc_cond_destroy(vlc_cond_t *wait) void vlc_cond_destroy(vlc_cond_t *wait)
@ -260,9 +248,15 @@ void vlc_cond_broadcast(vlc_cond_t *wait)
ReleaseSemaphore(wait->semaphore, waiters, NULL); ReleaseSemaphore(wait->semaphore, waiters, NULL);
} }
static DWORD vlc_cond_wait_delay(vlc_cond_t *wait, vlc_mutex_t *lock, static int vlc_cond_wait_delay(vlc_cond_t *wait, vlc_mutex_t *lock,
DWORD delay) mtime_t us)
{ {
if (us < 0)
us = 0;
if (us > 0x7fffffff)
us = 0x7fffffff;
DWORD delay = us;
DWORD result; DWORD result;
vlc_testcancel(); vlc_testcancel();
@ -282,7 +276,7 @@ static DWORD vlc_cond_wait_delay(vlc_cond_t *wait, vlc_mutex_t *lock,
if (result == WAIT_IO_COMPLETION) if (result == WAIT_IO_COMPLETION)
vlc_testcancel(); vlc_testcancel();
return result; return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;
} }
void vlc_cond_wait(vlc_cond_t *wait, vlc_mutex_t *lock) void vlc_cond_wait(vlc_cond_t *wait, vlc_mutex_t *lock)
@ -292,29 +286,19 @@ void vlc_cond_wait(vlc_cond_t *wait, vlc_mutex_t *lock)
int vlc_cond_timedwait(vlc_cond_t *wait, vlc_mutex_t *lock, mtime_t deadline) int vlc_cond_timedwait(vlc_cond_t *wait, vlc_mutex_t *lock, mtime_t deadline)
{ {
mtime_t total; return vlc_cond_wait_delay(wait, lock, deadline - mdate());
}
switch (wait->clock)
{
case VLC_CLOCK_REALTIME: /* FIXME? sub-second precision */
total = CLOCK_FREQ * time(NULL);
break;
case VLC_CLOCK_MONOTONIC:
total = mdate();
break;
default:
vlc_assert_unreachable();
}
total = (deadline - total) / 1000; int vlc_cond_timedwait_daytime(vlc_cond_t *wait, vlc_mutex_t *lock,
if (total < 0) time_t deadline)
total = 0; {
time_t now;
mtime_t delay;
DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total; time(&now);
delay = ((mtime_t)deadline - (mtime_t)now) * CLOCK_FREQ;
if (vlc_cond_wait_delay(wait, lock, delay) == WAIT_TIMEOUT) return vlc_cond_wait_delay(wait, lock, delay);
return ETIMEDOUT;
return 0;
} }
/*** Semaphore ***/ /*** Semaphore ***/

Loading…
Cancel
Save