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(¤t->wait_sync, - &sobj->lock, timeout)); + ret = timedwait_cond(¤t->wait_sync, + &sobj->lock, timeout); else - ret = __RT(pthread_cond_wait(¤t->wait_sync, - &sobj->lock)); + ret = wait_cond(¤t->wait_sync, &sobj->lock); /* Check for spurious wake up. */ } while (ret == 0 && holder_linked(¤t->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