Zephyr内核调度之代码分析5--设置优先级
本文分析设置优先级如何引发调度。
前文参考
[1] Zephyr内核调度之调度方式与时机 [2] Zephyr线程阻塞和超时机制分析 [3] Zephyr用户模式-系统调用 [4] Zephyr内核调度之代码分析2-调度关键函数 [5] Zephyr内核调度之代码分析3–线程睡眠和挂起
在[1]中提到了17种调度时机,本文分析其中1种:设置优先级
- z_impl_k_thread_priority_set
由于系统调用的关系可被应用调用的内核函数实际实现对应到sched.c中(参考[3]): k_thread_priority_set->z_impl_k_thread_priority_set
void z_impl_k_thread_priority_set(k_tid_t thread, int prio)
{
//判断优先级合法性
Z_ASSERT_VALID_PRIO(prio, NULL);
//ISR中不能调整线程优先级
__ASSERT(!arch_is_in_isr(), "");
struct k_thread *th = (struct k_thread *)thread;
//设置优先级
z_thread_priority_set(th, prio);
}
void z_thread_priority_set(struct k_thread *thread, int prio)
{
//设置优先级,并返回是否需要调度
bool need_sched = z_set_prio(thread, prio);
//需要调度,且没有锁调度,执行上下文切换。z_reschedule_unlocked参考[5]
if (need_sched && _current->base.sched_locked == 0U) {
z_reschedule_unlocked();
}
}
bool z_set_prio(struct k_thread *thread, int prio)
{
bool need_sched = 0;
LOCKED(&sched_spinlock) {
//修改就绪线程的优先级,意味着就绪列表会重新排列,需要进行调度
need_sched = z_is_thread_ready(thread);
if (need_sched) {
//线程在就绪列表内,将线程从ready_q中取出,修改优先级后再重新加入到ready_q中,想当于进行了重排
if (!IS_ENABLED(CONFIG_SMP) || z_is_thread_queued(thread)) {
dequeue_thread(&_kernel.ready_q.runq, thread);
thread->base.prio = prio;
queue_thread(&_kernel.ready_q.runq, thread);
} else {
thread->base.prio = prio;
}
//重排后,选出最优的线程
update_cache(1);
} else {
//如果线程处于挂起状态,直接修改优先级
thread->base.prio = prio;
}
}
return need_sched;
dequeue_thread,queue_thread,update_cache参考[4].