video_filter: erase: use C99 loop declarations
[vlc.git] / src / misc / threads.c
blob1972621b28c8b0461cff19851c502b4d5e567a27
1 /*****************************************************************************
2 * threads.c: LibVLC generic thread support
3 *****************************************************************************
4 * Copyright (C) 2009-2012 RĂ©mi Denis-Courmont
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include <assert.h>
27 #include <vlc_common.h>
29 /*** Global locks ***/
31 void vlc_global_mutex (unsigned n, bool acquire)
33 static vlc_mutex_t locks[] = {
34 VLC_STATIC_MUTEX,
35 VLC_STATIC_MUTEX,
36 VLC_STATIC_MUTEX,
37 VLC_STATIC_MUTEX,
38 VLC_STATIC_MUTEX,
40 static_assert (VLC_MAX_MUTEX == (sizeof (locks) / sizeof (locks[0])),
41 "Wrong number of global mutexes");
42 assert (n < (sizeof (locks) / sizeof (locks[0])));
44 vlc_mutex_t *lock = locks + n;
45 if (acquire)
46 vlc_mutex_lock (lock);
47 else
48 vlc_mutex_unlock (lock);
51 #ifdef LIBVLC_NEED_RWLOCK
52 /*** Generic read/write locks ***/
53 #include <stdlib.h>
54 #include <limits.h>
55 /* NOTE:
56 * lock->state is a signed long integer:
57 * - The sign bit is set when the lock is held for writing.
58 * - The other bits code the number of times the lock is held for reading.
59 * Consequently:
60 * - The value is negative if and only if the lock is held for writing.
61 * - The value is zero if and only if the lock is not held at all.
63 #define READER_MASK LONG_MAX
64 #define WRITER_BIT LONG_MIN
66 void vlc_rwlock_init (vlc_rwlock_t *lock)
68 vlc_mutex_init (&lock->mutex);
69 vlc_cond_init (&lock->wait);
70 lock->state = 0;
73 void vlc_rwlock_destroy (vlc_rwlock_t *lock)
75 vlc_cond_destroy (&lock->wait);
76 vlc_mutex_destroy (&lock->mutex);
79 void vlc_rwlock_rdlock (vlc_rwlock_t *lock)
81 vlc_mutex_lock (&lock->mutex);
82 /* Recursive read-locking is allowed.
83 * Ensure that there is no active writer. */
84 while (lock->state < 0)
86 assert (lock->state == WRITER_BIT);
87 mutex_cleanup_push (&lock->mutex);
88 vlc_cond_wait (&lock->wait, &lock->mutex);
89 vlc_cleanup_pop ();
91 if (unlikely(lock->state >= READER_MASK))
92 abort (); /* An overflow is certainly a recursion bug. */
93 lock->state++;
94 vlc_mutex_unlock (&lock->mutex);
97 void vlc_rwlock_wrlock (vlc_rwlock_t *lock)
99 vlc_mutex_lock (&lock->mutex);
100 /* Wait until nobody owns the lock in any way. */
101 while (lock->state != 0)
103 mutex_cleanup_push (&lock->mutex);
104 vlc_cond_wait (&lock->wait, &lock->mutex);
105 vlc_cleanup_pop ();
107 lock->state = WRITER_BIT;
108 vlc_mutex_unlock (&lock->mutex);
111 void vlc_rwlock_unlock (vlc_rwlock_t *lock)
113 vlc_mutex_lock (&lock->mutex);
114 if (lock->state < 0)
115 { /* Write unlock */
116 assert (lock->state == WRITER_BIT);
117 /* Let reader and writer compete. OS scheduler decides who wins. */
118 lock->state = 0;
119 vlc_cond_broadcast (&lock->wait);
121 else
122 { /* Read unlock */
123 assert (lock->state > 0);
124 /* If there are no readers left, wake up one pending writer. */
125 if (--lock->state == 0)
126 vlc_cond_signal (&lock->wait);
128 vlc_mutex_unlock (&lock->mutex);
130 #endif /* LIBVLC_NEED_RWLOCK */
132 #ifdef LIBVLC_NEED_SEMAPHORE
133 /*** Generic semaphores ***/
134 #include <limits.h>
135 #include <errno.h>
137 void vlc_sem_init (vlc_sem_t *sem, unsigned value)
139 vlc_mutex_init (&sem->lock);
140 vlc_cond_init (&sem->wait);
141 sem->value = value;
144 void vlc_sem_destroy (vlc_sem_t *sem)
146 vlc_cond_destroy (&sem->wait);
147 vlc_mutex_destroy (&sem->lock);
150 int vlc_sem_post (vlc_sem_t *sem)
152 int ret = 0;
154 vlc_mutex_lock (&sem->lock);
155 if (likely(sem->value != UINT_MAX))
156 sem->value++;
157 else
158 ret = EOVERFLOW;
159 vlc_mutex_unlock (&sem->lock);
160 vlc_cond_signal (&sem->wait);
162 return ret;
165 void vlc_sem_wait (vlc_sem_t *sem)
167 vlc_mutex_lock (&sem->lock);
168 mutex_cleanup_push (&sem->lock);
169 while (!sem->value)
170 vlc_cond_wait (&sem->wait, &sem->lock);
171 sem->value--;
172 vlc_cleanup_pop ();
173 vlc_mutex_unlock (&sem->lock);
175 #endif /* LIBVLC_NEED_SEMAPHORE */