Module: xenomai-forge Branch: master Commit: 0ef38e7d4e936dc0ae5d2d9e406f3b865129ac30 URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=0ef38e7d4e936dc0ae5d2d9e406f3b865129ac30
Author: Philippe Gerum <[email protected]> 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 [email protected] https://mail.gna.org/listinfo/xenomai-git
