1 有前面的铺垫,简单讲解初始化/创建/删除/脱离的函数
2 附上官方使用例程
重点:
实际上,用 rt_thread_delete() 函数删除线程接口,仅仅是把相应的线程状态更改为 RT_THREAD_CLOSE 状态,然后放入到 rt_thread_defunct 队列中;而真正的删除动作(释放线程控制块和释放线程栈)需要到下一次执行空闲线程时,由空闲线程完成最后的线程删除动作。
1 其它接口函数的操作也类似,也就是并不会一定在当前线程立即执行所有任务,而是在空闲线程内执行,通过钩子函数
2 RTM_EXPORT() 是 RT-Thread 导出的所有函数都可以被应用程序使用
3 线程本身不能去操作本身的状态
4 init – detach / create – delete 相互对应
5 MSH_CMD_EXPORT() 将函数导入到 Finsh 可调用的列表中(Finsh 就是类似 shell 的终端)
/** //看官方 API 参数介绍
* This function will initialize a thread, normally it's used to initialize a
* static thread object.
*
* @param thread the static thread object
* @param name the name of thread, which shall be unique
* @param entry the entry function of thread
* @param parameter the parameter of thread enter function
* @param stack_start the start address of thread stack
* @param stack_size the size of thread stack
* @param priority the priority of thread
* @param tick the time slice if there are same priority thread
*
* @return the operation status, RT_EOK on OK, -RT_ERROR on error
*/
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_uint32_t tick)
{
/* thread check */
RT_ASSERT(thread != RT_NULL);
//这就是 ASSERT 用于判断类似 if ,但并不推荐会降低程序执行效率仅用于调试
RT_ASSERT(stack_start != RT_NULL);
/* init thread object */
//初始化+将线程加入到对象管理器中,具体实现对使用关系不大,不需要关心
//中间用到了线程锁 rt_enter_critical() 加锁 rt_exit_critical() 解锁
//以及中断管理 temp=rt_hw_interrupt_disable(); rt_hw_interrupt_enable(temp);
rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);
//已在 (2) 中讲解
return _rt_thread_init(thread,
name,
entry,
parameter,
stack_start,
stack_size,
priority,
tick);
}
/**
* This function will create a thread object and allocate thread object memory
* and stack.
*
* @param name the name of thread, which shall be unique
* @param entry the entry function of thread
* @param parameter the parameter of thread enter function
* @param stack_size the size of thread stack
* @param priority the priority of thread
* @param tick the time slice if there are same priority thread //线程的时间片大小(一次运行的最大时间)
*
* @return the created thread object
*/
rt_thread_t rt_thread_create(const char *name,
void (*entry)(void *parameter),
void *parameter,
rt_uint32_t stack_size,
rt_uint8_t priority,
rt_uint32_t tick)
{
struct rt_thread *thread;
void *stack_start;
//这个函数主要目的就是向系统索取一个可用的线程资源,具体实现可另看对于理解程序影响不大
thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread,
name);
if (thread == RT_NULL)
return RT_NULL;
//分配内存资源给栈表
stack_start = (void *)RT_KERNEL_MALLOC(stack_size);
if (stack_start == RT_NULL)
{
/* allocate stack failure */
rt_object_delete((rt_object_t)thread);
return RT_NULL;
}
//已在 (2) 中讲解
_rt_thread_init(thread,
name,
entry,
parameter,
stack_start,
stack_size,
priority,
tick);
return thread;
}
/**
* This function will delete a thread. The thread object will be removed from
* thread queue and deleted from system object management in the idle thread.
*
* @param thread the thread to be deleted
*
* @return the operation status, RT_EOK on OK, -RT_ERROR on error
*/
rt_err_t rt_thread_delete(rt_thread_t thread)
{
rt_base_t lock;
/* thread check */
RT_ASSERT(thread != RT_NULL);
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread) == RT_FALSE);
// (thread->stat & 0x0f ) != 0x00 只要不是未初始化状态就进入将线程移出调度列表
if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
{
/* remove from schedule */
rt_schedule_remove_thread(thread);
}
//定时器从时钟管理器中离线
/* release thread timer */
rt_timer_detach(&(thread->thread_timer));
/* change stat */
thread->stat = RT_THREAD_CLOSE;
/* disable interrupt */
lock = rt_hw_interrupt_disable();
//加入到离线列表等待删除
/* insert to defunct thread list */
rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
/* enable interrupt */
rt_hw_interrupt_enable(lock);
return RT_EOK;
}
RTM_EXPORT(rt_thread_delete);
/**
* This function will detach a thread. The thread object will be removed from
* thread queue and detached/deleted from system object management.
*
* @param thread the thread to be deleted
*
* @return the operation status, RT_EOK on OK, -RT_ERROR on error
*/
rt_err_t rt_thread_detach(rt_thread_t thread)
{
rt_base_t lock;
/* thread check */
RT_ASSERT(thread != RT_NULL);
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread));
if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
{
/* remove from schedule */
rt_schedule_remove_thread(thread);
}
/* release thread timer */
rt_timer_detach(&(thread->thread_timer));
/* change stat */
thread->stat = RT_THREAD_CLOSE;
//这里需要判断是由系统自动生成的线程且以及被清理就执行脱离程序
if ((rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) &&
thread->cleanup == RT_NULL)
{
rt_object_detach((rt_object_t)thread);
}
else
{
/* disable interrupt */
lock = rt_hw_interrupt_disable();
/* insert to defunct thread list */
rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
/* enable interrupt */
rt_hw_interrupt_enable(lock);
}
return RT_EOK;
}
RTM_EXPORT(rt_thread_detach);
#include
#define THREAD_STACK_SIZE 1024
#define THREAD_PRIORITY 20
#define THREAD_TIMESLICE 10
/* 针对每个线程的计数器 */
volatile rt_uint32_t count[2];
/* 线程 1、2 共用一个入口,但入口参数不同 */
static void thread_entry(void* parameter) {
rt_uint32_t value;
value = (rt_uint32_t)parameter;
while (1) {
rt_kprintf("thread %d is running\n", value);
rt_thread_mdelay(1000); // 延时一段时间
}
}
static rt_thread_t tid1 = RT_NULL;
static rt_thread_t tid2 = RT_NULL;
static void hook_of_scheduler(struct rt_thread* from, struct rt_thread* to) {
rt_kprintf("from: %s --> to: %s \n", from->name , to->name);
}
int scheduler_hook(void) {
/* 设置调度器钩子 */
rt_scheduler_sethook(hook_of_scheduler);
/* 创建线程 1 */
tid1 = rt_thread_create("thread1",
thread_entry,
(void*)1,
THREAD_STACK_SIZE,
THREAD_PRIORITY,
THREAD_TIMESLICE);
if (tid1 != RT_NULL)
rt_thread_startup(tid1);
/* 创建线程 2 */
tid2 = rt_thread_create("thread2",
thread_entry,
(void*)2, THREAD_STACK_SIZE,
THREAD_PRIORITY,
THREAD_TIMESLICE - 5);
if (tid2 != RT_NULL)
rt_thread_startup(tid2);
return 0;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(scheduler_hook, scheduler_hook sample);