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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sat Dec  3 22:04:47 2011 +0100

nucleus/synch: inline fast path of xnsynch_release()

---

 include/cobalt/nucleus/synch.h  |    6 +-
 include/cobalt/nucleus/thread.h |   25 ++++++
 include/rtdm/rtdm_driver.h      |    3 +-
 kernel/cobalt/monitor.c         |    6 +-
 kernel/cobalt/mutex.h           |    2 +-
 kernel/cobalt/nucleus/synch.c   |  156 ++++++++++++++++++--------------------
 6 files changed, 109 insertions(+), 89 deletions(-)

diff --git a/include/cobalt/nucleus/synch.h b/include/cobalt/nucleus/synch.h
index be56dde..42e4fbe 100644
--- a/include/cobalt/nucleus/synch.h
+++ b/include/cobalt/nucleus/synch.h
@@ -136,6 +136,10 @@ typedef struct xnsynch {
 extern "C" {
 #endif
 
+void __xnsynch_fixup_rescnt(struct xnthread *thread);
+
+struct xnthread *__xnsynch_transfer_ownership(struct xnsynch *synch,
+                                             struct xnthread *lastowner);
 #if XENO_DEBUG(SYNCH_RELAX)
 
 void xnsynch_detect_relaxed_owner(struct xnsynch *synch,
@@ -188,8 +192,6 @@ xnflags_t xnsynch_acquire(struct xnsynch *synch,
                          xnticks_t timeout,
                          xntmode_t timeout_mode);
 
-struct xnthread *xnsynch_release(struct xnsynch *synch);
-
 struct xnthread *xnsynch_peek_pendq(struct xnsynch *synch);
 
 int xnsynch_flush(struct xnsynch *synch, xnflags_t reason);
diff --git a/include/cobalt/nucleus/thread.h b/include/cobalt/nucleus/thread.h
index 5140e86..b8c4511 100644
--- a/include/cobalt/nucleus/thread.h
+++ b/include/cobalt/nucleus/thread.h
@@ -398,6 +398,31 @@ struct xnthread *xnthread_lookup(xnhandle_t threadh)
        return (thread && xnthread_handle(thread) == threadh) ? thread : NULL;
 }
 
+/*
+ * XXX: Mutual dependency issue with synch.h, we have to define
+ * xnsynch_release() here.
+ */
+static inline struct xnthread *
+xnsynch_release(struct xnsynch *synch, struct xnthread *thread)
+{
+       xnarch_atomic_t *lockp;
+       xnhandle_t threadh;
+
+       XENO_BUGON(NUCLEUS, !testbits(synch->status, XNSYNCH_OWNER));
+
+       trace_mark(xn_nucleus, synch_release, "synch %p", synch);
+
+       if (unlikely(xnthread_test_state(thread, XNOTHER)))
+               __xnsynch_fixup_rescnt(thread);
+
+       lockp = xnsynch_fastlock(synch);
+       threadh = xnthread_handle(thread);
+       if (likely(xnsynch_fast_release(lockp, threadh)))
+               return NULL;
+
+       return __xnsynch_transfer_ownership(synch, thread);
+}
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/include/rtdm/rtdm_driver.h b/include/rtdm/rtdm_driver.h
index 0138421..b3b4dd9 100644
--- a/include/rtdm/rtdm_driver.h
+++ b/include/rtdm/rtdm_driver.h
@@ -1212,7 +1212,8 @@ static inline void rtdm_mutex_unlock(rtdm_mutex_t *mutex)
 
        trace_mark(xn_rtdm, mutex_unlock, "mutex %p", mutex);
 
-       if (unlikely(xnsynch_release(&mutex->synch_base) != NULL))
+       if (unlikely(xnsynch_release(&mutex->synch_base,
+                                    xnpod_current_thread()) != NULL))
                xnpod_schedule();
 }
 
diff --git a/kernel/cobalt/monitor.c b/kernel/cobalt/monitor.c
index 6a3ff1b..d6f807e 100644
--- a/kernel/cobalt/monitor.c
+++ b/kernel/cobalt/monitor.c
@@ -255,7 +255,7 @@ int cobalt_monitor_wait(struct cobalt_monitor_shadow __user 
*u_monsh,
        }
 
        /* Release the gate prior to waiting, all atomically. */
-       xnsynch_release(&mon->gate);
+       xnsynch_release(&mon->gate, &cur->threadbase);
 
        synch = &cur->monitor_synch;
        if (event & COBALT_MONITOR_WAITDRAIN)
@@ -314,7 +314,7 @@ int cobalt_monitor_sync(struct cobalt_monitor_shadow __user 
*u_monsh)
 
        if (mon->data->flags & COBALT_MONITOR_SIGNALED) {
                cobalt_monitor_wakeup(mon);
-               xnsynch_release(&mon->gate);
+               xnsynch_release(&mon->gate, xnpod_current_thread());
                xnpod_schedule();
                ret = cobalt_monitor_enter_inner(mon);
        }
@@ -343,7 +343,7 @@ int cobalt_monitor_exit(struct cobalt_monitor_shadow __user 
*u_monsh)
        if (mon->data->flags & COBALT_MONITOR_SIGNALED)
                cobalt_monitor_wakeup(mon);
 
-       xnsynch_release(&mon->gate);
+       xnsynch_release(&mon->gate, xnpod_current_thread());
        xnpod_schedule();
 out:
        xnlock_put_irqrestore(&nklock, s);
diff --git a/kernel/cobalt/mutex.h b/kernel/cobalt/mutex.h
index 82bbf05..feba86f 100644
--- a/kernel/cobalt/mutex.h
+++ b/kernel/cobalt/mutex.h
@@ -119,7 +119,7 @@ static inline int cobalt_mutex_release(xnthread_t *cur, 
cobalt_mutex_t *mutex)
                        need_resched |= cobalt_cond_deferred_signals(cond);
                }
        }
