Module: xenomai-forge Branch: master Commit: fa98315c3a3b40f72739fcdef02241cec1e0872c URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=fa98315c3a3b40f72739fcdef02241cec1e0872c
Author: Philippe Gerum <r...@xenomai.org> Date: Tue Jun 18 21:52:28 2013 +0200 cobalt/kernel/synch: turn claimq into regular kernel list --- include/cobalt/kernel/registry.h | 1 + include/cobalt/kernel/synch.h | 21 ++---- include/cobalt/kernel/thread.h | 12 +++- kernel/cobalt/synch.c | 160 ++++++++++++++++++-------------------- kernel/cobalt/thread.c | 2 +- 5 files changed, 96 insertions(+), 100 deletions(-) diff --git a/include/cobalt/kernel/registry.h b/include/cobalt/kernel/registry.h index 554686b..190ddfe 100644 --- a/include/cobalt/kernel/registry.h +++ b/include/cobalt/kernel/registry.h @@ -30,6 +30,7 @@ #ifdef __KERNEL__ +#include <cobalt/kernel/queue.h> #include <cobalt/kernel/synch.h> #include <cobalt/kernel/vfile.h> diff --git a/include/cobalt/kernel/synch.h b/include/cobalt/kernel/synch.h index 605f5ef..523b6f2 100644 --- a/include/cobalt/kernel/synch.h +++ b/include/cobalt/kernel/synch.h @@ -73,7 +73,6 @@ static inline int xnsynch_fast_release(atomic_long_t *fastlock, #ifdef __KERNEL__ #include <cobalt/kernel/list.h> -#include <cobalt/kernel/queue.h> #define XNSYNCH_CLAIMED 0x10 /* Claimed by other thread(s) w/ PIP */ @@ -98,19 +97,13 @@ struct xnthread; struct xnsynch; typedef struct xnsynch { - - xnpholder_t link; /* Link in claim queues */ - - xnflags_t status; /* Status word */ - - struct list_head pendq; /* Pending threads */ - - struct xnthread *owner; /* Thread which owns the resource */ - - atomic_long_t *fastlock; /* Pointer to fast lock word */ - - void (*cleanup)(struct xnsynch *synch); /* Cleanup handler */ - + struct list_head link; /** thread->claimq */ + int wprio; /** wait prio in claimq */ + xnflags_t status; /** Status word */ + struct list_head pendq; /** Pending threads */ + struct xnthread *owner; /** Thread which owns the resource */ + atomic_long_t *fastlock; /** Pointer to fast lock word */ + void (*cleanup)(struct xnsynch *synch); /* Cleanup handler */ } xnsynch_t; #define xnsynch_test_flags(synch,flags) testbits((synch)->status,flags) diff --git a/include/cobalt/kernel/thread.h b/include/cobalt/kernel/thread.h index 861f341..4cc8ad4 100644 --- a/include/cobalt/kernel/thread.h +++ b/include/cobalt/kernel/thread.h @@ -233,7 +233,11 @@ typedef struct xnthread { #define link2thread(ln, fld) container_of(ln, struct xnthread, fld) - xnpqueue_t claimq; /* Owned resources claimed by others (PIP) */ + /** + * List of xnsynch owned by this thread _and_ claimed by + * others (PIP). + */ + struct list_head claimq; struct xnsynch *wchan; /* Resource the thread pends on */ @@ -343,6 +347,12 @@ typedef struct xnthread { #define xnthread_private(thread) ((thread)->privdata) #define xnthread_personality(thread) ((thread)->personality) +#define xnthread_for_each_claimed(__pos, __thread) \ + list_for_each_entry(__pos, &(__thread)->claimq, link) + +#define xnthread_for_each_claimed_safe(__pos, __tmp, __thread) \ + list_for_each_entry_safe(__pos, __tmp, &(__thread)->claimq, link) + #define xnthread_run_handler(__t, __h) \ do { \ struct xnpersonality *__p__ = (__t)->personality; \ diff --git a/kernel/cobalt/synch.c b/kernel/cobalt/synch.c index 383359d..f238af9 100644 --- a/kernel/cobalt/synch.c +++ b/kernel/cobalt/synch.c @@ -99,14 +99,13 @@ void xnsynch_init(struct xnsynch *synch, xnflags_t flags, atomic_long_t *fastlock) { - initph(&synch->link); - if (flags & XNSYNCH_PIP) flags |= XNSYNCH_PRIO | XNSYNCH_OWNER; /* Obviously... */ synch->status = flags & ~XNSYNCH_CLAIMED; synch->owner = NULL; synch->cleanup = NULL; /* Only works for PIP-enabled objects. */ + synch->wprio = -1; INIT_LIST_HEAD(&synch->pendq); if (flags & XNSYNCH_OWNER) { @@ -278,7 +277,7 @@ out: EXPORT_SYMBOL_GPL(xnsynch_wakeup_many_sleepers); /*! - * \fn void xnsynch_wakeup_this_sleeper(struct xnsynch *synch, struct xnpholder *holder); + * \fn void xnsynch_wakeup_this_sleeper(struct xnsynch *synch, struct xnthread *sleeper); * \brief Unblock a particular thread from wait. * * This service wakes up a specific thread which is currently pending on @@ -422,12 +421,13 @@ xnflags_t xnsynch_acquire(struct xnsynch *synch, xnticks_t timeout, xnlock_get_irqsave(&nklock, s); - /* Set claimed bit. - In case it appears to be set already, re-read its state - under nklock so that we don't miss any change between the - lock-less read and here. But also try to avoid cmpxchg - where possible. Only if it appears not to be set, start - with cmpxchg directly. */ + /* + * Set claimed bit. In case it appears to be set already, + * re-read its state under nklock so that we don't miss any + * change between the lock-less read and here. But also try to + * avoid cmpxchg where possible. Only if it appears not to be + * set, start with cmpxchg directly. + */ if (xnsynch_fast_is_claimed(fastlock)) { old = atomic_long_read(lockp); goto test_no_owner; @@ -480,11 +480,12 @@ xnflags_t xnsynch_acquire(struct xnsynch *synch, xnticks_t timeout, } if (testbits(synch->status, XNSYNCH_CLAIMED)) - removepq(&owner->claimq, &synch->link); + list_del(&synch->link); else __setbits(synch->status, XNSYNCH_CLAIMED); - insertpqf(&owner->claimq, &synch->link, thread->wprio); + synch->wprio = thread->wprio; + list_add_priff(synch, &owner->claimq, wprio, link); xnsynch_renice_thread(owner, thread); } } else @@ -597,16 +598,16 @@ static void xnsynch_clear_boost(struct xnsynch *synch, struct xnsynch *hsynch; int wprio; - removepq(&owner->claimq, &synch->link); + list_del(&synch->link); __clrbits(synch->status, XNSYNCH_CLAIMED); wprio = owner->bprio + owner->sched_class->weight; - if (emptypq_p(&owner->claimq)) { + if (list_empty(&owner->claimq)) { xnthread_clear_state(owner, XNBOOST); target = owner; } else { /* Find the highest priority needed to enforce the PIP. */ - hsynch = container_of(getheadpq(&owner->claimq), struct xnsynch, link); + hsynch = list_first_entry(&owner->claimq, struct xnsynch, link); XENO_BUGON(NUCLEUS, list_empty(&hsynch->pendq)); target = list_first_entry(&hsynch->pendq, struct xnthread, plink); if (target->wprio > wprio) @@ -645,39 +646,39 @@ void xnsynch_requeue_sleeper(struct xnthread *thread) list_add_priff(thread, &synch->pendq, wprio, plink); owner = synch->owner; - if (owner != NULL && thread->wprio > owner->wprio) { + if (owner == NULL || thread->wprio <= owner->wprio) + return; + + /* + * The new (weighted) priority of the sleeping thread is + * higher than the priority of the current owner of the + * resource: we need to update the PI state. + */ + synch->wprio = thread->wprio; + if (testbits(synch->status, XNSYNCH_CLAIMED)) { /* - * The new (weighted) priority of the sleeping thread - * is higher than the priority of the current owner of - * the resource: we need to update the PI state. + * The resource is already claimed, just reorder the + * claim queue. */ - if (testbits(synch->status, XNSYNCH_CLAIMED)) { - /* - * The resource is already claimed, just - * reorder the claim queue. - */ - removepq(&owner->claimq, &synch->link); - insertpqf(&owner->claimq, &synch->link, - thread->wprio); - } else { - /* - * The resource was NOT claimed, claim it now - * and boost the owner. - */ - __setbits(synch->status, XNSYNCH_CLAIMED); - insertpqf(&owner->claimq, &synch->link, - thread->wprio); - if (!xnthread_test_state(owner, XNBOOST)) { - owner->bprio = owner->cprio; - xnthread_set_state(owner, XNBOOST); - } - } + list_del(&synch->link); + list_add_priff(synch, &owner->claimq, wprio, link); + } else { /* - * Renice the owner thread, progressing in the PI - * chain as needed. + * The resource was NOT claimed, claim it now and + * boost the owner. */ - xnsynch_renice_thread(owner, thread); + __setbits(synch->status, XNSYNCH_CLAIMED); + list_add_priff(synch, &owner->claimq, wprio, link); + if (!xnthread_test_state(owner, XNBOOST)) { + owner->bprio = owner->cprio; + xnthread_set_state(owner, XNBOOST); + } } + /* + * Renice the owner thread, progressing in the PI chain as + * needed. + */ + xnsynch_renice_thread(owner, thread); } EXPORT_SYMBOL_GPL(xnsynch_requeue_sleeper); @@ -875,9 +876,8 @@ EXPORT_SYMBOL_GPL(xnsynch_flush); void xnsynch_forget_sleeper(struct xnthread *thread) { - struct xnsynch *synch = thread->wchan; + struct xnsynch *synch = thread->wchan, *nsynch; struct xnthread *owner, *target; - struct xnpholder *h; trace_mark(xn_nucleus, synch_forget, "thread %p thread_name %s synch %p", @@ -887,32 +887,35 @@ void xnsynch_forget_sleeper(struct xnthread *thread) thread->wchan = NULL; list_del(&thread->plink); - if (testbits(synch->status, XNSYNCH_CLAIMED)) { - /* Find the highest priority needed to enforce the PIP. */ - owner = synch->owner; - if (list_empty(&synch->pendq)) - /* No more sleepers: clear the boost. */ - xnsynch_clear_boost(synch, owner); - else { - target = list_first_entry(&synch->pendq, struct xnthread, plink); - h = getheadpq(&owner->claimq); - if (target->wprio != h->prio) { - /* - * Reorder the claim queue, and lower - * the priority to the required - * minimum needed to prevent priority - * inversion. - */ - removepq(&owner->claimq, &synch->link); - insertpqf(&owner->claimq, &synch->link, - target->wprio); - - h = getheadpq(&owner->claimq); - if (h->prio < owner->wprio) - xnsynch_renice_thread(owner, target); - } - } + if (!testbits(synch->status, XNSYNCH_CLAIMED)) + return; + + /* Find the highest priority needed to enforce the PIP. */ + owner = synch->owner; + + if (list_empty(&synch->pendq)) { + /* No more sleepers: clear the boost. */ + xnsynch_clear_boost(synch, owner); + return; } + + target = list_first_entry(&synch->pendq, struct xnthread, plink); + nsynch = list_first_entry(&owner->claimq, struct xnsynch, link); + + if (target->wprio == nsynch->wprio) + return; /* No change. */ + + /* + * Reorder the claim queue, and lower the priority to the + * required minimum needed to prevent priority inversion. + */ + synch->wprio = target->wprio; + list_del(&synch->link); + list_add_priff(synch, &owner->claimq, wprio, link); + + nsynch = list_first_entry(&owner->claimq, struct xnsynch, link); + if (nsynch->wprio < owner->wprio) + xnsynch_renice_thread(owner, target); } EXPORT_SYMBOL_GPL(xnsynch_forget_sleeper); @@ -932,17 +935,9 @@ EXPORT_SYMBOL_GPL(xnsynch_forget_sleeper); void xnsynch_release_all_ownerships(struct xnthread *thread) { - struct xnpholder *holder, *nholder; - struct xnsynch *synch; + struct xnsynch *synch, *tmp; - for (holder = getheadpq(&thread->claimq); holder != NULL; - holder = nholder) { - /* - * Since xnsynch_release() alters the claim queue, we - * need to be conservative while scanning it. - */ - synch = container_of(holder, struct xnsynch, link); - nholder = nextpq(&thread->claimq, holder); + xnthread_for_each_claimed_safe(synch, tmp, thread) { xnsynch_release(synch, thread); if (synch->cleanup) synch->cleanup(synch); @@ -980,12 +975,9 @@ void xnsynch_detect_claimed_relax(struct xnthread *owner) { struct xnthread *sleeper; struct xnsynch *synch; - struct xnpholder *hs; - for (hs = getheadpq(&owner->claimq); hs != NULL; - hs = nextpq(&owner->claimq, hs)) { - synch = container_of(hs, struct xnsynch, link); - list_for_each_entry(sleeper, &synch->pendq, plink) { + xnthread_for_each_claimed(synch, owner) { + xnsynch_for_each_sleeper(sleeper, synch) { if (xnthread_test_state(sleeper, XNTRAPSW)) { xnthread_set_info(sleeper, XNSWREP); xnshadow_send_sig(sleeper, SIGDEBUG, diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c index 6b8b3b1..70400bb 100644 --- a/kernel/cobalt/thread.c +++ b/kernel/cobalt/thread.c @@ -183,7 +183,7 @@ int xnthread_init(struct xnthread *thread, inith(&thread->glink); initph(&thread->rlink); thread->selector = NULL; - initpq(&thread->claimq); + INIT_LIST_HEAD(&thread->claimq); thread->privdata = NULL; thread->personality = attr->personality; _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git