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