Module: xenomai-forge
Branch: master
Commit: 0ef38e7d4e936dc0ae5d2d9e406f3b865129ac30
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=0ef38e7d4e936dc0ae5d2d9e406f3b865129ac30

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sun Nov  6 16:19:02 2011 +0100

copperplate/threadobj: fix cancel state breakage with thread lock

---

 lib/copperplate/threadobj.c |   28 ++++++++++++++++++++++++++--
 1 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/lib/copperplate/threadobj.c b/lib/copperplate/threadobj.c
index e37fc84..c13cf54 100644
--- a/lib/copperplate/threadobj.c
+++ b/lib/copperplate/threadobj.c
@@ -837,10 +837,29 @@ void threadobj_start(struct threadobj *thobj)     /* 
thobj->lock held. */
 
 void threadobj_wait_start(struct threadobj *thobj) /* thobj->lock free. */
 {
+       int oldstate;
+
        threadobj_lock(thobj);
 
-       while ((thobj->status & (THREADOBJ_STARTED|THREADOBJ_ABORTED)) == 0)
+       /*
+        * NOTE: to spare us the need for passing the equivalent of a
+        * syncstate argument to each thread locking operation, we
+        * hold the cancel state of the locker directly into the
+        * locked thread, prior to disabling cancellation for the
+        * calling thread. However, this means that we must save the
+        * currently saved state on the stack prior to calling any
+        * service which releases that lock implicitly, such as
+        * pthread_cond_wait(). Failing to do so would introduce the
+        * possibility for the saved state to be overwritten by
+        * another thread which managed to grab the lock after
+        * pthread_cond_wait() dropped it.
+        */
+
+       while ((thobj->status & (THREADOBJ_STARTED|THREADOBJ_ABORTED)) == 0) {
+               oldstate = thobj->cancel_state;
                __RT(pthread_cond_wait(&thobj->barrier, &thobj->lock));
+               thobj->cancel_state = oldstate;
+       }
 
        threadobj_unlock(thobj);
 
@@ -888,8 +907,13 @@ int threadobj_prologue(struct threadobj *thobj, const char 
*name)
 
 static void cancel_sync(struct threadobj *thobj) /* thobj->lock held */
 {
-       while (thobj->status & THREADOBJ_WARMUP)
+       int oldstate;
+
+       while (thobj->status & THREADOBJ_WARMUP) {
+               oldstate = thobj->cancel_state;
                __RT(pthread_cond_wait(&thobj->barrier, &thobj->lock));
+               thobj->cancel_state = oldstate;
+       }
 
        if ((thobj->status & THREADOBJ_STARTED) == 0) {
                thobj->status |= THREADOBJ_ABORTED;


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to