0
点赞
收藏
分享

微信扫一扫

嵌入式操作系统内核原理和开发(线程状态)


 
     从第一篇的os博客以来,谈了很多内容,有中断、切换、调度、内存、互斥和延时等等,但是线程的状态却没有涉及到,今天我们要好好说一说。说到线程的状态,按照一般的说法,主要包括就绪、延时、阻塞、阻塞超时四个状态。如果线程没有死亡的话,那么这几个状态也够用了,但是我们后来发现可能需要对某些线程进行挂起处理,这可能是出现了故障或者是为了调试使用。因此,除了上面的四个状态,我们还要补充对应的四个挂起状态,分别是挂起、延时挂起、阻塞挂起、阻塞延时挂起。

     说到了线程状态,下面我们就看看常见的线程处理函数有哪些,无外乎线程创建、线程延时、线程挂起、线程恢复和线程删除等等。 

RAW_U16 raw_task_create(RAW_TASK_OBJ  *task_obj, RAW_U8  *task_name,  RAW_VOID   *task_arg, 
RAW_U8 task_prio, RAW_U16 time_slice, PORT_STACK *task_stack_base,
RAW_U32 stack_size, RAW_TASK_ENTRY task_entry, RAW_U8 auto_start)

{
#if (RAW_TASK_STACK_CHECK > 0)
PORT_STACK *p_stack;
RAW_U32 i;
#endif

RAW_SR_ALLOC();

#if (RAW_TASK_FUNCTION_CHECK > 0)

if (task_obj == 0) {
return RAW_NULL_OBJECT;
}

if (task_prio >= CONFIG_RAW_PRIO_MAX) {
return RAW_BYOND_MAX_PRIORITY;
}

if (task_stack_base == 0) {
return RAW_NULL_POINTER;
}

if (task_entry == 0) {
return RAW_NULL_POINTER;
}

#endif

RAW_CRITICAL_ENTER();

if (task_prio == IDLE_PRIORITY) {

if (idle_task_exit) {

RAW_CRITICAL_EXIT();
return RAW_IDLE_EXIT;

}

idle_task_exit = 1;
}


RAW_CRITICAL_EXIT();

raw_memset(task_obj, 0, sizeof(RAW_TASK_OBJ));

#if (CONFIG_ROUND_ROBIN > 0)

if (time_slice) {
task_obj->time_total = time_slice;

}

else {

task_obj->time_total = TIME_SLICE_DEFAULT;
}

task_obj->time_slice = task_obj->time_total;

#endif

if (auto_start)
task_obj->task_state = RAW_RDY;
else
task_obj->task_state = RAW_SUSPENDED;


#if (RAW_TASK_STACK_CHECK > 0)

task_obj->task_stack_base = task_stack_base;
p_stack = task_stack_base;

for (i = 0; i < stack_size; i++) {
*p_stack++ =0;

}

#endif

task_obj->task_stack = port_stack_init(task_stack_base, stack_size, task_arg, task_entry);
task_obj->task_name = task_name;
task_obj->priority = task_prio;

task_create_hook(task_obj);


RAW_CRITICAL_ENTER();

#if (RAW_TASK_STACK_CHECK > 0)
task_obj->stack_size = stack_size;
list_insert(&task_head, &task_obj->stack_check_list);
#endif

if (auto_start) {
add_ready_list_end(&raw_ready_queue, task_obj);
}

if (raw_os_active != RAW_OS_RUNNING) { /* Return if multitasking has not started */
RAW_CRITICAL_EXIT();
return RAW_OS_STOPPED;
}

RAW_CRITICAL_EXIT();

if (auto_start) {
raw_sched();
}

return RAW_SUCCESS;

}

    创建线程的函数是比较复杂的,内容长一些,参数也多一些。首先看看有哪些参数,虽然很多,但是慢慢梳理一下也不难理解,有名称、参数、优先级、时间片、堆栈起始指针、堆栈大小、入口函数和标志。整个函数基本上都是赋值的过程,最重要的其实就两个部分,一个是port_stack_init,另一个就是add_ready_list_end。前者可以对堆栈进行默认处理,比如压入一些寄存器、压入函数参数、函数指针等等,后者就是把线程加入到就绪队列。


