vlc | branch: master | Rémi Denis-Courmont <[email protected]> | 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; } /** _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
