本篇目标:回答一个问题——就绪列表里可能挂几十个任务,怎么用最快速度挑出优先级最高的那个? 答案:用一个 32 位整数当“优先级位图”,一条
__stp_ffs 定位最高优先级。一、问题拆解
就绪列表是
stp_thread_priority_table[32]:下标是优先级,每个元素是一条链表。要找最高优先级任务,朴素做法是从 0 开始遍历 32 条链表看哪个非空——最坏 32 次判断,每次调度都来一遍,太慢。更好的思路:单独用一个 32 位变量记录“哪些优先级上有就绪任务”。
bit0 对应优先级 0,bit1 对应优先级 1……某优先级有就绪任务就置 1。于是“找最高优先级”变成“找这个 32 位数最低的置 1 位”,一条指令/一次查表完成。
二、优先级组怎么维护
插入线程时置位:
删除线程时复位——注意:只有当该优先级链表空了才能清位,否则会把别的任务“误删”:
number_task = 1 << priority 是每个线程预先算好的掩码,置位/复位就是一次 OR/AND。三、__stp_ffs:找最低置 1 位
ffs = find first set,从低位找第一个 1。stp_rtos 提供三种实现,按编译器/平台选。3.1 查表法(空间换时间)
__lowest_bit_bitmap[256] 预先把 0~255 每个数的“最低置 1 位位号”存好,查表 O(1)。比如 __lowest_bit_bitmap[10] = 1(10 = 0b1010,最低的 1 在 bit1)。3.2 RBIT + CLZ(ARM 指令)
CLZ 数的是“最高位方向”的前导零,配合 RBIT 位反转,就等价于数“最低位方向”的尾随零。Cortex-M3/M4 有这两条指令,单周期完成。3.3 __builtin_ffs(GCC 内建)
GCC 会把它编译成最优指令序列。stp_rtos 用 GNU 工具链,实际走这条。
四、调度:stp_schedule
三步:关中断 → 找最高优先级线程 → 需要就切换。
stp_list_entry 用 stp_container_of 从链表节点反推结构体首地址——原理篇04的 TCB 就是靠它从 tlist 找回 stp_thread。五、小结
- 优先级位图把“遍历 32 条链表”降成“一次 ffs”;
- 置位/复位必须成对,且清位前要确认链表已空;
- 三种 ffs 实现殊途同归,GNU 下用
__builtin_ffs。
核心一句话:用一个 bit 代表一个优先级,找最高优先级 = 找最低的 1。
- Author:felixfixit
- URL:http://www.felixmicrospace.top/article/resource_management_task_scheduling
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!