-       need_resched |= xnsynch_release(&mutex->synchbase) != NULL;
+       need_resched |= xnsynch_release(&mutex->synchbase, cur) != NULL;
 
        return need_resched;
 }
diff --git a/kernel/cobalt/nucleus/synch.c b/kernel/cobalt/nucleus/synch.c
index b7bc202..50f3cc3 100644
--- a/kernel/cobalt/nucleus/synch.c
+++ b/kernel/cobalt/nucleus/synch.c
@@ -572,6 +572,46 @@ xnflags_t xnsynch_acquire(struct xnsynch *synch, xnticks_t 
timeout,
 EXPORT_SYMBOL_GPL(xnsynch_acquire);
 
 /*!
+ * \fn struct xnthread *xnsynch_release(struct xnsynch *synch, struct xnthread 
*owner);
+ * \brief Give the resource ownership to the next waiting thread.
+ *
+ * This service releases the ownership of the given synchronization
+ * object. The thread which is currently leading the object's pending
+ * list, if any, is unblocked from its pending state. However, no
+ * reschedule is performed.
+ *
+ * This service must be used only with synchronization objects that
+ * track ownership (XNSYNCH_OWNER set).
+ *
+ * @param synch The descriptor address of the synchronization object
+ * whose ownership is changed.
+ *
+ * @param owner The descriptor address of the current owner.
+ *
+ * @return The descriptor address of the unblocked thread.
+ *
+ * Side-effects:
+ *
+ * - The effective priority of the previous resource owner might be
+ * lowered to its base priority value as a consequence of the priority
+ * inheritance boost being cleared.
+ *
+ * - The synchronization object ownership is transfered to the
+ * unblocked thread.
+ *
+ * Environments:
+ *
+ * This service can be called from:
+ *
+ * - Kernel module initialization/cleanup code
+ * - Interrupt service routine
+ * - Kernel-based task
+ * - User-space task
+ *
+ * Rescheduling: never.
+ */
+
+/*!
  * @internal
  * \fn void xnsynch_clear_boost(struct xnsynch *synch, struct xnthread *owner);
  * \brief Clear the priority boost.
@@ -680,105 +720,56 @@ void xnsynch_requeue_sleeper(struct xnthread *thread)
 }
 EXPORT_SYMBOL_GPL(xnsynch_requeue_sleeper);
 
-static inline struct xnthread *
-xnsynch_release_thread(struct xnsynch *synch, struct xnthread *lastowner)
+void __xnsynch_fixup_rescnt(struct xnthread *thread)
+{
+       if (xnthread_get_rescnt(thread) == 0)
+               xnshadow_send_sig(thread, SIGDEBUG,
+                                 SIGDEBUG_MIGRATE_PRIOINV, 1);
+       else
+               xnthread_dec_rescnt(thread);
+}
+EXPORT_SYMBOL_GPL(__xnsynch_fixup_rescnt);
+
+struct xnthread *__xnsynch_transfer_ownership(struct xnsynch *synch,
+                                             struct xnthread *lastowner)
 {
-       xnhandle_t lastownerh, newownerh;
        struct xnthread *newowner;
        struct xnpholder *holder;
        xnarch_atomic_t *lockp;
+       xnhandle_t newownerh;
        spl_t s;
 
-       XENO_BUGON(NUCLEUS, !testbits(synch->status, XNSYNCH_OWNER));
-
-       if (xnthread_test_state(lastowner, XNOTHER)) {
-               if (xnthread_get_rescnt(lastowner) == 0)
-                       xnshadow_send_sig(lastowner, SIGDEBUG,
-                                         SIGDEBUG_MIGRATE_PRIOINV, 1);
-               else
-                       xnthread_dec_rescnt(lastowner);
-       }
-
-       lastownerh = xnthread_handle(lastowner);
-       if (xnsynch_fast_release(xnsynch_fastlock(synch), lastownerh))
-               return NULL;    /* This is a BUG, we should have one. */
-
        xnlock_get_irqsave(&nklock, s);
 
-       trace_mark(xn_nucleus, synch_release, "synch %p", synch);
+       lockp = xnsynch_fastlock(synch);
 
-       holder = getpq(&synch->pendq);
-       if (holder) {
-               newowner = link2thread(holder, plink);
-               newowner->wchan = NULL;
-               newowner->wwake = synch;
-               synch->owner = newowner;
-               xnthread_set_info(newowner, XNWAKEN);
-               xnpod_resume_thread(newowner, XNPEND);
-
-               if (testbits(synch->status, XNSYNCH_CLAIMED))
-                       xnsynch_clear_boost(synch, lastowner);
-
-               newownerh = xnsynch_fast_set_claimed(xnthread_handle(newowner),
-                                                    xnsynch_pended_p(synch));
-       } else {
-               newowner = NULL;
+       if (emptypq_p(&synch->pendq)) {
                synch->owner = NULL;
-               newownerh = XN_NO_HANDLE;
+               xnarch_atomic_set(lockp, XN_NO_HANDLE);
+               xnlock_put_irqrestore(&nklock, s);
+               return NULL;
        }
 
-       lockp = xnsynch_fastlock(synch);
+       holder = getpq(&synch->pendq);
+       newowner = link2thread(holder, plink);
+       newowner->wchan = NULL;
+       newowner->wwake = synch;
+       synch->owner = newowner;
+       xnthread_set_info(newowner, XNWAKEN);
+       xnpod_resume_thread(newowner, XNPEND);
+
+       if (testbits(synch->status, XNSYNCH_CLAIMED))
+               xnsynch_clear_boost(synch, lastowner);
+
+       newownerh = xnsynch_fast_set_claimed(xnthread_handle(newowner),
+                                            xnsynch_pended_p(synch));
        xnarch_atomic_set(lockp, newownerh);
 
        xnlock_put_irqrestore(&nklock, s);
 
-       xnarch_post_graph_if(synch, 0, emptypq_p(&synch->pendq));
-
        return newowner;
 }
-
-/*!
- * \fn struct xnthread *xnsynch_release(struct xnsynch *synch);
- * \brief Give the resource ownership to the next waiting thread.
- *
- * This service releases the ownership of the given synchronization
- * object. The thread which is currently leading the object's pending
- * list, if any, is unblocked from its pending state. However, no
- * reschedule is performed.
- *
- * This service must be used only with synchronization objects that
- * track ownership (XNSYNCH_OWNER set).
- *
- * @param synch The descriptor address of the synchronization object
- * whose ownership is changed.
- *
- * @return The descriptor address of the unblocked thread.
- *
- * Side-effects:
- *
- * - The effective priority of the previous resource owner might be
- * lowered to its base priority value as a consequence of the priority
- * inheritance boost being cleared.
- *
- * - The synchronization object ownership is transfered to the
- * unblocked thread.
- *
- * Environments:
- *
- * This service can be called from:
- *
- * - Kernel module initialization/cleanup code
- * - Interrupt service routine
- * - Kernel-based task
- * - User-space task
- *
- * Rescheduling: never.
- */
-struct xnthread *xnsynch_release(struct xnsynch *synch)
-{
-       return xnsynch_release_thread(synch, xnpod_current_thread());
-}
-EXPORT_SYMBOL_GPL(xnsynch_release);
+EXPORT_SYMBOL_GPL(__xnsynch_transfer_ownership);
 
 /*!
  * \fn struct xnthread *xnsynch_peek_pendq(struct xnsynch *synch);
@@ -813,6 +804,7 @@ struct xnthread *xnsynch_peek_pendq(struct xnsynch *synch)
        holder = getheadpq(&synch->pendq);
        if (holder)
                thread = link2thread(holder, plink);
+
        xnlock_put_irqrestore(&nklock, s);
 
        return thread;
@@ -993,7 +985,7 @@ void xnsynch_release_all_ownerships(struct xnthread *thread)
                 */
                synch = link2synch(holder);
                nholder = nextpq(&thread->claimq, holder);
-               xnsynch_release_thread(synch, thread);
+               xnsynch_release(synch, thread);
                if (synch->cleanup)
                        synch->cleanup(synch);
        }


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

Reply via email to