• Rt-Thread 4-线程


    目录

    1、基本概念

    1.1、线程栈

    1.1.1、线程栈大小设置

    1.2、线程管理的功能特点

    1.3、线程状态

    1.3.1、线程状态切换 

    ​编辑

    1.4、线程优先级

    1.5、时间片

    2、线程控制块

    3、函数

    3.1、内部函数

    3.1.1、_rt_thread_init()函数

    3.1.2、_thread_cleanup_execute()函数

    3.2、接口函数

    3.2.1、rt_thread_init()函数

    3.2.2、rt_thread_create()函数

    3.2.3、rt_thread_detach()函数

    3.2.4、rt_thread_delete()函数

    3.2.5、rt_thread_startup()函数

    3.2.6、rt_thread_resume()函数

    3.2.7、rt_thread_exit()函数

    3.2.8、rt_thread_yield()函数

    3.2.9、rt_thread_sleep()函数

    3.2.10、rt_thread_delay()函数

    3.2.11、rt_thread_mdelay()函数

    3.2.12、rt_thread_delay_until()函数

    3.2.13、rt_thread_control()线程控制

    3.2.14、rt_thread_suspend()函数

    3.2.15、rt_thread_timeout()函数

    3.2.16、rt_thread_find()函数 

    3.2.17、rt_thread_self()函数

    3.2.18、rt_thread_suspend_sethook()函数

    3.2.19、rt_thread_resume_sethook()函数

    3.2.20、rt_thread_inited_sethook()函数


    1、基本概念

    1.1、线程栈

    RT-Thread 线程具有独立的栈,当进行线程切换时,会将当前线程的上下文存在栈中,当线程要恢复运行时,再从栈中读取上下文信息(具体来说就是各个变量和数据,包括所有的寄存器变量、堆栈、内存信息等),进行恢复。

    1.1.1、线程栈大小设置

    对于资源相对较大的 MCU,可以适当设计较大的线程栈;

    也可以在初始时设置较大的栈,例如指定大小为 1K 或 2K 字节,然后在 FinSH 中用 list_thread 命令查看线程运行的过程中线程所使用的栈的大小,通过此命令,能够看到从线程启动运行时,到当前时刻点,线程使用的最大栈深度,而后加上适当的余量形成最终的线程栈大小,最后对栈空间大小加以修改。

    1.2、线程管理的功能特点

    RT-Thread 的线程调度器是抢占式的,主要的工作就是从就绪线程列表中查找最高优先级线程,保证最高优先级的线程能够被运行,最高优先级的任务一旦就绪,总能得到 CPU 的使用权。

    当一个运行着的线程使一个比它优先级高的线程满足运行条件,当前线程的 CPU 使用权就被剥夺了,或者说被让出了,高优先级的线程立刻得到了 CPU 的使用权。

    如果是中断服务程序使一个高优先级的线程满足运行条件,中断完成时,被中断的线程挂起,优先级高的线程开始运行。
    当调度器调度线程切换时,先将当前线程上下文保存起来,当再切回到这个线程时,线程调度器将该线程的上下文信息恢复。

    1.3、线程状态

    在 RT-Thread 中,线程包含五种状态。

    状态说明
    RT_THREAD_INIT初始状态当线程刚开始创建还没开始运行时就处于初始状态;在初始状态下,线程不参与调度。
    RT_THREAD_READY就绪状态在就绪状态下,线程按照优先级排队,等待被执行;一旦当前线程运行完毕让出处理器,操
    作系统会马上寻找最高优先级的就绪态线程运行。
    RT_THREAD_RUNNING运行状态线程当前正在运行。在单核系统中,只有 rt_thread_self() 函数返回的线程处于运行状态;
    在多核系统中,可能就不止这一个线程处于运行状态
    RT_THREAD_SUSPEND挂起状态(阻塞态)它可能因为资源不可用而挂起等待,或线程主动延时一段时间而挂起。在挂起
    状态下,线程不参与调度。
    RT_THREAD_CLOSE关闭状态当线程运行结束时将处于关闭状态。关闭状态的线程不参与线程的调度。

    1.3.1、线程状态切换 

    1.4、线程优先级

    RT-Thread 线程的优先级是表示线程被调度的优先程度。每个线程都具有优先级,线程越重要,赋予的优先级就应越高,线程被调度的可能性才会越大。在系统中,当有比当前线程优先级更高的线程就绪时,当前线程将立刻被换出,高优先级线程抢占处理器运行。
    RT-Thread 最大支持 256 个线程优先级 (0~255),数值越小的优先级越高, 0 为最高优先级。在一些资源比较紧张的系统中,可以根据实际情况选择只支持 8 个或 32 个优先级的系统配置;

    注:最低优先级默认分配给空闲线程使用,用户一般不使用。

    1.5、时间片

    每个线程都有时间片这个参数,但时间片仅对优先级相同的就绪态线程有效。

    系统对优先级相同的就绪态线程采用时间片轮转的调度方式进行调度时,时间片起到约束线程单次运行时长的作用,其单位是一个系统节拍。

    2、线程控制块

    线程控制块由结构体 struct rt_thread 表示,线程控制块是操作系统用于管理线程的一个数据结构,它会存放线程的一些信息,例如优先级、线程名称、线程状态等,也包含线程与线程之间连接用的链表结构,线程等待事件集合等。

    1. struct rt_thread
    2. {
    3. char name[RT_NAME_MAX]; /* 线程名字 */
    4. rt_uint8_t type; /* 对象类型 */
    5. rt_uint8_t flags; /* 线程标志 */
    6. rt_list_t list; /* 对象链表 */
    7. rt_list_t tlist; /* 线程链表节点 */
    8. /* stack point and entry */
    9. void *sp; /* 栈指针 */
    10. void *entry; /* 入口函数 */
    11. void *parameter; /* 参数 */
    12. void *stack_addr; /* 栈地址 */
    13. rt_uint32_t stack_size; /* 栈大小 */
    14. rt_err_t error; /* 线程错误码* /
    15. rt_uint8_t stat; /* 线程状态 */
    16. rt_uint8_t current_priority; /* 当前优先级*/
    17. rt_uint8_t init_priority; /* 初始优先级 */
    18. #if RT_THREAD_PRIORITY_MAX > 32
    19. rt_uint8_t number;
    20. rt_uint8_t high_mask;
    21. #endif
    22. rt_uint32_t number_mask;
    23. #if defined(RT_USING_EVENT)
    24. rt_uint32_t event_set; /* 事件集 */
    25. rt_uint8_t event_info; /* 事件信息 */
    26. #endif
    27. rt_ubase_t init_tick; /* 时间片 */
    28. rt_ubase_t remaining_tick; /* 剩余时间 */
    29. struct rt_timer thread_timer; /* 线程定时器 */
    30. void (*cleanup)(struct rt_thread *tid); /* 线程退出回调函数 */
    31. rt_uint32_t user_data; /* 用户数据 */
    32. };
    33. typedef struct rt_thread *rt_thread_t;

    3、函数

    3.1、内部函数

    3.1.1、_rt_thread_init()函数

    此函数用于初始化线程资源。

    1)初始化线程链表

    2)设置栈环境

    3)设置线程优先级

    4)初始化线程参数

    5)初始化线程定时器

    6)调用钩子回调函数

    1. static rt_err_t _rt_thread_init(struct rt_thread *thread,
    2. const char *name,
    3. void (*entry)(void *parameter),
    4. void *parameter,
    5. void *stack_start,
    6. rt_uint32_t stack_size,
    7. rt_uint8_t priority,
    8. rt_uint32_t tick)
    9. {
    10. rt_list_init(&(thread->tlist)); //初始化线程链表
    11. thread->entry = (void *)entry; //设置入口函数
    12. thread->parameter = parameter; //设置入口参数
    13. thread->stack_addr = stack_start; //设置栈地址
    14. thread->stack_size = stack_size; //设置栈大小
    15. rt_memset(thread->stack_addr, '#', thread->stack_size); //初始化线程栈空间,设置为全'#'
    16. #ifdef ARCH_CPU_STACK_GROWS_UPWARD //向上生长的栈
    17. thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
    18. (void *)((char *)thread->stack_addr),
    19. (void *)rt_thread_exit); //栈初始化
    20. #else //向下生长的栈
    21. thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
    22. (void *)((char *)thread->stack_addr + thread->stack_size - 4),
    23. (void *)rt_thread_exit); //栈初始化
    24. #endif
    25. RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX); //断言priority < RT_THREAD_PRIORITY_MAX
    26. thread->init_priority = priority; //设置线程优先级为priority
    27. thread->current_priority = priority; //设置线程当前优先级为priority
    28. thread->number_mask = 0; //设置线程number_mask为0
    29. #if RT_THREAD_PRIORITY_MAX > 32 //最大优先级大于32
    30. thread->number = 0; //设置线程number为0
    31. thread->high_mask = 0; //设置线程high_mask为0
    32. #endif
    33. thread->init_tick = tick; //设置init_tick为0
    34. thread->remaining_tick = tick; //设置线程remaining_tick为0
    35. thread->error = RT_EOK; //设置线程错误码为RT_EOK
    36. thread->stat = RT_THREAD_INIT; //设置线程状态为RT_THREAD_INIT
    37. thread->cleanup = 0; //设置线程cleanup为0
    38. thread->user_data = 0; //设置线程user_data为0
    39. rt_timer_init(&(thread->thread_timer),
    40. thread->name,
    41. rt_thread_timeout,
    42. thread,
    43. 0,
    44. RT_TIMER_FLAG_ONE_SHOT); //初始化线程定时器
    45. RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread)); //调用回调
    46. return RT_EOK; //返回RT_EOK
    47. }

    3.1.2、_thread_cleanup_execute()函数

    执行线程退出回调函数。

    1. static void _thread_cleanup_execute(rt_thread_t thread)
    2. {
    3. register rt_base_t level;
    4. level = rt_hw_interrupt_disable();
    5. /* 调用线程清理函数 */
    6. if (thread->cleanup != RT_NULL)
    7. thread->cleanup(thread);
    8. rt_hw_interrupt_enable(level);
    9. }

    3.2、接口函数

    3.2.1、rt_thread_init()函数

    此函数将初始化一个线程。

    1)初始化线程对象

    2)初始化线程

    1. rt_err_t rt_thread_init(struct rt_thread *thread,
    2. const char *name,
    3. void (*entry)(void *parameter),
    4. void *parameter,
    5. void *stack_start,
    6. rt_uint32_t stack_size,
    7. rt_uint8_t priority,
    8. rt_uint32_t tick)
    9. {
    10. /* 参数检查 */
    11. RT_ASSERT(thread != RT_NULL); //断言thread != RT_NULL
    12. RT_ASSERT(stack_start != RT_NULL); //断言stack_start != RT_NULL
    13. rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name); //初始化线程对象
    14. return _rt_thread_init(thread,
    15. name,
    16. entry,
    17. parameter,
    18. stack_start,
    19. stack_size,
    20. priority,
    21. tick); //线程初始化
    22. }

    3.2.2、rt_thread_create()函数

    此函数将创建一个线程对象并分配线程对象内存和堆栈。

    1)分配线程对象

    2)分配栈空间

    3)初始化线程

    1. rt_thread_t rt_thread_create(const char *name,
    2. void (*entry)(void *parameter),
    3. void *parameter,
    4. rt_uint32_t stack_size,
    5. rt_uint8_t priority,
    6. rt_uint32_t tick)
    7. {
    8. struct rt_thread *thread;
    9. void *stack_start;
    10. thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread,
    11. name); //分配线程对象
    12. if (thread == RT_NULL) //分配对象失败
    13. return RT_NULL; //返回RT_NULL
    14. stack_start = (void *)RT_KERNEL_MALLOC(stack_size); //分配线程内存
    15. if (stack_start == RT_NULL) //分配失败
    16. {
    17. rt_object_delete((rt_object_t)thread); //删除对象
    18. return RT_NULL; //返回RT_NULL
    19. }
    20. _rt_thread_init(thread,
    21. name,
    22. entry,
    23. parameter,
    24. stack_start,
    25. stack_size,
    26. priority,
    27. tick); //线程初始化
    28. return thread; //返回线程
    29. }

    3.2.3、rt_thread_detach()函数

    此函数将分离一个线程。线程对象将从线程队列中删除,并从对象容器管理中分离/删除。

    1)从调度器中移除线程

    2)执行线程退出回调函数

    3)调用rt_timer_detach()函数卸载线程定时器

    4)改变线程状态为RT_THREAD_CLOSE

    5)如果存在线程是静态的,则卸载线程对象。否则将线程插入到僵尸线程链表中。

    1. rt_err_t rt_thread_detach(rt_thread_t thread)
    2. {
    3. rt_base_t lock;
    4. /* 参数检查 */
    5. RT_ASSERT(thread != RT_NULL); //断言thread != RT_NULL
    6. RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); //断言对象是线程
    7. RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread)); //断言对象是静态的
    8. if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
    9. return RT_EOK;
    10. if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT) //线程不等于RT_THREAD_INIT
    11. {
    12. rt_schedule_remove_thread(thread); //从调度器中移除线程
    13. }
    14. _thread_cleanup_execute(thread); //线程退出回调函数
    15. rt_timer_detach(&(thread->thread_timer)); //释放线程定时器
    16. thread->stat = RT_THREAD_CLOSE; //改变线程状态为RT_THREAD_CLOSE
    17. if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) //线程是静态的,同时线程cleanup为RT_NULL
    18. {
    19. rt_object_detach((rt_object_t)thread); //线程对象脱离
    20. }
    21. else
    22. {
    23. lock = rt_hw_interrupt_disable(); //关中断
    24. rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); //将线程插入到僵尸线程链表
    25. rt_hw_interrupt_enable(lock); //开中断
    26. }
    27. return RT_EOK; //返回RT_EOK
    28. }

    注:此函数可用于静态线程和动态线程的卸载。

    3.2.4、rt_thread_delete()函数

    此函数将删除一个线程。线程对象将从线程队列中删除,并从空闲线程中的对象容器管理中删除。

    1)从就绪链表移除线程

    2)执行线程退出回调函数

    3)调用rt_timer_detach()函数卸载线程定时器

    4)改变线程状态为RT_THREAD_CLOSE

    5)将线程插入到僵尸线程链表中。

    1. rt_err_t rt_thread_delete(rt_thread_t thread)
    2. {
    3. rt_base_t lock;
    4. /* 参数检查 */
    5. RT_ASSERT(thread != RT_NULL); //断言thread != RT_NULL
    6. RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); //断言对象是线程
    7. RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread) == RT_FALSE); //断言线程不是静态的
    8. if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT) //线程的状态不为RT_THREAD_INIT
    9. {
    10. rt_schedule_remove_thread(thread); //从调度器中移除线程
    11. }
    12. _thread_cleanup_execute(thread); //线程退出回调函数
    13. rt_timer_detach(&(thread->thread_timer)); //释放线程定时器
    14. thread->stat = RT_THREAD_CLOSE; //改变线程状态
    15. lock = rt_hw_interrupt_disable(); //关中断
    16. rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); //将线程插入到僵尸线程链表
    17. rt_hw_interrupt_enable(lock); //开中断
    18. return RT_EOK; //返回RT_EOK
    19. }

    3.2.5、rt_thread_startup()函数

    此函数将启动一个线程并将其放入系统就绪队列。

    1)设置线程当前优先级为线程优先级

    2)计算优先级属性

    3)改变线程状态为RT_THREAD_SUSPEND; 

    4) 调用rt_thread_resume()函数唤醒线程

    5)调度

    1. rt_err_t rt_thread_startup(rt_thread_t thread)
    2. {
    3. /* 参数检查 */
    4. RT_ASSERT(thread != RT_NULL); //断言thread != RT_NULL
    5. RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT); //断言线程状态为RT_THREAD_INIT
    6. RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); //断言对象是线程
    7. thread->current_priority = thread->init_priority; //设置线程当前优先级为线程优先级
    8. /* 计算优先级属性 */
    9. #if RT_THREAD_PRIORITY_MAX > 32 //最大优先级大于32
    10. thread->number = thread->current_priority >> 3; //优先级组
    11. thread->number_mask = 1L << thread->number; //优先级组掩码
    12. thread->high_mask = 1L << (thread->current_priority & 0x07); //组子优先级
    13. #else //最大优先级小于32
    14. thread->number_mask = 1L << thread->current_priority; //优先级
    15. #endif
    16. RT_DEBUG_LOG(RT_DEBUG_THREAD, ("startup a thread:%s with priority:%d\n",
    17. thread->name, thread->init_priority)); //打印信息
    18. thread->stat = RT_THREAD_SUSPEND; //改变线程状态
    19. rt_thread_resume(thread); //唤醒线程
    20. if (rt_thread_self() != RT_NULL) //已经开始调度
    21. {
    22. rt_schedule(); //调度
    23. }
    24. return RT_EOK; //返回RT_EOK
    25. }

    3.2.6、rt_thread_resume()函数

    此函数将恢复一个线程并将其放入系统就绪队列。

    1)移除线程链表节点

    2)停止线程定时器

    3)将线程插入到就绪链表

    4)调用钩子回调函数

    1. rt_err_t rt_thread_resume(rt_thread_t thread)
    2. {
    3. register rt_base_t temp;
    4. /* 参数检查 */
    5. RT_ASSERT(thread != RT_NULL); //断言thread != RT_NULL
    6. RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); //断言对象是线程
    7. RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: %s\n", thread->name)); //打印信息
    8. if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND) //线程状态不为挂起态
    9. {
    10. RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n",
    11. thread->stat)); //打印信息
    12. return -RT_ERROR; //返回-RT_ERROR
    13. }
    14. temp = rt_hw_interrupt_disable(); //关中断
    15. rt_list_remove(&(thread->tlist)); //从挂起链表中移除
    16. rt_timer_stop(&thread->thread_timer); //停止线程定时器
    17. rt_hw_interrupt_enable(temp); //开中断
    18. rt_schedule_insert_thread(thread); //将线程插入到调度器
    19. RT_OBJECT_HOOK_CALL(rt_thread_resume_hook, (thread)); //调用回调
    20. return RT_EOK; //返回RT_EOK
    21. }

    3.2.7、rt_thread_exit()函数

    此函数将退出一个线程。

    1)从调度器中移除线程

    2)改变线程状态为RT_THREAD_CLOSE

    3)卸载线程定时器

    4)如果是静态的,线程对象脱离。否则将线程插入到僵尸线程链表

    5)调度

    1. void rt_thread_exit(void)
    2. {
    3. struct rt_thread *thread;
    4. register rt_base_t level;
    5. thread = rt_current_thread; //获取当前线程
    6. level = rt_hw_interrupt_disable(); //关中断
    7. rt_schedule_remove_thread(thread); //从调度器中移除线程
    8. thread->stat = RT_THREAD_CLOSE; //改变线程状态
    9. rt_timer_detach(&thread->thread_timer); //卸载线程定时器
    10. if ((rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) &&
    11. thread->cleanup == RT_NULL) //线程是静态的,同时线程cleanup为RT_NULL
    12. {
    13. rt_object_detach((rt_object_t)thread); //线程对象脱离
    14. }
    15. else
    16. {
    17. rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); //将线程插入到僵尸线程链表
    18. }
    19. rt_hw_interrupt_enable(level); //开中断
    20. rt_schedule(); //调度
    21. }

    3.2.8、rt_thread_yield()函数

    此函数将让出当前线程处理器,调度程序将选择一个最高的线程运行。在让出处理器之后,当前线程仍然处于READY状态。

    1)程序处于就绪态且在就绪队列链表中时

    2)从链表中移除本线程

    3)将当前线程放到就绪队列队尾

    4)调度

    1. rt_err_t rt_thread_yield(void)
    2. {
    3. register rt_base_t level;
    4. struct rt_thread *thread;
    5. level = rt_hw_interrupt_disable(); //关中断
    6. thread = rt_current_thread; //设置为当前线程
    7. /* if the thread stat is READY and on ready queue list */
    8. if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY &&
    9. thread->tlist.next != thread->tlist.prev) //线程状态为就绪态,且线程链表不为空
    10. {
    11. rt_list_remove(&(thread->tlist)); //从线程链表中移除本线程
    12. rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
    13. &(thread->tlist)); //将线程放到就绪队列队尾
    14. rt_hw_interrupt_enable(level); //开中断
    15. rt_schedule(); //调度
    16. return RT_EOK; //返回RT_EOK
    17. }
    18. rt_hw_interrupt_enable(level); //开中断
    19. return RT_EOK; //返回RT_EOK
    20. }

    3.2.9、rt_thread_sleep()函数

    此函数将让当前线程休眠一些时间。

    1)挂起线程

    2)设置线程定时器时间

    3)启动线程定时器

    4)调度

    1. rt_err_t rt_thread_sleep(rt_tick_t tick)
    2. {
    3. register rt_base_t temp;
    4. struct rt_thread *thread;
    5. temp = rt_hw_interrupt_disable(); //关线程
    6. thread = rt_current_thread; //设置为当前线程
    7. RT_ASSERT(thread != RT_NULL); //断言thread != RT_NULL
    8. RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); //断言对象是线程
    9. rt_thread_suspend(thread); //挂起线程
    10. rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick); //设置线程定时器时间
    11. rt_timer_start(&(thread->thread_timer)); //启动线程定时器
    12. rt_hw_interrupt_enable(temp); //开中断
    13. rt_schedule(); //调度
    14. if (thread->error == -RT_ETIMEOUT) //线程错误码等于-RT_ETIMEOUT
    15. thread->error = RT_EOK; //返回RT_EOK
    16. return RT_EOK; //返回RT_EOK
    17. }

    3.2.10、rt_thread_delay()函数

    此函数将让当前线程延迟一些节拍。

    1. rt_err_t rt_thread_delay(rt_tick_t tick)
    2. {
    3. return rt_thread_sleep(tick); //调用rt_thread_sleep函数
    4. }

    3.2.11、rt_thread_mdelay()函数

    此函数将允许当前线程延迟几毫秒。

    1. rt_err_t rt_thread_mdelay(rt_int32_t ms)
    2. {
    3. rt_tick_t tick;
    4. tick = rt_tick_from_millisecond(ms); //将ms换算成需要多少tick
    5. return rt_thread_sleep(tick); //延时
    6. }

    3.2.12、rt_thread_delay_until()函数

    此函数延迟线程直到(*tick + inc_tick).

    1. rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick)
    2. {
    3. register rt_base_t level;
    4. struct rt_thread *thread;
    5. RT_ASSERT(tick != RT_NULL);
    6. thread = rt_thread_self(); //设置为当前线程
    7. RT_ASSERT(thread != RT_NULL);
    8. RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
    9. level = rt_hw_interrupt_disable(); //关中断
    10. if (rt_tick_get() - *tick < inc_tick)
    11. {
    12. *tick = *tick + inc_tick - rt_tick_get();
    13. rt_thread_suspend(thread); //挂起线程
    14. rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, tick); //复位线程定时器超时时间
    15. rt_timer_start(&(thread->thread_timer)); //启动线程定时器
    16. rt_hw_interrupt_enable(level); //开中断
    17. rt_schedule(); //调度
    18. /* 清除线程的error为RT_EOK */
    19. if (thread->error == -RT_ETIMEOUT)
    20. {
    21. thread->error = RT_EOK;
    22. }
    23. }
    24. else
    25. {
    26. rt_hw_interrupt_enable(level); //开中断
    27. }
    28. *tick = rt_tick_get(); //获取唤醒时的tick
    29. return RT_EOK;
    30. }

    3.2.13、rt_thread_control()线程控制

    该函数通过控制命令控制线程行为。

    RT_THREAD_CTRL_CHANGE_PRIORITY改变线程优先级
    RT_THREAD_CTRL_STARTUP启动线程
    RT_THREAD_CTRL_CLOSE关闭线程
    1. rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)
    2. {
    3. register rt_base_t temp;
    4. /* 参数检查 */
    5. RT_ASSERT(thread != RT_NULL); //断言thread != RT_NULL
    6. RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); //断言对象是线程
    7. switch (cmd)
    8. {
    9. case RT_THREAD_CTRL_CHANGE_PRIORITY: //控制优先级
    10. temp = rt_hw_interrupt_disable(); //关中断
    11. if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY) //线程状态为就绪态
    12. {
    13. rt_schedule_remove_thread(thread); //从调度器中移除
    14. thread->current_priority = *(rt_uint8_t *)arg; //改变线程当前优先级
    15. /* 重新计算优先级属性 */
    16. #if RT_THREAD_PRIORITY_MAX > 32
    17. thread->number = thread->current_priority >> 3; /* 5bit */
    18. thread->number_mask = 1 << thread->number;
    19. thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */
    20. #else
    21. thread->number_mask = 1 << thread->current_priority;
    22. #endif
    23. rt_schedule_insert_thread(thread); //插入到调度器中
    24. }
    25. else
    26. {
    27. thread->current_priority = *(rt_uint8_t *)arg; //改变线程当前优先级
    28. /* recalculate priority attribute */
    29. #if RT_THREAD_PRIORITY_MAX > 32
    30. thread->number = thread->current_priority >> 3; /* 5bit */
    31. thread->number_mask = 1 << thread->number;
    32. thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */
    33. #else
    34. thread->number_mask = 1 << thread->current_priority;
    35. #endif
    36. }
    37. rt_hw_interrupt_enable(temp); //开中断
    38. break;
    39. case RT_THREAD_CTRL_STARTUP: //启动线程
    40. return rt_thread_startup(thread); //调用rt_thread_startup函数
    41. #ifdef RT_USING_HEAP
    42. case RT_THREAD_CTRL_CLOSE: //删除线程
    43. return rt_thread_delete(thread); //调用rt_thread_delete函数
    44. #endif
    45. default:
    46. break;
    47. }
    48. return RT_EOK; //返回RT_EOK
    49. }

    3.2.14、rt_thread_suspend()函数

    此函数将挂起指定的线程。

    1)线程状态不等于就绪态的线程,直接返回

    2)设置线程状态为RT_THREAD_SUSPEND

    3)从调度器中移除线程

    4)停止线程定时器

    5)调用钩子回调函数

    1. rt_err_t rt_thread_suspend(rt_thread_t thread)
    2. {
    3. register rt_base_t temp;
    4. /* 参数检查 */
    5. RT_ASSERT(thread != RT_NULL); //断言thread != RT_NULL
    6. RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); //断言对象是线程
    7. RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: %s\n", thread->name)); //打印信息
    8. if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_READY) //线程状态不等于就绪态
    9. {
    10. RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, 0x%2x\n",
    11. thread->stat)); //打印信息
    12. return -RT_ERROR; //返回-RT_ERROR
    13. }
    14. temp = rt_hw_interrupt_disable(); //关中断
    15. /* 改变线程状态 */
    16. thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK); //设置线程状态为RT_THREAD_SUSPEND
    17. rt_schedule_remove_thread(thread); //从调度器中移除
    18. rt_timer_stop(&(thread->thread_timer)); //停止线程定时器
    19. rt_hw_interrupt_enable(temp); //开中断
    20. RT_OBJECT_HOOK_CALL(rt_thread_suspend_hook, (thread)); //调用回调
    21. return RT_EOK; //返回RT_EOK
    22. }

    3.2.15、rt_thread_timeout()函数

    此函数是线程的超时函数。

    1)设置error成员为-RT_ETIMEOUT

    2)从挂起链表中移除

    3)将线程插入到就绪链表

    4)调度

    1. void rt_thread_timeout(void *parameter)
    2. {
    3. struct rt_thread *thread;
    4. thread = (struct rt_thread *)parameter;
    5. /* 参数检查 */
    6. RT_ASSERT(thread != RT_NULL); //断言thread != RT_NULL
    7. RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND); //断言线程状态为挂起态
    8. RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); //断言对象是线程
    9. thread->error = -RT_ETIMEOUT; //设置线程错误码为-RT_ETIMEOUT
    10. rt_list_remove(&(thread->tlist)); //从挂起链表中移除
    11. rt_schedule_insert_thread(thread); //将线程插入到调度器
    12. rt_schedule(); //调度
    13. }

    3.2.16、rt_thread_find()函数 

    此函数用于根据名字查找指定线程。

    1. rt_thread_t rt_thread_find(char *name)
    2. {
    3. return (rt_thread_t)rt_object_find(name, RT_Object_Class_Thread);
    4. }

    3.2.17、rt_thread_self()函数

    此函数将返回当前的线程。

    1. rt_thread_t rt_thread_self(void)
    2. {
    3. return rt_current_thread; //返回rt_current_thread
    4. }

    3.2.18、rt_thread_suspend_sethook()函数

    设置线程挂起时的钩子函数。

    1. void rt_thread_suspend_sethook(void (*hook)(rt_thread_t thread))
    2. {
    3. rt_thread_suspend_hook = hook;
    4. }

    3.2.19、rt_thread_resume_sethook()函数

    设置线程恢复时的钩子函数。

    1. void rt_thread_resume_sethook(void (*hook)(rt_thread_t thread))
    2. {
    3. rt_thread_resume_hook = hook;
    4. }

    3.2.20、rt_thread_inited_sethook()函数

    设置线程初始化时的钩子函数。

    1. void rt_thread_inited_sethook(void (*hook)(rt_thread_t thread))
    2. {
    3. rt_thread_inited_hook = hook;
    4. }

  • 相关阅读:
    一种表达了1/4的差值结构
    <二.1> android 直接使用hal库播放pcm demo
    问题解决——SSH时出现WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!(转)
    Defocus(散焦)
    java计算机毕业设计旅游管理系统源码+mysql数据库+系统+lw文档+部署
    自定义View之Measure(二)
    【接口设计注意点】
    Oracle EBS form开发 提示 FRM-15500:Valid and unique object name must be entered
    【计算机网络】 IP协议格式以及以太网帧结构
    vue3 + vite + ts + setup , 第十七练 vue3 中使用vue-router(一),router跳转传参/嵌套路由/路由重定向/别名
  • 原文地址:https://blog.csdn.net/qq_37932504/article/details/115273567