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

Author: Philippe Gerum <r...@xenomai.org>
Date:   Mon Nov 28 13:26:08 2011 +0100

cobalt, copperplate/syncobj: introduce fast internal events

Condvars are the basic mechanism used internally by Copperplate's
syncobj for implementing resource waits, so this ought to be fast and
optimized.

We introduce a streamlined internal version of Cobalt's condvar
support, and use it in Copperplate. This version removes all
extraneous code which is either redundant or useless when called from
the Copperplate innards.

---

 lib/cobalt/internal.c     |  109 +++++++++++++++++++++++++++++++++++++++++++++
 lib/cobalt/internal.h     |   11 +++++
 lib/copperplate/syncobj.c |   75 ++++++++++++++++++++++++++-----
 3 files changed, 183 insertions(+), 12 deletions(-)

diff --git a/lib/cobalt/internal.c b/lib/cobalt/internal.c
index 1d0787b..d09420c 100644
--- a/lib/cobalt/internal.c
+++ b/lib/cobalt/internal.c
@@ -26,6 +26,8 @@
 #include <sys/types.h>
 #include <semaphore.h>
 #include <cobalt/syscall.h>
+#include <kernel/cobalt/mutex.h>
+#include <kernel/cobalt/cond.h>
 #include <asm-generic/bits/current.h>
 
 extern int __cobalt_muxid;
@@ -44,3 +46,110 @@ int __cobalt_thread_stat(pthread_t tid, struct 
cobalt_threadstat *stat)
        return -XENOMAI_SKINCALL2(__cobalt_muxid,
                                  __cobalt_thread_getstat, tid, stat);
 }
+
+static inline unsigned long *cond_get_signalsp(struct __shadow_cond *shadow)
+{
+       if (likely(!shadow->attr.pshared))
+               return shadow->pending_signals;
+
+       return (unsigned long *)(xeno_sem_heap[1]
+                                + shadow->pending_signals_offset);
+}
+
+static inline struct mutex_dat *
+cond_get_mutex_datp(struct __shadow_cond *shadow)
+{
+       if (shadow->mutex_datp == (struct mutex_dat *)~0UL)
+               return NULL;
+
+       if (likely(!shadow->attr.pshared))
+               return shadow->mutex_datp;
+
+       return (struct mutex_dat *)(xeno_sem_heap[1]
+                                   + shadow->mutex_datp_offset);
+}
+
+int __cobalt_event_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+       struct __shadow_cond *_cnd;
+       struct __shadow_mutex *_mx;
+       unsigned int count;
+       int err, _err = 0;
+
+       _cnd = &((union __xeno_cond *)cond)->shadow_cond;
+       _mx = &((union __xeno_mutex *)mutex)->shadow_mutex;
+       count = _mx->lockcnt;
+
+       err = XENOMAI_SKINCALL5(__cobalt_muxid,
+                                __cobalt_cond_wait_prologue,
+                                _cnd, _mx, &_err, 0, NULL);
+       while (err == -EINTR)
+               err = XENOMAI_SKINCALL2(__cobalt_muxid,
+                                       __cobalt_cond_wait_epilogue, _cnd, _mx);
+
+       _mx->lockcnt = count;
+
+       return -err ?: -_err;
+}
+
+int __cobalt_event_timedwait(pthread_cond_t *cond,
+                            pthread_mutex_t *mutex,
+                            const struct timespec *abstime)
+{
+       struct __shadow_cond *_cnd;
+       struct __shadow_mutex *_mx;
+       unsigned int count;
+       int err, _err = 0;
+
+       _cnd = &((union __xeno_cond *)cond)->shadow_cond;
+       _mx = &((union __xeno_mutex *)mutex)->shadow_mutex;
+       count = _mx->lockcnt;
+
+       err = XENOMAI_SKINCALL5(__cobalt_muxid,
+                                __cobalt_cond_wait_prologue,
+                                _cnd, _mx, &_err, 1, abstime);
+       while (err == -EINTR)
+               err = XENOMAI_SKINCALL2(__cobalt_muxid,
+                                       __cobalt_cond_wait_epilogue, _cnd, _mx);
+
+       _mx->lockcnt = count;
+
+       return -err ?: -_err;
+}
+
+int __cobalt_event_signal(pthread_cond_t *cond)
+{
+       struct __shadow_cond *_cnd = &((union __xeno_cond *)cond)->shadow_cond;
+       unsigned long pending_signals, *pending_signalsp;
+       struct mutex_dat *mutex_datp;
+
+       mutex_datp = cond_get_mutex_datp(_cnd);
+       if (mutex_datp == NULL)
+               return 0;
+
+       mutex_datp->flags |= COBALT_MUTEX_COND_SIGNAL;
+
+       pending_signalsp = cond_get_signalsp(_cnd);
+       pending_signals = *pending_signalsp;
+       if (pending_signals != ~0UL)
+               *pending_signalsp = pending_signals + 1;
+
+       return 0;
+}
+
+int __cobalt_event_broadcast(pthread_cond_t *cond)
+{
+       struct mutex_dat *mutex_datp;
+       struct __shadow_cond *_cnd;
+
+       _cnd = &((union __xeno_cond *)cond)->shadow_cond;
+
+       mutex_datp = cond_get_mutex_datp(_cnd);
+       if (mutex_datp == NULL)
+               return 0;
+
+       mutex_datp->flags |= COBALT_MUTEX_COND_SIGNAL;
+       *cond_get_signalsp(_cnd) = ~0UL;
+
+       return 0;
+}
diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
index 83886c0..7d9b3b6 100644
--- a/lib/cobalt/internal.h
+++ b/lib/cobalt/internal.h
@@ -6,4 +6,15 @@ void __cobalt_thread_harden(void);
 int __cobalt_thread_stat(pthread_t tid,
                         struct cobalt_threadstat *stat);
 
