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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sat Dec  3 18:49:52 2011 +0100

cobalt/monitor: dequeue GRANT waiters on the wakeup side

---

 kernel/cobalt/monitor.c |   57 +++++++++++++++++++++++++++++-----------------
 1 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/kernel/cobalt/monitor.c b/kernel/cobalt/monitor.c
index 2ce195c..6a3ff1b 100644
--- a/kernel/cobalt/monitor.c
+++ b/kernel/cobalt/monitor.c
@@ -174,15 +174,29 @@ static int cobalt_monitor_wakeup(struct cobalt_monitor 
*mon)
         * Unblock waiters requesting a grant, either those who
         * received it only or all of them, depending on the broadcast
         * bit.
+        *
+        * We update the PENDED flag to inform userland about the
+        * presence of waiters, so that it may decide not to issue any
+        * syscall for exiting the monitor if nobody else is waiting
+        * at the gate.
         */
        bcast = (datp->flags & COBALT_MONITOR_BROADCAST) != 0;
-       for (h = getheadq(&mon->waiters); h; h = nextq(&mon->waiters, h)) {
+       h = getheadq(&mon->waiters);
+       while (h) {
                tid = container_of(h, struct cobalt_thread, monitor_link);
+               h = nextq(&mon->waiters, h);
                p = &tid->threadbase;
+               /*
+                * A thread might receive XNGRANT albeit it does not
+                * wait on a monitor, or it might have timed out
+                * before we got there, so we really have to check
+                * that ->wchan does match our sleep queue.
+                */
                if (bcast || ((*p->u_mode & XNGRANT) &&
                              p->wchan == &tid->monitor_synch)) {
                        xnsynch_wakeup_this_sleeper(&tid->monitor_synch,
                                                    &p->plink);
+                       removeq(&mon->waiters, &tid->monitor_link);
                        resched = 1;
                }
        }
@@ -201,6 +215,11 @@ drain:
                                != NULL;
        }
 
+       if (resched &&
+           emptyq_p(&mon->waiters) &&
+           !xnsynch_pended_p(&mon->drain))
+               mon->data->flags &= ~COBALT_MONITOR_PENDED;
+
        return resched;
 }
 
@@ -248,29 +267,25 @@ int cobalt_monitor_wait(struct cobalt_monitor_shadow 
__user *u_monsh,
        mon->data->flags |= COBALT_MONITOR_PENDED;
 
        info = xnsynch_sleep_on(synch, timeout, tmode);
-       if ((info & XNRMID) != 0 ||
-           !cobalt_obj_active(mon, COBALT_MONITOR_MAGIC,
-                              struct cobalt_monitor)) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (info) {
+               if ((info & XNRMID) != 0 ||
+                   !cobalt_obj_active(mon, COBALT_MONITOR_MAGIC,
+                                      struct cobalt_monitor)) {
+                       ret = -EINVAL;
+                       goto out;
+               }
 
-       /*
-        * We update the PENDED flag to inform userland about the
-        * presence of waiters, so that it may decide not to issue any
-        * syscall for exiting the monitor if there is nobody else
-        * waiting at the gate.
-        */
-       if ((event & COBALT_MONITOR_WAITDRAIN) == 0)
-               removeq(&mon->waiters, &cur->monitor_link);
+               if ((event & COBALT_MONITOR_WAITDRAIN) == 0)
+                       removeq(&mon->waiters, &cur->monitor_link);
 
-       if (emptyq_p(&mon->waiters) && !xnsynch_pended_p(&mon->drain))
-               mon->data->flags &= ~COBALT_MONITOR_PENDED;
+               if (emptyq_p(&mon->waiters) && !xnsynch_pended_p(&mon->drain))
+                       mon->data->flags &= ~COBALT_MONITOR_PENDED;
 
-       if (info & XNBREAK)
-               opret = -EINTR;
-       else if (info & XNTIMEO)
-               opret = -ETIMEDOUT;
+               if (info & XNBREAK)
+                       opret = -EINTR;
+               else if (info & XNTIMEO)
+                       opret = -ETIMEDOUT;
+       }
 
        ret = cobalt_monitor_enter_inner(mon);
 out:


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

Reply via email to