线程优先级表的索引对应的线程的优先级。
为了快速的找到线程在线程优先级表的插入和移出的位置,RT-Thread专门设计了一个线程就绪优先级组。线程就绪优先组是一个32位的整型数,每一个位对应一个优先级,最多表示32个优先级
rt_uint32_t rt_thread_ready_priority_group;
从图中看出,第一个置1的位是位1,即表示此时就绪的线程当中,优先级最高的线程1,然后调度器从线程优先级表的索引1下去除线程1的线程控制块,从而切换到线程1.
kservice.c中
const rt_uint8_t __lowest_bit_bitmap[] =
{
/* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
/* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};
/**
* This function finds the first bit set (beginning with the least significant bit)
* in value and return the index of that bit.
*
* Bits are numbered starting at 1 (the least significant bit). A return value of
* zero from any of these functions means that the argument was zero.
*
* @return return the index of the first bit set. If value is 0, then this function
* shall return 0.
*/
int __rt_ffs(int value)
{
if (value == 0) return 0;
if (value & 0xff)
return __lowest_bit_bitmap[value & 0xff] + 1;
if (value & 0xff00)
return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9;
if (value & 0xff0000)
return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17;
return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;
}
scheduler.c
rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
将线程插入到线程优先级表和移出分别由scheduler.c的rt_schedule_insert_thread()和rt_schedule_remove_thread()这两个函数实现。
void rt_schedule_insert_thread(struct rt_thread *thread)
{
register rt_base_t temp;
/* disable interrupt */
temp = rt_hw_interrupt_disable();
/* change stat */
thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);
/* insert thread to ready list */
rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
&(thread->tlist));
/* set priority mask */
#if RT_THREAD_PRIORITY_MAX > 32
rt_thread_ready_table[thread->number] |= thread->high_mask;
#endif
rt_thread_ready_priority_group |= thread->number_mask;
P_DBG("insert thread %x grout %x\n",thread,rt_thread_ready_priority_group);
/* enable interrupt */
rt_hw_interrupt_enable(temp);
}
/*
* This function will remove a thread from system ready queue.
*
* @param thread the thread to be removed
*
* @note Please do not invoke this function in user application.
*/
void rt_schedule_remove_thread(struct rt_thread *thread)
{
register rt_base_t temp;
/* disable interrupt */
temp = rt_hw_interrupt_disable();
/* remove thread from ready list */
rt_list_remove(&(thread->tlist));
if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority])))
{
rt_thread_ready_priority_group &= ~thread->number_mask;
}
/* enable interrupt */
rt_hw_interrupt_enable(temp);
}
struct rt_thread
{
char name[RT_NAME_MAX];
rt_uint8_t type;
rt_uint8_t flag;
rt_list_t list;
void *sp; /* 线程栈指针 */
void *entry; /* 线程入口地址 */
void *parameter; /* 线程形参 */
void *stack_addr; /* 线程起始地址 */
rt_uint32_t stack_size; /* 线程栈大小,单位为字节 */
rt_list_t tlist; /* 线程链表节点 */
#if TEST_USE_TICK_ENABLE
rt_ubase_t init_tick;
rt_ubase_t remaining_tick;
#endif
**rt_uint8_t current_priority;
rt_uint8_t init_priority;
rt_uint32_t number_mask;
rt_err_t error;
rt_uint8_t stat;**
};
rtdef.h中定义错误码
#define RT_EOK 0 /**< There is no error */
#define RT_ERROR 1 /**< A generic error happens */
#define RT_ETIMEOUT 2 /**< Timed out */
#define RT_EFULL 3 /**< The resource is full */
#define RT_EEMPTY 4 /**< The resource is empty */
#define RT_ENOMEM 5 /**< No memory */
#define RT_ENOSYS 6 /**< No system */
#define RT_EBUSY 7 /**< Busy */
#define RT_EIO 8 /**< IO error */
#define RT_EINTR 9 /**< Interrupted system call */
#define RT_EINVAL 10 /**< Invalid argument */
定义线程状态
#define RT_THREAD_INIT 0x00 /**< Initialized status */
#define RT_THREAD_READY 0x01 /**< Ready status */
#define RT_THREAD_SUSPEND 0x02 /**< Suspend status */
#define RT_THREAD_RUNNING 0x03 /**< Running status */
#define RT_THREAD_BLOCK RT_THREAD_SUSPEND /**< Blocked status */
#define RT_THREAD_CLOSE 0x04 /**< Closed status */
#define RT_THREAD_STAT_MASK 0x0f
修改rt_system_scheduler_init()
void rt_system_scheduler_init(void)
{
register rt_base_t offset;
for(offset = 0; offset < RT_THREAD_PRIORITY_MAX;offset++)
{
rt_list_init(&rt_thread_priority_table[offset]);
}
rt_current_priority = RT_THREAD_PRIORITY_MAX - 1;
rt_current_thread = RT_NULL;
rt_thread_ready_priority_group = 0;
/* 初始化线程休眠列表,当线程创建好没有启动之前会被放入到这个列表 */
}
rt_err_t rt_thread_init(struct rt_thread *thread,const char *name,
void (*entry)(void *parameter),
void *parameter,
void *stack_start,
rt_uint32_t stack_size,
**rt_uint8_t priority**)
{
rt_object_init((rt_object_t)thread,RT_Object_Class_Thread,name);
rt_list_init(&(thread->tlist));
thread->entry = (void *)entry;
thread->parameter = parameter;
thread->stack_addr = stack_start;
thread->stack_size = stack_size;
/* 初始化线程栈,并返回线程栈指针 */
thread->sp = (void *)rt_hw_stack_init( thread->entry,
thread->parameter,
(void *)((char *)thread->stack_addr + thread->stack_size - 4) );
**thread->init_priority = priority;
thread->current_priority = priority;
thread->number_mask = 0;
thread->error = RT_EOK;
thread->stat = RT_THREAD_INIT;**
}
rt_err_t rt_thread_startup(rt_thread_t thread)
{
thread->current_priority = thread->init_priority;
thread->number_mask = 1L << thread->current_priority;
thread->stat = RT_THREAD_SUSPEND;
rt_thread_resume(thread);
if(rt_thread_self() != RT_NULL)
{
rt_schedule();
}
}
rt_err_t rt_thread_resume(rt_thread_t thread)
{
register rt_base_t temp;
if((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND)
{
return -RT_ERROR;
}
temp = rt_hw_interrupt_disable();
rt_list_remove(&(thread->tlist));
rt_hw_interrupt_enable(temp);
rt_schedule_insert_thread(thread);
}
void rt_thread_idle_init(void)
{
rt_thread_init(&idle,"idle",rt_thread_idle_entry,RT_NULL,&rt_thread_stack[0],sizeof(rt_thread_stack),RT_THREAD_PRIORITY_MAX - 1);
**rt_thread_startup(&idle);**
}
不再是手动指定第一个需要运行的线程,而是根据优先级来决定第一个运行的线程。
void rt_system_scheduler_start(void)
{
register struct rt_thread *to_thread;
register rt_ubase_t highest_ready_priority;
highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group)-1;
P_DBG("first start pri %d\n",highest_ready_priority);
to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,struct rt_thread,tlist);
rt_current_thread = to_thread;
rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp);
}
根据优先级来实现
void rt_schedule(void)
{
register rt_base_t temp;
rt_base_t level;
register rt_ubase_t highest_ready_priority;
struct rt_thread *to_thread;
struct rt_thread *from_thread;
temp = rt_hw_interrupt_disable();
highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group)-1;
P_DBG("read pri %d\n",highest_ready_priority);
to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,struct rt_thread,tlist);
P_DBG("read tgread %x\n",to_thread);
if(to_thread != rt_current_thread)
{
P_DBG("!= current thread %x\n",rt_current_thread);
rt_current_priority = (rt_uint8_t) highest_ready_priority;
from_thread = rt_current_thread;
rt_current_thread = to_thread;
rt_hw_context_switch((rt_uint32_t)&from_thread->sp,(rt_uint32_t)&to_thread->sp);
rt_hw_interrupt_enable(temp);
}
else
{
rt_hw_interrupt_enable(temp);
}
/* 产生上下文切换 */
}
void rt_thread_delay(rt_tick_t tick)
{
register rt_base_t temp;
struct rt_thread *thread;
temp = rt_hw_interrupt_disable();
thread = rt_current_thread;
thread->remaining_tick = tick;
thread->stat = RT_THREAD_SUSPEND;
rt_thread_ready_priority_group &= ~thread->number_mask;
rt_hw_interrupt_enable(temp);
rt_schedule();
}
void rt_tick_increase(void)
{
rt_ubase_t i;
struct rt_thread *thread;
rt_tick++;
for(i = 0;i < RT_THREAD_PRIORITY_MAX;i++)
{
thread = rt_list_entry(rt_thread_priority_table[i].next,struct rt_thread,tlist);
if(thread->remaining_tick > 0)
{
thread->remaining_tick--;
if(thread->remaining_tick == 0)
{
rt_thread_ready_priority_group |= thread->number_mask;
}
}
rt_schedule();
}
}
/* 初始化线程 */
rt_thread_init( &rt_flag1_thread, "flag1", /* 线程控制块 */
flag1_thread_entry, /* 线程入口地址 */
RT_NULL, /* 线程形参 */
&rt_flag1_thread_stack[0], /* 线程栈起始地址 */
sizeof(rt_flag1_thread_stack),3 ); /* 线程栈大小,单位为字节 */
/* 将线程插入到就绪列表 */
//rt_list_insert_before( &(rt_thread_priority_table[0]),&(rt_flag1_thread.tlist) );
P_DBG("thread flag1 %x timer %s\n",&rt_flag1_thread,rt_flag1_thread.thread_timer.parent.name);
rt_thread_startup(&rt_flag1_thread);
/* 初始化线程 */
rt_thread_init( &rt_flag2_thread, "falg2", /* 线程控制块 */
flag2_thread_entry, /* 线程入口地址 */
RT_NULL, /* 线程形参 */
&rt_flag2_thread_stack[0], /* 线程栈起始地址 */
sizeof(rt_flag2_thread_stack),4 ); /* 线程栈大小,单位为字节 */
/* 将线程插入到就绪列表 */
P_DBG("thread flag1 %x timer %s\n",&rt_flag2_thread,rt_flag2_thread.thread_timer.parent.name);
//rt_list_insert_before( &(rt_thread_priority_table[1]),&(rt_flag2_thread.tlist) );
rt_thread_startup(&rt_flag2_thread);
/* 启动系统调度器 */
rt_system_scheduler_start();
/* 线程1 */
void flag1_thread_entry( void *p_arg )
{
for( ;; )
{
P_DBG("flag1 thread\n");
flag2 = 1;
P_DBG("flag1 thread will dela1\n");
rt_thread_delay(10);
flag2 = 0;
P_DBG("flag1 thread will dela2\n");
rt_thread_delay(10);
}
}
/* 线程2 */
void flag2_thread_entry( void *p_arg )
{
for( ;; )
{
P_DBG("flag2 thread\n");
flag2 = 1;
rt_thread_delay(2);
flag2 = 0;
P_DBG("flag2 thread will dela1\n");
rt_thread_delay(2);
}
}