[vlc-commits] threads: generic futex-based semaphores
Rémi Denis-Courmont
git at videolan.org
Wed Jun 1 21:57:09 CEST 2016
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | 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 */
More information about the vlc-commits
mailing list