vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Wed Jun 1 21:18:14 2016 +0300| [4d29bafd6d762ecbc99d7ae075e73cf1fc458c4a] | committer: Rémi Denis-Courmont
threads: generic futex-based semaphores > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=4d29bafd6d762ecbc99d7ae075e73cf1fc458c4a --- include/vlc_threads.h | 4 +-- src/misc/threads.c | 86 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 72 insertions(+), 18 deletions(-) diff --git a/include/vlc_threads.h b/include/vlc_threads.h index 33f2a8a..d3ea0ac 100644 --- a/include/vlc_threads.h +++ b/include/vlc_threads.h @@ -334,9 +334,7 @@ typedef struct #ifdef LIBVLC_NEED_SEMAPHORE typedef struct vlc_sem { - vlc_mutex_t lock; - vlc_cond_t wait; - unsigned value; + unsigned value; } vlc_sem_t; #endif diff --git a/src/misc/threads.c b/src/misc/threads.c index 8bdcb1f..6451274 100644 --- a/src/misc/threads.c +++ b/src/misc/threads.c @@ -24,6 +24,7 @@ #include <assert.h> #include <errno.h> +#include <limits.h> #include <vlc_common.h> @@ -215,8 +216,6 @@ int vlc_cond_timedwait_daytime(vlc_cond_t *cond, vlc_mutex_t *mutex, #ifdef LIBVLC_NEED_RWLOCK /*** Generic read/write locks ***/ -#include <stdlib.h> -#include <limits.h> /* NOTE: * lock->state is a signed long integer: * - The sign bit is set when the lock is held for writing. @@ -296,45 +295,102 @@ void vlc_rwlock_unlock (vlc_rwlock_t *lock) #ifdef LIBVLC_NEED_SEMAPHORE /*** Generic semaphores ***/ -#include <limits.h> -#include <errno.h> +# ifdef LIBVLC_NEED_CONDVAR +static inline atomic_uint *vlc_sem_value(vlc_sem_t *sem) +{ + /* XXX: ugly but avoids including vlc_atomic.h in vlc_threads.h */ + static_assert (sizeof (sem->value) <= sizeof (atomic_uint), + "Size mismatch!"); + static_assert ((alignof (sem->value) % alignof (atomic_uint)) == 0, + "Alignment mismatch"); + return (atomic_uint *)&sem->value; +} + +void vlc_sem_init(vlc_sem_t *sem, unsigned value) +{ + atomic_init(vlc_sem_value(sem), value); +} + +void vlc_sem_destroy(vlc_sem_t *sem) +{ + (void) sem; +} + +int vlc_sem_post(vlc_sem_t *sem) +{ + unsigned count = 0; + + while (!atomic_compare_exchange_weak(vlc_sem_value(sem), &count, + count + 1)) + { + if (unlikely(count == UINT_MAX)) + return EOVERFLOW; + } + + vlc_addr_signal(&sem->value); + return 0; +} + +void vlc_sem_wait(vlc_sem_t *sem) +{ + unsigned count = 1; + + vlc_testcancel(); + + while (!atomic_compare_exchange_weak(vlc_sem_value(sem), &count, + count - 1)) + { + if (count == 0) + { + vlc_cancel_addr_prepare(&sem->value); + vlc_addr_wait(&sem->value, 0); + vlc_cancel_addr_finish(&sem->value); + } + } +} +# else +static struct +{ + vlc_mutex_t lock; + vlc_cond_t wait; +} semaphores = { VLC_STATIC_MUTEX, VLC_STATIC_COND }; void vlc_sem_init (vlc_sem_t *sem, unsigned value) { - vlc_mutex_init (&sem->lock); - vlc_cond_init (&sem->wait); + union { unsigned u; signed s; } u = { .u = value }; + sem->value = value; } void vlc_sem_destroy (vlc_sem_t *sem) { - vlc_cond_destroy (&sem->wait); - vlc_mutex_destroy (&sem->lock); + (void) sem; } int vlc_sem_post (vlc_sem_t *sem) { int ret = 0; - vlc_mutex_lock (&sem->lock); + vlc_mutex_lock(&semaphores.lock); if (likely(sem->value != UINT_MAX)) sem->value++; else ret = EOVERFLOW; - vlc_mutex_unlock (&sem->lock); - vlc_cond_signal (&sem->wait); + vlc_mutex_unlock(&semaphores.lock); + vlc_cond_broadcast(&semaphores.wait); return ret; } void vlc_sem_wait (vlc_sem_t *sem) { - vlc_mutex_lock (&sem->lock); - mutex_cleanup_push (&sem->lock); + vlc_mutex_lock(&semaphores.lock); + mutex_cleanup_push(&semaphores.lock); while (!sem->value) - vlc_cond_wait (&sem->wait, &sem->lock); + vlc_cond_wait(&semaphores.wait, &semaphores.lock); sem->value--; vlc_cleanup_pop (); - vlc_mutex_unlock (&sem->lock); + vlc_mutex_unlock(&semaphores.lock); } +# endif #endif /* LIBVLC_NEED_SEMAPHORE */ _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
