Module: xenomai-forge Branch: master Commit: 0b0888a2022a3acd215992b03262c32ca6ad7c36 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=0b0888a2022a3acd215992b03262c32ca6ad7c36
Author: Philippe Gerum <r...@xenomai.org> Date: Thu Jan 9 10:47:22 2014 +0100 copperplate/threadobj: fix suspend vs deletion race (mercury) Over Mercury, the notifier wait action should not be entered if a cancellation request is pending. Otherwise, the thread pending deletion would sleep in notifier_wait(), with the requestor waiting in cancel_sync(), both indefinitely. --- include/copperplate/threadobj.h | 1 + lib/copperplate/threadobj.c | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/copperplate/threadobj.h b/include/copperplate/threadobj.h index 184c711..218c274 100644 --- a/include/copperplate/threadobj.h +++ b/include/copperplate/threadobj.h @@ -124,6 +124,7 @@ void threadobj_save_timeout(struct threadobj_corespec *corespec, #define __THREAD_S_ACTIVE (1 << 5) /* Running user code. */ #define __THREAD_S_SUSPENDED (1 << 6) /* Suspended via threadobj_suspend(). */ #define __THREAD_S_SAFE (1 << 7) /* TCB release deferred. */ +#define __THREAD_S_ZOMBIE (1 << 8) /* Deletion process ongoing. */ #define __THREAD_S_DEBUG (1 << 31) /* Debug mode enabled. */ /* * threadobj->run_state, locklessly updated by "current", merged diff --git a/lib/copperplate/threadobj.c b/lib/copperplate/threadobj.c index a31479c..c54cdf8 100644 --- a/lib/copperplate/threadobj.c +++ b/lib/copperplate/threadobj.c @@ -420,11 +420,13 @@ static void notifier_callback(const struct notifier *nf) * threadobj_suspend(). */ threadobj_lock(current); - current->status |= __THREAD_S_SUSPENDED; - threadobj_unlock(current); - notifier_wait(nf); /* Wait for threadobj_resume(). */ - threadobj_lock(current); - current->status &= ~__THREAD_S_SUSPENDED; + if ((current->status & __THREAD_S_ZOMBIE) == 0) { + current->status |= __THREAD_S_SUSPENDED; + threadobj_unlock(current); + notifier_wait(nf); /* Wait for threadobj_resume(). */ + threadobj_lock(current); + current->status &= ~__THREAD_S_SUSPENDED; + } threadobj_unlock(current); } @@ -488,7 +490,7 @@ static inline void threadobj_run_corespec(struct threadobj *thobj) { } -static inline void threadobj_cancel_corespec(struct threadobj *thobj) +static inline void threadobj_cancel_corespec(struct threadobj *thobj) /* thobj->lock held */ { } @@ -872,9 +874,9 @@ void threadobj_init(struct threadobj *thobj, static void destroy_thread(struct threadobj *thobj) { + threadobj_cleanup_corespec(thobj); __RT(pthread_cond_destroy(&thobj->barrier)); __RT(pthread_mutex_destroy(&thobj->lock)); - threadobj_cleanup_corespec(thobj); } void threadobj_destroy(struct threadobj *thobj) /* thobj->lock free */ @@ -1089,8 +1091,6 @@ static void cancel_sync(struct threadobj *thobj) /* thobj->lock held */ int oldstate, ret = 0; sem_t *sem; - __threadobj_check_locked(thobj); - /* * We have to allocate the cancel sync sema4 in the main heap * dynamically, so that it always live in valid memory when we @@ -1106,6 +1106,7 @@ static void cancel_sync(struct threadobj *thobj) /* thobj->lock held */ __STD(sem_init(sem, sem_scope_attribute, 0)); thobj->cancel_sem = sem; + thobj->status |= __THREAD_S_ZOMBIE; /* * If the thread to delete is warming up, wait until it _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git