RAW_U16  raw_sleep(RAW_U32  dly) 
{
RAW_U16 error_status;

RAW_SR_ALLOC();

#if (RAW_TASK_FUNCTION_CHECK > 0)

if (raw_int_nesting) {

return RAW_NOT_CALLED_BY_ISR;
}
#endif

RAW_CRITICAL_ENTER();

if (dly) {

/*system is locked so task can not sleep just return immediately*/
if (raw_sched_lock) {
RAW_CRITICAL_EXIT();
return RAW_SCHED_DISABLE;
}

raw_task_active->task_state = RAW_DLY;

tick_list_insert(raw_task_active, dly);

remove_ready_list(&raw_ready_queue, raw_task_active);
}

else {
/*make current task to the end of ready list*/
move_to_ready_list_end(&raw_ready_queue, raw_task_active);
}

RAW_CRITICAL_EXIT();

raw_sched();

if (dly) {
/*task is timeout after sleep*/
error_status = block_state_post_process(raw_task_active, 0);
}

else {

error_status = RAW_SUCCESS;

}

return error_status;
}

    我们之前也介绍过系统的延时功能。延时,就是把线程暂时从就绪队列清除出来,添加到延时队列中。当然如果参数为0,那表示作者只是希望暂时释放cpu的使用权,如果此时没有同等优先级的任务,那么下一个运行的线程还是它自己。 

RAW_U16  raw_task_suspend(RAW_TASK_OBJ *task_ptr)
{
RAW_SR_ALLOC();

#if (RAW_TASK_FUNCTION_CHECK > 0)

if (task_ptr == 0) {
return RAW_NULL_OBJECT;
}

#endif

if (task_ptr->priority == IDLE_PRIORITY) {
return RAW_SUSPEND_TASK_NOT_ALLOWED;
}

RAW_CRITICAL_ENTER();

if (task_ptr == raw_task_active) {

if (raw_sched_lock) {
RAW_CRITICAL_EXIT();
return RAW_SCHED_LOCKED;
}
}

switch (task_ptr->task_state) {
case RAW_RDY:
task_ptr->task_state = RAW_SUSPENDED;
remove_ready_list(&raw_ready_queue, task_ptr);
break;

case RAW_DLY:
task_ptr->task_state = RAW_DLY_SUSPENDED;
break;

case RAW_PEND:

task_ptr->task_state = RAW_PEND_SUSPENDED;
break;


case RAW_PEND_TIMEOUT:
task_ptr->task_state = RAW_PEND_TIMEOUT_SUSPENDED;
break;


case RAW_DLY_SUSPENDED:
case RAW_PEND_SUSPENDED:
case RAW_PEND_TIMEOUT_SUSPENDED:
RAW_CRITICAL_EXIT();
return RAW_SUSPENDED_AGAIN;


default:

#if (CONFIG_RAW_ASSERT > 0)
RAW_ASSERT(0);
#endif

RAW_CRITICAL_EXIT();
return RAW_STATE_UNKNOWN;
}

RAW_CRITICAL_EXIT();

raw_sched();

return RAW_SUCCESS;
}

    挂起任务的动作其实是比较残暴的,因为此时你不知道线程处于什么状态。当然任务如果已经被挂起了,那什么也不用做了,否则就需要把任务修改为对应的挂起状态就可以了。当然如果任务是就绪态的,还得把任务清除处理来。在函数结束的时候,我们需要重新进行调度,因为很有可能当前最高优先级的线程已经发生了改变。


