aCoral的优先级与数字大小成反比,即:数字越大,优先级越低。
#define MAX_PRIO_NUM ((CFG_MAX_THREAD+1) & 0xff)
#define MINI_PRIO CFG_MAX_THREAD //最低优先级40
typedef enum{
ACORAL_INIT_PRIO; //init线程独有的0优先级
ACORAL_MAX_PRIOL; //最高优先级是1
ACORAL_HARD_RT_PRIO_MAX; //硬实时任务最高优先级
ACORAL_HARD_RT_PRIO_MIN = ACORAL_HARD_RT_PRIO MAX+CFG_HARD_RT_PRIO_NUM;
ACORAL_NOHARD_RT_PRIO_MAX; //非硬实时任务最高优先级
DAEMON_PRIO = MINI_PRIO - 2; //回收线程优先级
ACORAL_NONHARD_RT_PRIO_MIN,
ACORAL_IDLE_PRIO; //空闲线程优先级
}acoralPrioEnum;
#define CFG_MEN2 1 //任意大小内存分配系统是否启用
#define CFG_MEM2_SIZE (1024000) //任意大小内存分配系统的大小,从伙伴系统管理的堆内存中拿出的一部分
acoral_list_t主要用来将线程结构挂到相应链表队列,它是一个双向链表。
struct acoral_list{
strcut acoral_list *next,*prev;
}
typedef strcut acoral_list acoral_list_t;
以就绪队列ready为例,当用户调用了acoral_rdy_thread或acoral_resume_thread接口时,就会将线程挂到就绪队列acoral_ready_queue上,也就是将就绪队列ready成员挂到这个链表上。
这种方式的优点是:可以用相同的数据处理方式来描述所有双向链表,不用再单独为各个链表编写各种函数。
线程优先级
就绪队列采用的是优先级链表,每个优先级是一个链表,相同优先级的线程挂在该链表上。
对于RTOS而言,几乎都是采用了基于优先级的抢占调度策略。
就绪队列
#define PRIO_BITMAP_SIZE ((ACORAL_MAX_PRIO_NUM+31)/32)
typedef struct{
unsigned int num; //就绪的线程数
unsigned int bitmap[PRIO_BITMAP_SIZE]; //优先级位图,每一位对应一个优先级,为1表示这个优先级有就绪线程。
acoral_list_t queue[ACORAL_MAX_PRIO_NUM]; //每一个优先级都有独立的队列
}
优先级位图数组bitmap[PRIO_BITMAP_SIZE],用来标识某一优先级是否有就绪队列,这样才能确保以O(1)复杂度找出最高优先级的线程。
每个变量从右到左每一位依次代表一个优先级,为0表示该位对应的优先级没有任务就绪。
acoral_list_t queue[ACORAL_MAX_PRIO_NUM];优先级链表数组
每个CPU都有一个。
调度策略
把线程相关的操作统称为线程调度,将调度分为两层,上层为策略,下层为机制,采用策略与机制分离的设计原则,这样可以灵活方便地扩展调度策略,而不改变底层的调度机制。
调度策略就是如何确定线程的CPU、优先级等参数,线程按哪种策略来调度,然后根据相应操作初始化线程。
一种策略对应一种线程。
调度机制就是负责调度策略的具体实施,即根据给定调度策略来安排任务的具体执行。
当用户创建线程时,需要指定某种调度策略,并找到该调度策略对应的策略控制块,再为TCB成员赋值。
- 普通线程(通用策略创建的线程),需要人为指定CPU,优先级信息。
- 周期线程(周期策略创建的线程),这种线程需要每隔一个固定时间就要执行一次。