mcs: return pointer from refill_head and others

A previous commit produced some build errors, since it converted the
`REFILL_HEAD` and `REFILL_TAIL` macros to functions returning
`refill_t`, and the results were used as lvalues. This commit returns
pointers instead, and also converts `REFILL_INDEX` to a function.

Signed-off-by: Matthew Brecknell <Matthew.Brecknell@data61.csiro.au>
This commit is contained in:
Matthew Brecknell 2020-09-03 18:39:38 +10:00
parent b181184d75
commit 4522d895d7
6 changed files with 61 additions and 58 deletions

View file

@ -40,14 +40,17 @@
#endif /* CONFIG_KERNEL_STATIC_MAX_BUDGET_US != 0 */
/* Short hand for accessing refill queue items */
#define REFILL_INDEX(sc, index) (((refill_t *) (SC_REF(sc) + sizeof(sched_context_t)))[index])
static inline refill_t refill_head(sched_context_t *sc)
static inline refill_t *refill_index(sched_context_t *sc, word_t index)
{
return REFILL_INDEX(sc, sc->scRefillHead);
return ((refill_t *)(SC_REF(sc) + sizeof(sched_context_t))) + index;
}
static inline refill_t refill_tail(sched_context_t *sc)
static inline refill_t *refill_head(sched_context_t *sc)
{
return REFILL_INDEX(sc, sc->scRefillTail);
return refill_index(sc, sc->scRefillHead);
}
static inline refill_t *refill_tail(sched_context_t *sc)
{
return refill_index(sc, sc->scRefillTail);
}
@ -89,11 +92,11 @@ static inline bool_t refill_single(sched_context_t *sc)
* has available if usage is charged to it. */
static inline ticks_t refill_capacity(sched_context_t *sc, ticks_t usage)
{
if (unlikely(usage > refill_head(sc).rAmount)) {
if (unlikely(usage > refill_head(sc)->rAmount)) {
return 0;
}
return refill_head(sc).rAmount - usage;
return refill_head(sc)->rAmount - usage;
}
/*
@ -113,7 +116,7 @@ static inline bool_t refill_sufficient(sched_context_t *sc, ticks_t usage)
*/
static inline bool_t refill_ready(sched_context_t *sc)
{
return refill_head(sc).rTime <= (NODE_STATE_ON_CORE(ksCurTime, sc->scCore) + getKernelWcetTicks());
return refill_head(sc)->rTime <= (NODE_STATE_ON_CORE(ksCurTime, sc->scCore) + getKernelWcetTicks());
}
/* Create a new refill in a non-active sc */

View file

@ -135,8 +135,8 @@ static inline void commitTime(void)
/* for round robin threads, there are only two refills: the HEAD, which is what
* we are consuming, and the tail, which is what we have consumed */
assert(refill_size(NODE_STATE(ksCurSC)) == MIN_REFILLS);
REFILL_HEAD(NODE_STATE(ksCurSC)).rAmount -= NODE_STATE(ksConsumed);
REFILL_TAIL(NODE_STATE(ksCurSC)).rAmount += NODE_STATE(ksConsumed);
refill_head(NODE_STATE(ksCurSC))->rAmount -= NODE_STATE(ksConsumed);
refill_tail(NODE_STATE(ksCurSC))->rAmount += NODE_STATE(ksConsumed);
} else {
refill_split_check(NODE_STATE(ksConsumed));
}

View file

@ -604,7 +604,7 @@ static void handleYield(void)
#ifdef CONFIG_KERNEL_MCS
/* Yield the current remaining budget */
ticks_t consumed = NODE_STATE(ksCurSC)->scConsumed + NODE_STATE(ksConsumed);
chargeBudget(refill_head(NODE_STATE(ksCurSC)).rAmount, false, CURRENT_CPU_INDEX(), true);
chargeBudget(refill_head(NODE_STATE(ksCurSC))->rAmount, false, CURRENT_CPU_INDEX(), true);
/* Manually updated the scConsumed so that the full timeslice isn't added, just what was consumed */
NODE_STATE(ksCurSC)->scConsumed = consumed;
#else

View file

@ -42,8 +42,8 @@ static inline word_t refill_next(sched_context_t *sc, word_t index)
UNUSED static inline void print_index(sched_context_t *sc, word_t index)
{
printf("index %lu, Amount: %llx, time %llx\n", index, REFILL_INDEX(sc, index).rAmount,
REFILL_INDEX(sc, index).rTime);
printf("index %lu, Amount: %llx, time %llx\n", index, refill_index(sc, index)->rAmount,
refill_index(sc, index)->rTime);
}
UNUSED static inline void refill_print(sched_context_t *sc)
@ -68,7 +68,7 @@ static UNUSED bool_t refill_ordered(sched_context_t *sc)
word_t next = refill_next(sc, sc->scRefillHead);
while (current != sc->scRefillTail) {
if (!(REFILL_INDEX(sc, current).rTime <= REFILL_INDEX(sc, next).rTime)) {
if (!(refill_index(sc, current)->rTime <= refill_index(sc, next)->rTime)) {
refill_print(sc);
return false;
}
@ -98,12 +98,12 @@ static UNUSED bool_t refill_ordered(sched_context_t *sc)
/* compute the sum of a refill queue */
static UNUSED ticks_t refill_sum(sched_context_t *sc)
{
ticks_t sum = refill_head(sc).rAmount;
ticks_t sum = refill_head(sc)->rAmount;
word_t current = sc->scRefillHead;
while (current != sc->scRefillTail) {
current = refill_next(sc, current);
sum += REFILL_INDEX(sc, current).rAmount;
sum += refill_index(sc, current)->rAmount;
}
return sum;
@ -116,7 +116,7 @@ static inline refill_t refill_pop_head(sched_context_t *sc)
assert(!refill_single(sc));
UNUSED word_t prev_size = refill_size(sc);
refill_t refill = refill_head(sc);
refill_t refill = *refill_head(sc);
sc->scRefillHead = refill_next(sc, sc->scRefillHead);
/* sanity */
@ -133,7 +133,7 @@ static inline void refill_add_tail(sched_context_t *sc, refill_t refill)
word_t new_tail = refill_next(sc, sc->scRefillTail);
sc->scRefillTail = new_tail;
refill_tail(sc) = refill;
*refill_tail(sc) = refill;
/* sanity */
assert(new_tail < sc->scRefillMax);
@ -161,9 +161,9 @@ void refill_new(sched_context_t *sc, word_t max_refills, ticks_t budget, ticks_t
sc->scRefillMax = max_refills;
assert(budget > MIN_BUDGET);
/* full budget available */
refill_head(sc).rAmount = budget;
refill_head(sc)->rAmount = budget;
/* budget can be used from now */
refill_head(sc).rTime = NODE_STATE_ON_CORE(ksCurTime, core);
refill_head(sc)->rTime = NODE_STATE_ON_CORE(ksCurTime, core);
maybe_add_empty_tail(sc);
REFILL_SANITY_CHECK(sc, budget);
}
@ -180,7 +180,7 @@ void refill_update(sched_context_t *sc, ticks_t new_period, ticks_t new_budget,
/* move the head refill to the start of the list - it's ok as we're going to truncate the
* list to size 1 - and this way we can't be in an invalid list position once new_max_refills
* is updated */
REFILL_INDEX(sc, 0) = refill_head(sc);
*refill_index(sc, 0) = *refill_head(sc);
sc->scRefillHead = 0;
/* truncate refill list to size 1 */
sc->scRefillTail = sc->scRefillHead;
@ -190,17 +190,17 @@ void refill_update(sched_context_t *sc, ticks_t new_period, ticks_t new_budget,
sc->scPeriod = new_period;
if (refill_ready(sc)) {
refill_head(sc).rTime = NODE_STATE_ON_CORE(ksCurTime, sc->scCore);
refill_head(sc)->rTime = NODE_STATE_ON_CORE(ksCurTime, sc->scCore);
}
if (refill_head(sc).rAmount >= new_budget) {
if (refill_head(sc)->rAmount >= new_budget) {
/* if the heads budget exceeds the new budget just trim it */
refill_head(sc).rAmount = new_budget;
refill_head(sc)->rAmount = new_budget;
maybe_add_empty_tail(sc);
} else {
/* otherwise schedule the rest for the next period */
refill_t new = { .rAmount = (new_budget - refill_head(sc).rAmount),
.rTime = refill_head(sc).rTime + new_period
refill_t new = { .rAmount = (new_budget - refill_head(sc)->rAmount),
.rTime = refill_head(sc)->rTime + new_period
};
refill_add_tail(sc, new);
}
@ -213,10 +213,10 @@ static inline void schedule_used(sched_context_t *sc, refill_t new)
/* schedule the used amount */
if (new.rAmount < MIN_BUDGET && !refill_single(sc)) {
/* used amount is to small - merge with last and delay */
refill_tail(sc).rAmount += new.rAmount;
refill_tail(sc).rTime = MAX(new.rTime, refill_tail(sc).rTime);
} else if (new.rTime <= refill_tail(sc).rTime) {
refill_tail(sc).rAmount += new.rAmount;
refill_tail(sc)->rAmount += new.rAmount;
refill_tail(sc)->rTime = MAX(new.rTime, refill_tail(sc)->rTime);
} else if (new.rTime <= refill_tail(sc)->rTime) {
refill_tail(sc)->rAmount += new.rAmount;
} else {
refill_add_tail(sc, new);
}
@ -226,9 +226,9 @@ static inline void ensure_sufficient_head(sched_context_t *sc)
{
/* ensure the refill head is sufficient, such that when we wake in awaken,
* there is enough budget to run */
while (refill_head(sc).rAmount < MIN_BUDGET || refill_full(sc)) {
while (refill_head(sc)->rAmount < MIN_BUDGET || refill_full(sc)) {
refill_t refill = refill_pop_head(sc);
refill_head(sc).rAmount += refill.rAmount;
refill_head(sc)->rAmount += refill.rAmount;
/* this loop is guaranteed to terminate as the sum of
* rAmount in a refill must be >= MIN_BUDGET */
}
@ -244,12 +244,12 @@ void refill_budget_check(ticks_t usage)
REFILL_SANITY_START(sc);
if (capacity == 0) {
while (refill_head(sc).rAmount <= usage) {
while (refill_head(sc)->rAmount <= usage) {
/* exhaust and schedule replenishment */
usage -= refill_head(sc).rAmount;
usage -= refill_head(sc)->rAmount;
if (refill_single(sc)) {
/* update in place */
refill_head(sc).rTime += sc->scPeriod;
refill_head(sc)->rTime += sc->scPeriod;
} else {
refill_t old_head = refill_pop_head(sc);
old_head.rTime = old_head.rTime + sc->scPeriod;
@ -261,15 +261,15 @@ void refill_budget_check(ticks_t usage)
if (usage > 0) {
/* budget reduced when calculating capacity */
/* due to overrun delay next replenishment */
refill_head(sc).rTime += usage;
refill_head(sc)->rTime += usage;
/* merge front two replenishments if times overlap */
if (!refill_single(sc) &&
refill_head(sc).rTime + refill_head(sc).rAmount >=
REFILL_INDEX(sc, refill_next(sc, sc->scRefillHead)).rTime) {
refill_head(sc)->rTime + refill_head(sc)->rAmount >=
refill_index(sc, refill_next(sc, sc->scRefillHead))->rTime) {
refill_t refill = refill_pop_head(sc);
refill_head(sc).rAmount += refill.rAmount;
refill_head(sc).rTime = refill.rTime;
refill_head(sc)->rAmount += refill.rAmount;
refill_head(sc)->rTime = refill.rTime;
}
}
}
@ -292,17 +292,17 @@ void refill_split_check(ticks_t usage)
/* something is seriously wrong if this is called and no
* time has been used */
assert(usage > 0);
assert(usage <= refill_head(sc).rAmount);
assert(usage <= refill_head(sc)->rAmount);
assert(sc->scPeriod > 0);
REFILL_SANITY_START(sc);
/* first deal with the remaining budget of the current replenishment */
ticks_t remnant = refill_head(sc).rAmount - usage;
ticks_t remnant = refill_head(sc)->rAmount - usage;
/* set up a new replenishment structure */
refill_t new = (refill_t) {
.rAmount = usage, .rTime = refill_head(sc).rTime + sc->scPeriod
.rAmount = usage, .rTime = refill_head(sc)->rTime + sc->scPeriod
};
if (refill_size(sc) == sc->scRefillMax || remnant < MIN_BUDGET) {
@ -311,10 +311,10 @@ void refill_split_check(ticks_t usage)
if (refill_single(sc)) {
/* update inplace */
new.rAmount += remnant;
refill_head(sc) = new;
*refill_head(sc) = new;
} else {
refill_pop_head(sc);
refill_head(sc).rAmount += remnant;
refill_head(sc)->rAmount += remnant;
schedule_used(sc, new);
ensure_sufficient_head(sc);
}
@ -323,7 +323,7 @@ void refill_split_check(ticks_t usage)
/* leave remnant as reduced replenishment */
assert(remnant >= MIN_BUDGET);
/* split the head refill */
refill_head(sc).rAmount = remnant;
refill_head(sc)->rAmount = remnant;
schedule_used(sc, new);
}
@ -333,9 +333,9 @@ void refill_split_check(ticks_t usage)
static bool_t refill_unblock_check_mergable(sched_context_t *sc)
{
ticks_t amount = refill_head(sc).rAmount;
ticks_t amount = refill_head(sc)->rAmount;
ticks_t tail = NODE_STATE_ON_CORE(ksCurTime, sc->scCore) + amount;
bool_t enough_time = REFILL_INDEX(sc, refill_next(sc, sc->scRefillHead)).rTime <= tail;
bool_t enough_time = refill_index(sc, refill_next(sc, sc->scRefillHead))->rTime <= tail;
return !refill_single(sc) && enough_time;
}
@ -350,15 +350,15 @@ void refill_unblock_check(sched_context_t *sc)
/* advance earliest activation time to now */
REFILL_SANITY_START(sc);
if (refill_ready(sc)) {
refill_head(sc).rTime = NODE_STATE_ON_CORE(ksCurTime, sc->scCore);
refill_head(sc)->rTime = NODE_STATE_ON_CORE(ksCurTime, sc->scCore);
NODE_STATE(ksReprogram) = true;
/* merge available replenishments */
while (refill_unblock_check_mergable(sc)) {
ticks_t amount = refill_head(sc).rAmount;
ticks_t amount = refill_head(sc)->rAmount;
refill_pop_head(sc);
refill_head(sc).rAmount += amount;
refill_head(sc).rTime = NODE_STATE_ON_CORE(ksCurTime, sc->scCore);
refill_head(sc)->rAmount += amount;
refill_head(sc)->rTime = NODE_STATE_ON_CORE(ksCurTime, sc->scCore);
}
assert(refill_sufficient(sc, 0));

View file

@ -566,14 +566,14 @@ void postpone(sched_context_t *sc)
void setNextInterrupt(void)
{
time_t next_interrupt = NODE_STATE(ksCurTime) +
refill_head(NODE_STATE(ksCurThread)->tcbSchedContext).rAmount;
refill_head(NODE_STATE(ksCurThread)->tcbSchedContext)->rAmount;
if (CONFIG_NUM_DOMAINS > 1) {
next_interrupt = MIN(next_interrupt, NODE_STATE(ksCurTime) + ksDomainTime);
}
if (NODE_STATE(ksReleaseHead) != NULL) {
next_interrupt = MIN(refill_head(NODE_STATE(ksReleaseHead)->tcbSchedContext).rTime, next_interrupt);
next_interrupt = MIN(refill_head(NODE_STATE(ksReleaseHead)->tcbSchedContext)->rTime, next_interrupt);
}
setDeadline(next_interrupt - getTimerPrecision());
@ -584,13 +584,13 @@ void chargeBudget(ticks_t consumed, bool_t canTimeoutFault, word_t core, bool_t
if (isRoundRobin(NODE_STATE_ON_CORE(ksCurSC, core))) {
assert(refill_size(NODE_STATE_ON_CORE(ksCurSC, core)) == MIN_REFILLS);
refill_head(NODE_STATE_ON_CORE(ksCurSC, core)).rAmount += refill_tail(NODE_STATE_ON_CORE(ksCurSC, core)).rAmount;
refill_tail(NODE_STATE_ON_CORE(ksCurSC, core)).rAmount = 0;
refill_head(NODE_STATE_ON_CORE(ksCurSC, core))->rAmount += refill_tail(NODE_STATE_ON_CORE(ksCurSC, core))->rAmount;
refill_tail(NODE_STATE_ON_CORE(ksCurSC, core))->rAmount = 0;
} else {
refill_budget_check(consumed);
}
assert(refill_head(NODE_STATE_ON_CORE(ksCurSC, core)).rAmount >= MIN_BUDGET);
assert(refill_head(NODE_STATE_ON_CORE(ksCurSC, core))->rAmount >= MIN_BUDGET);
NODE_STATE_ON_CORE(ksCurSC, core)->scConsumed += consumed;
NODE_STATE_ON_CORE(ksConsumed, core) = 0;
if (isCurCPU && likely(isSchedulable(NODE_STATE_ON_CORE(ksCurThread, core)))) {

View file

@ -288,7 +288,7 @@ void tcbReleaseEnqueue(tcb_t *tcb)
/* find our place in the ordered queue */
while (after != NULL &&
refill_head(tcb->tcbSchedContext).rTime >= refill_head(after->tcbSchedContext).rTime) {
refill_head(tcb->tcbSchedContext)->rTime >= refill_head(after->tcbSchedContext)->rTime) {
before = after;
after = after->tcbSchedNext;
}