[vlc-commits] interrupt: fix interruptible functions without any interrupt context
Rémi Denis-Courmont
git at videolan.org
Mon Dec 21 19:56:04 CET 2015
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Mon Dec 21 20:53:55 2015 +0200| [c1a723e0b003fd1011c36cd4df802e64b118accd] | committer: Rémi Denis-Courmont
interrupt: fix interruptible functions without any interrupt context
If there are no interrupt contexts in the whole process, then the
thread variable is uninitialized. This adds a check.
Using thread_local would be much simpler and faster (but C11 threads).
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=c1a723e0b003fd1011c36cd4df802e64b118accd
---
src/misc/interrupt.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/src/misc/interrupt.c b/src/misc/interrupt.c
index b78f8b0..979d5f3 100644
--- a/src/misc/interrupt.c
+++ b/src/misc/interrupt.c
@@ -54,7 +54,7 @@ static void vlc_interrupt_destructor(void *data)
#endif
static unsigned vlc_interrupt_refs = 0;
-static vlc_mutex_t vlc_interrupt_lock = VLC_STATIC_MUTEX;
+static vlc_rwlock_t vlc_interrupt_lock = VLC_STATIC_RWLOCK;
static vlc_threadvar_t vlc_interrupt_var;
/**
@@ -62,7 +62,7 @@ static vlc_threadvar_t vlc_interrupt_var;
*/
void vlc_interrupt_init(vlc_interrupt_t *ctx)
{
- vlc_mutex_lock(&vlc_interrupt_lock);
+ vlc_rwlock_wrlock(&vlc_interrupt_lock);
assert(vlc_interrupt_refs < UINT_MAX);
if (vlc_interrupt_refs++ == 0)
#ifndef NDEBUG
@@ -70,7 +70,7 @@ void vlc_interrupt_init(vlc_interrupt_t *ctx)
#else
vlc_threadvar_create(&vlc_interrupt_var, NULL);
#endif
- vlc_mutex_unlock(&vlc_interrupt_lock);
+ vlc_rwlock_unlock(&vlc_interrupt_lock);
vlc_mutex_init(&ctx->lock);
ctx->interrupted = false;
@@ -99,11 +99,11 @@ void vlc_interrupt_deinit(vlc_interrupt_t *ctx)
assert(!ctx->attached);
vlc_mutex_destroy(&ctx->lock);
- vlc_mutex_lock(&vlc_interrupt_lock);
+ vlc_rwlock_wrlock(&vlc_interrupt_lock);
assert(vlc_interrupt_refs > 0);
if (--vlc_interrupt_refs == 0)
vlc_threadvar_delete(&vlc_interrupt_var);
- vlc_mutex_unlock(&vlc_interrupt_lock);
+ vlc_rwlock_unlock(&vlc_interrupt_lock);
}
void vlc_interrupt_destroy(vlc_interrupt_t *ctx)
@@ -132,6 +132,12 @@ vlc_interrupt_t *vlc_interrupt_set(vlc_interrupt_t *newctx)
{
vlc_interrupt_t *oldctx;
+ /* This function is called to push or pop an interrupt context. Either way
+ * either newctx or oldctx (or both) are non-NULL. Thus vlc_interrupt_refs
+ * must be larger than zero and vlc_interrupt_var must be valid. And so the
+ * read/write lock is not needed. */
+ assert(vlc_interrupt_refs > 0);
+
oldctx = vlc_threadvar_get(vlc_interrupt_var);
#ifndef NDEBUG
if (oldctx != NULL)
@@ -152,7 +158,13 @@ vlc_interrupt_t *vlc_interrupt_set(vlc_interrupt_t *newctx)
static vlc_interrupt_t *vlc_interrupt_get(void)
{
- return vlc_threadvar_get(vlc_interrupt_var);
+ vlc_interrupt_t *ctx = NULL;
+
+ vlc_rwlock_rdlock(&vlc_interrupt_lock);
+ if (vlc_interrupt_refs > 0)
+ ctx = vlc_threadvar_get(vlc_interrupt_var);
+ vlc_rwlock_unlock(&vlc_interrupt_lock);
+ return ctx;
}
/**
More information about the vlc-commits
mailing list