kernel/sched: Optimize deadline comparison

Needing to check the current cycle time (which involves a spinlock and
register read on most architectures) is wasteful in the scheduler
priority predicate, which is a hot path.  If we "burn" one bit of
precision (and document the rule), we can do the comparison without
knowing the current time.

2^31 cycles is still far longer than a live deadline thread in any
legitimate realtime app should ever live before being scheduled.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2020-07-10 09:43:36 -07:00 committed by Anas Nashif
commit ef626571b2
2 changed files with 15 additions and 14 deletions

View file

@ -718,11 +718,12 @@ __syscall void k_thread_priority_set(k_tid_t thread, int prio);
* static priority. Threads at different priorities will be scheduled * static priority. Threads at different priorities will be scheduled
* according to their static priority. * according to their static priority.
* *
* @note Deadlines that are negative (i.e. in the past) are still seen * @note Deadlines are stored internally using 32 bit unsigned
* as higher priority than others, even if the thread has "finished" * integers. The number of cycles between the "first" deadline in the
* its work. If you don't want it scheduled anymore, you have to * scheduler queue and the "last" deadline must be less than 2^31 (i.e
* reset the deadline into the future, block/pend the thread, or * a signed non-negative quantity). Failure to adhere to this rule
* modify its priority with k_thread_priority_set(). * may result in scheduled threads running in an incorrect dealine
* order.
* *
* @note Despite the API naming, the scheduler makes no guarantees the * @note Despite the API naming, the scheduler makes no guarantees the
* the thread WILL be scheduled within that deadline, nor does it take * the thread WILL be scheduled within that deadline, nor does it take

View file

@ -100,18 +100,18 @@ bool z_is_t1_higher_prio_than_t2(struct k_thread *thread_1,
} }
#ifdef CONFIG_SCHED_DEADLINE #ifdef CONFIG_SCHED_DEADLINE
/* Note that we don't care about wraparound conditions. The /* If we assume all deadlines live within the same "half" of
* expectation is that the application will have arranged to * the 32 bit modulus space (this is a documented API rule),
* block the threads, change their priorities or reset their * then the latest dealine in the queue minus the earliest is
* deadlines when the job is complete. Letting the deadlines * guaranteed to be (2's complement) non-negative. We can
* go negative is fine and in fact prevents aliasing bugs. * leverage that to compare the values without having to check
* the current time.
*/ */
if (thread_1->base.prio == thread_2->base.prio) { if (thread_1->base.prio == thread_2->base.prio) {
int now = (int) k_cycle_get_32(); int32_t d1 = thread_1->base.prio_deadline;
int dt1 = thread_1->base.prio_deadline - now; int32_t d2 = thread_2->base.prio_deadline;
int dt2 = thread_2->base.prio_deadline - now;
return dt1 < dt2; return (d2 - d1) >= 0;
} }
#endif #endif