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:
parent
b181184d75
commit
4522d895d7
6 changed files with 61 additions and 58 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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)))) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue