lk中是根据优先级来选择下一个要运行的thread,如果是同一个优先级就按注册时候的顺序执行。
下来我们看看code中的实现.
lk中thread 切换时在thread_resched 中进行的,这个可以会在timer函数的interrupt callback函数中调用,或者
某个thread 主动调用这个函数放弃cpu。
void thread_resched(void)
{
thread_t *oldthread;
thread_t *newthread;
oldthread = current_thread;
int next_queue = HIGHEST_PRIORITY - __builtin_clz(run_queue_bitmap) - (32 - NUM_PRIORITIES);
newthread = list_remove_head_type(&run_queue[next_queue], thread_t, queue_node);
}
所有thread 都是放在run_queue 这个数组中,因此只要知道priority,就可以得到thread。如上所示。
从下面的code中我们就可以得到下一个要执行thread的优先级.
假定当前NUM_PRIORITIES=HIGHEST_PRIORITY=32
int next_queue = HIGHEST_PRIORITY - __builtin_clz(run_queue_bitmap) - (32 - NUM_PRIORITIES)
则
int next_queue = HIGHEST_PRIORITY - __builtin_clz(run_queue_bitmap)
其中__builtin_clz 返回run_queue_bitmap 前导0的个数,例如现在run_queue_bitmap = 0000,1001,1111,1001
所以__builtin_clz(run_queue_bitmap)就等于4
所以
int next_queue = HIGHEST_PRIORITY -4 =28
所以我们就先运行优先级28的thread.
如果优先级28有多个thread ,那要先运行哪个呢?
可以看thread_resched中的list_remove_head_type函数
#define list_remove_head_type(list, type, element) ({\
struct list_node *__nod = list_remove_head(list);\
type *__t;\
if(__nod)\
__t = containerof(__nod, type, element);\
else\
__t = (type *)0;\
__t;\
})
可见是去list 这个列表的head,也就是第一个注册这个优先级的thread.
所以结论就是:lk中是根据优先级来选择下一个要运行的thread,如果是同一个优先级就按注册时候的顺序执行。