RAW_U16  raw_task_resume(RAW_TASK_OBJ *task_ptr)
{
RAW_SR_ALLOC();

#if (RAW_TASK_FUNCTION_CHECK > 0)

if (task_ptr == 0) {
return RAW_NULL_OBJECT;
}

#endif

RAW_CRITICAL_ENTER();

switch (task_ptr->task_state) {
case RAW_RDY:
case RAW_DLY:
case RAW_PEND:
case RAW_PEND_TIMEOUT:

RAW_CRITICAL_EXIT();
return HAS_NOT_SUSPENDED;


case RAW_SUSPENDED:
task_ptr->task_state = RAW_RDY;
add_ready_list(&raw_ready_queue, task_ptr);
break;

case RAW_DLY_SUSPENDED:

task_ptr->task_state = RAW_DLY;
break;

case RAW_PEND_SUSPENDED:

task_ptr->task_state = RAW_PEND;
break;

case RAW_PEND_TIMEOUT_SUSPENDED:

task_ptr->task_state = RAW_PEND_TIMEOUT;
break;

default:

#if (CONFIG_RAW_ASSERT > 0)
RAW_ASSERT(0);
#endif

RAW_CRITICAL_EXIT();

return RAW_STATE_UNKNOWN;

}

RAW_CRITICAL_EXIT();

raw_sched();

return RAW_SUCCESS;
}

    恢复函数其实就是挂起函数的逆向操作。如果任务没有被挂起,那么什么也不用做。否则就需要把任务的状态修改为对应的非挂起状态,当然该就绪的线程还得加入到就绪队列当中去。同时在函数结束之前不忘调度一下,说不定刚刚释放的这个线程就是优先级最高的那个线程。


RAW_U16 raw_task_delete(RAW_TASK_OBJ *task_ptr)
{
RAW_SR_ALLOC();

#if (RAW_TASK_FUNCTION_CHECK > 0)

if (task_ptr == 0) {

return RAW_NULL_OBJECT;
}

if (raw_int_nesting) {

return RAW_NOT_CALLED_BY_ISR;

}

#endif

if (task_ptr->priority == IDLE_PRIORITY) {

return RAW_DELETE_TASK_NOT_ALLOWED;
}

RAW_CRITICAL_ENTER();

if (task_ptr == raw_task_active) {

if (raw_sched_lock) {
RAW_CRITICAL_EXIT();
return RAW_SCHED_LOCKED;
}
}

switch (task_ptr->task_state) {
case RAW_RDY:
remove_ready_list(&raw_ready_queue, task_ptr);
break;

case RAW_SUSPENDED:
break;

case RAW_DLY: /* Task is only delayed, not on any wait list */
case RAW_DLY_SUSPENDED:
tick_list_remove(task_ptr);
break;

case RAW_PEND:
case RAW_PEND_SUSPENDED:
case RAW_PEND_TIMEOUT:
case RAW_PEND_TIMEOUT_SUSPENDED:
tick_list_remove(task_ptr);
list_delete(&task_ptr->task_list);
break;

default:

#if (CONFIG_RAW_ASSERT > 0)
RAW_ASSERT(0);
#endif

RAW_CRITICAL_EXIT();
return RAW_STATE_UNKNOWN;
}

task_ptr->task_state = RAW_DELETED;

#if (RAW_TASK_STACK_CHECK > 0)
/*make after_delete_list to right position*/
after_delete_list = task_ptr->stack_check_list.next;

if (after_delete_list == &task_head) {
after_delete_list = task_head.next;
}

list_delete(&task_ptr->stack_check_list);

#endif

RAW_CRITICAL_EXIT();

raw_sched();

return RAW_SUCCESS;
}

    删除函数的动作其实是比较残忍的,因为此时你不清楚线程已经执行到哪一步了,拥有了那些资源,正在处理哪些资源,所以没事不要用这个函数。这里做的只是把任务从就绪队列、等待队列和阻塞队列清除出来,但是真正善后的工作要比这多得多,如果有兴趣,你看看linux的exit函数就明白了。


 



举报

相关推荐

0 条评论