本文分析调度时机中的两种:线程启动和中止。
前文参考
[1] Zephyr内核调度之调度方式与时机
[2] Zephyr线程阻塞和超时机制分析
[3] Zephyr用户模式-系统调用
[4] Zephyr内核调度之代码分析2-调度关键函数
[5] Zephyr内核调度之代码分析3–线程睡眠和挂起
在[1]中提到了17种调度时机,本文分析其中2种:涉及线程创建启动和中止引起的调度
- 启动线程
- k_thread_start
- 中止线程
- k_thread_abort
- 等待线程中止
- k_thread_join
由于系统调用的关系可被应用调用的内核函数实际实现对应到sched.c中(参考[3]):
k_thread_start->z_impl_k_thread_start
k_thread_abort->z_impl_k_thread_abort
k_thread_join->z_impl_k_thread_join
API实现分析
启动线程
在创建线程时可以立即使用k_thread_start启动线程,也可以在之后的任意时刻使用k_thread_start启动线程,z_impl_k_thread_start通过调用z_sched_start实现
1 | void z_sched_start(struct k_thread *thread) |
作为调度的关键函数dready_thread和z_reschedule在[]中已分析过。
顺便说一句如果创建线程时是通过指定timeout时间后自动启动,那么在timeout到来时将使用[]中的分析的超时到的机制将线程加入到就绪列队,并执行调度。
线程中止
z_impl_k_thread_abort由z_thread_abort实现
1 | void z_thread_abort(struct k_thread *thread) |
作为调度的关键函数z_swap已经在[4]中分析过,end_thread后文分析。
等待线程中止
线程睡眠,是线程自己主动调用内核API让出CPU.k_msleep
直接通过k_sleep实现
1 | int z_impl_k_thread_join(struct k_thread *thread, k_timeout_t timeout) |
作为调度的关键函数z_swap和add_to_waitq_locked已经在[4]中分析过,add_thread_timeout在[2]中分析过.
内部函数分析
上一节中有提到一些和调度相关的内部函数,这里做展开分析
1 | static void end_thread(struct k_thread *thread) |
这里提的unpend_all(&thread->join_queue);
也就是会解除和join中add_to_waitq_locked 挂起的thread