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

Reply via email to