+int __cobalt_event_wait(pthread_cond_t *cond,
+                       pthread_mutex_t *mutex);
+
+int __cobalt_event_timedwait(pthread_cond_t *cond,
+                            pthread_mutex_t *mutex,
+                            const struct timespec *abstime);
+
+int __cobalt_event_signal(pthread_cond_t *cond);
+
+int __cobalt_event_broadcast(pthread_cond_t *cond);
+
 #endif /* XENO_COBALT_INTERNAL_H */
diff --git a/lib/copperplate/syncobj.c b/lib/copperplate/syncobj.c
index 95f75f3..f099d6a 100644
--- a/lib/copperplate/syncobj.c
+++ b/lib/copperplate/syncobj.c
@@ -55,6 +55,58 @@
  * normal runtime conditions.
  */
 
+#ifdef CONFIG_XENO_COBALT
+
+#include "cobalt/internal.h"
+
+static inline void signal_cond(pthread_cond_t *cond)
+{
+       __cobalt_event_signal(cond);
+}
+
+static inline int wait_cond(pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+       return __cobalt_event_wait(cond, mutex);
+}
+
+static inline int timedwait_cond(pthread_cond_t *cond,
+                                pthread_mutex_t *mutex,
+                                const struct timespec *abstime)
+{
+       return __cobalt_event_timedwait(cond, mutex, abstime);
+}
+
+static inline void broadcast_cond(pthread_cond_t *cond)
+{
+       __cobalt_event_broadcast(cond);
+}
+
+#else /* CONFIG_XENO_MERCURY */
+
+static inline void signal_cond(pthread_cond_t *cond)
+{
+       pthread_cond_signal(cond);
+}
+
+static inline int wait_cond(pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+       return pthread_cond_wait(cond, mutex);
+}
+
+static inline int timedwait_cond(pthread_cond_t *cond,
+                                pthread_mutex_t *mutex,
+                                const struct timespec *abstime)
+{
+       return pthread_cond_timedwait(cond, mutex, abstime);
+}
+
+static inline void broadcast_cond(pthread_cond_t *cond)
+{
+       pthread_cond_broadcast(cond);
+}
+
+#endif /* CONFIG_XENO_MERCURY */
+
 void syncobj_init(struct syncobj *sobj, int flags,
                  fnref_type(void (*)(struct syncobj *sobj)) finalizer)
 {
@@ -133,7 +185,7 @@ int __syncobj_signal_drain(struct syncobj *sobj)
 {
        /* Release one thread waiting for the object to drain. */
        --sobj->drain_count;
-       __RT(pthread_cond_signal(&sobj->post_sync));
+       signal_cond(&sobj->post_sync);
 
        return 1;
 }
@@ -187,11 +239,10 @@ int syncobj_pend(struct syncobj *sobj, const struct 
timespec *timeout,
 
        do {
                if (timeout)
-                       ret = __RT(pthread_cond_timedwait(&current->wait_sync,
-                                                         &sobj->lock, 
timeout));
+                       ret = timedwait_cond(&current->wait_sync,
+                                            &sobj->lock, timeout);
                else
-                       ret = __RT(pthread_cond_wait(&current->wait_sync,
-                                                    &sobj->lock));
+                       ret = wait_cond(&current->wait_sync, &sobj->lock);
                /* Check for spurious wake up. */
        } while (ret == 0 && holder_linked(&current->wait_link));
 
@@ -227,7 +278,7 @@ void syncobj_wakeup_waiter(struct syncobj *sobj, struct 
threadobj *thobj)
 {
        list_remove_init(&thobj->wait_link);
        sobj->pend_count--;
-       __RT(pthread_cond_signal(&thobj->wait_sync));
+       signal_cond(&thobj->wait_sync);
 }
 
 struct threadobj *syncobj_post(struct syncobj *sobj)
@@ -239,7 +290,7 @@ struct threadobj *syncobj_post(struct syncobj *sobj)
 
        thobj = list_pop_entry(&sobj->pend_list, struct threadobj, wait_link);
        sobj->pend_count--;
-       __RT(pthread_cond_signal(&thobj->wait_sync));
+       signal_cond(&thobj->wait_sync);
 
        return thobj;
 }
@@ -289,10 +340,10 @@ int syncobj_wait_drain(struct syncobj *sobj, const struct 
timespec *timeout,
                current->wait_hook(current, SYNCOBJ_BLOCK);
 
        if (timeout)
-               ret = __RT(pthread_cond_timedwait(&sobj->post_sync,
-                                                 &sobj->lock, timeout));
+               ret = timedwait_cond(&sobj->post_sync,
+                                    &sobj->lock, timeout);
        else
-               ret = __RT(pthread_cond_wait(&sobj->post_sync, &sobj->lock));
+               ret = wait_cond(&sobj->post_sync, &sobj->lock);
 
        pthread_setcancelstate(state, NULL);
 
@@ -329,7 +380,7 @@ int syncobj_flush(struct syncobj *sobj, int reason)
                thobj = list_pop_entry(&sobj->pend_list,
                                       struct threadobj, wait_link);
                thobj->wait_status |= reason;
-               __RT(pthread_cond_signal(&thobj->wait_sync));
+               signal_cond(&thobj->wait_sync);
                sobj->release_count++;
        }
        sobj->pend_count = 0;
@@ -342,7 +393,7 @@ int syncobj_flush(struct syncobj *sobj, int reason)
                } while (!list_empty(&sobj->drain_list));
                sobj->release_count += sobj->drain_count;
                sobj->drain_count = 0;
-               __RT(pthread_cond_broadcast(&sobj->post_sync));
+               broadcast_cond(&sobj->post_sync);
        }
 
        return sobj->release_count;


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

Reply via email to