Module: xenomai-3
Branch: next
Commit: e4c9b3d581f3ee349c52f39c321c0dc82b2a4ad1
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=e4c9b3d581f3ee349c52f39c321c0dc82b2a4ad1

Author: Philippe Gerum <r...@xenomai.org>
Date:   Tue Mar  1 10:00:59 2016 +0100

cobalt/thread: force secondary mode for joining threads

Make xnthread_join() switch the caller to secondary mode prior to
waiting for the target thread termination. The original runtime mode
is restored upon return.

Since the joiner was already synchronized on an event that may be sent
by the joinee from secondary mode exclusively, this change does not
drop any real-time guarantee for the joiner: there has never been any
in the first place.

This is a preparation step to a stricter synchronization between the
joiner and the joinee, especially in the SMP case.

---

 include/cobalt/kernel/thread.h |    2 --
 kernel/cobalt/posix/process.c  |    2 --
 kernel/cobalt/thread.c         |   75 +++++++++++++++++-----------------------
 3 files changed, 31 insertions(+), 48 deletions(-)

diff --git a/include/cobalt/kernel/thread.h b/include/cobalt/kernel/thread.h
index 59d6027..f25c6d0 100644
--- a/include/cobalt/kernel/thread.h
+++ b/include/cobalt/kernel/thread.h
@@ -188,8 +188,6 @@ struct xnthread {
        const char *exe_path;   /* Executable path */
        u32 proghash;           /* Hash value for exe_path */
 #endif
-       /** Exit event for joining the thread. */
-       struct xnsynch join_synch;
 };
 
 static inline int xnthread_get_state(const struct xnthread *thread)
diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
index 788a24a..5b80521 100644
--- a/kernel/cobalt/posix/process.c
+++ b/kernel/cobalt/posix/process.c
@@ -1048,8 +1048,6 @@ static void __handle_taskexit_event(struct task_struct *p)
                unregister_debugged_thread(thread);
 
        xnthread_run_handler_stack(thread, exit_thread);
-       /* Waiters will receive EIDRM */
-       xnsynch_destroy(&thread->join_synch);
        xnsched_run();
 
        if (xnthread_test_state(thread, XNUSER)) {
diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
index 2b0cf60..462d917 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -204,7 +204,6 @@ int __xnthread_init(struct xnthread *thread,
        memset(&thread->stat, 0, sizeof(thread->stat));
        thread->selector = NULL;
        INIT_LIST_HEAD(&thread->claimq);
-       xnsynch_init(&thread->join_synch, XNSYNCH_FIFO, NULL);
        /* These will be filled by xnthread_start() */
        thread->entry = NULL;
        thread->cookie = NULL;
@@ -1594,7 +1593,9 @@ EXPORT_SYMBOL_GPL(xnthread_cancel);
  * immediately.
  *
  * xnthread_join() adapts to the calling context (primary or
- * secondary).
+ * secondary), switching to secondary mode if needed for the duration
+ * of the wait. Upon return, the original runtime mode is restored,
+ * unless a Linux signal is pending.
  *
  * @param thread The descriptor address of the thread to join with.
  *
@@ -1617,62 +1618,48 @@ EXPORT_SYMBOL_GPL(xnthread_cancel);
  */
 int xnthread_join(struct xnthread *thread, bool uninterruptible)
 {
+       struct xnthread *curr = xnthread_current();
+       int ret = 0, switched = 0;
        unsigned int tag;
        spl_t s;
-       int ret;
 
        XENO_BUG_ON(COBALT, xnthread_test_state(thread, XNROOT));
 
+       if (thread == curr)
+               return -EDEADLK;
+
        xnlock_get_irqsave(&nklock, s);
 
-       tag = thread->idtag;
-       if (xnthread_test_info(thread, XNDORMANT) || tag == 0) {
-               xnlock_put_irqrestore(&nklock, s);
-               return 0;
+       if (xnthread_test_state(thread, XNJOINED)) {
+               ret = -EBUSY;
+               goto out;
        }
 
+       tag = thread->idtag;
+       if (xnthread_test_info(thread, XNDORMANT) || tag == 0)
+               goto out;
+
        trace_cobalt_thread_join(thread);
 
-       if (ipipe_root_p) {
-               if (xnthread_test_state(thread, XNJOINED)) {
-                       ret = -EBUSY;
-                       goto out;
-               }
-               xnthread_set_state(thread, XNJOINED);
+       xnthread_set_state(thread, XNJOINED);
+       
+       if (!xnthread_test_state(curr, XNRELAX|XNROOT)) {
+               xnlock_put_irqrestore(&nklock, s);
+               xnthread_relax(0, 0);
+               switched = 1;
+       } else
                xnlock_put_irqrestore(&nklock, s);
-               /*
-                * Only a very few threads are likely to terminate within a
-                * short time frame at any point in time, so experiencing a
-                * thundering herd effect due to synchronizing on a single
-                * wait queue is quite unlikely. In any case, we run in
-                * secondary mode.
-                */
-               if (uninterruptible)
-                       wait_event(nkjoinq, thread->idtag != tag);
-               else if (wait_event_interruptible(nkjoinq,
-                                                 thread->idtag != tag)) {
-                       xnlock_get_irqsave(&nklock, s);
-                       if (thread->idtag == tag)
-                               xnthread_clear_state(thread, XNJOINED);
-                       ret = -EINTR;
-                       goto out;
-               }
 
-               return 0;
-       }
+       if (uninterruptible)
+               wait_event(nkjoinq, thread->idtag != tag);
+       else if (wait_event_interruptible(nkjoinq,
+                                         thread->idtag != tag))
+               return -EINTR;
 
-       if (thread == xnthread_current())
-               ret = -EDEADLK;
-       else if (xnsynch_pended_p(&thread->join_synch))
-               ret = -EBUSY;
-       else {
-               xnthread_set_state(thread, XNJOINED);
-               ret = xnsynch_sleep_on(&thread->join_synch,
-                                      XN_INFINITE, XN_RELATIVE);
-               if ((ret & XNRMID) == 0 && thread->idtag == tag)
-                       xnthread_clear_state(thread, XNJOINED);
-               ret = ret & XNBREAK ? -EINTR : 0;
-       }
+       if (switched)
+               ret = xnthread_harden();
+
+       return ret;
 out:
        xnlock_put_irqrestore(&nklock, s);
 


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

Reply via email to