• Rt-Thread 6-空闲线程


    目录

    1、rt_thread_idle_init()函数

    2、rt_thread_idle_entry()函数

    3、 _has_defunct_thread()函数

    4、 rt_thread_idle_excute()函数

    4.1、2次调用_has_defunct_thread()解析

    4.2、关中断为什么在二处之间,而不是循环外说明

    5、rt_thread_idle_gethandler()函数

    6、rt_thread_idle_sethook()函数

    7、rt_thread_idle_delhook()函数


    在 idle 线程内部不允许执行线程挂起操作,所以 Flash 、网络等后端可能无法基于 idle 线程使用。

    1、rt_thread_idle_init()函数

    初始化空闲线程。

    1. void rt_thread_idle_init(void)
    2. {
    3. /* 初始化空闲线程 */
    4. rt_thread_init(&idle,
    5. "idle",
    6. rt_thread_idle_entry,
    7. RT_NULL,
    8. &rt_thread_stack[0],
    9. sizeof(rt_thread_stack),
    10. RT_THREAD_PRIORITY_MAX - 1,
    11. 32);
    12. rt_thread_startup(&idle); //启动线程
    13. }

    2、rt_thread_idle_entry()函数

    空闲线程入口函数。

    1)如果存在空闲钩子函数,将调用钩子函数。

    2)*调用rt_thread_idle_excute()函数执行空闲时做的一些后台工作

    3)*调用rt_system_power_manager()函数进行电源管理,如低功耗。

    1. static void rt_thread_idle_entry(void *parameter)
    2. {
    3. while (1)
    4. {
    5. /* 如果存在空闲钩子函数,将调用钩子函数 */
    6. #ifdef RT_USING_IDLE_HOOK
    7. rt_size_t i;
    8. for (i = 0; i < RT_IDEL_HOOK_LIST_SIZE; i++)
    9. {
    10. if (idle_hook_list[i] != RT_NULL)
    11. {
    12. idle_hook_list[i]();
    13. }
    14. }
    15. #endif
    16. rt_thread_idle_excute(); //空闲时做的一些后台工作
    17. #ifdef RT_USING_PM
    18. rt_system_power_manager(); //电源管理
    19. #endif
    20. }
    21. }

    3、 _has_defunct_thread()函数

    rt_list_isempty的原型为“int rt_list_isempty(const rt_list_t *l)”。因此,编译器有充分的理由在rt_thread_idle_excute中不更改rt_thread_defunct列表,从而将“while”循环优化为“if”循环。所以在这里添加volatile限定符。

    1. rt_inline int _has_defunct_thread(void)
    2. {
    3. const volatile rt_list_t *l = (const volatile rt_list_t *)&rt_thread_defunct;
    4. return l->next != l;
    5. }

    4、 rt_thread_idle_excute()函数

    进行以下循环,直至无僵尸线程:

    1)获取僵尸线程,并从僵尸链表中移除

    2)调用线程清理函数

    3)如果是静态线程对象,脱离对象后直接返回

    4)如果是动态线程对象,释放动态线程栈内存,删除动态线程对象,然后继续循环

    1. void rt_thread_idle_excute(void)
    2. {
    3. while (_has_defunct_thread())
    4. {
    5. rt_base_t lock;
    6. rt_thread_t thread;
    7. #ifdef RT_USING_MODULE
    8. struct rt_dlmodule *module = RT_NULL;
    9. #endif
    10. RT_DEBUG_NOT_IN_INTERRUPT;
    11. lock = rt_hw_interrupt_disable(); //关中断
    12. /* 重新检查僵尸链表是否为空 */
    13. if (_has_defunct_thread())
    14. {
    15. /* 获取僵尸线程 */
    16. thread = rt_list_entry(rt_thread_defunct.next,
    17. struct rt_thread,
    18. tlist);
    19. #ifdef RT_USING_MODULE
    20. module = (struct rt_dlmodule*)thread->module_id;
    21. if (module)
    22. {
    23. dlmodule_destroy(module);
    24. }
    25. #endif
    26. /* 从僵尸链表中移除 */
    27. rt_list_remove(&(thread->tlist));
    28. rt_enter_critical(); //进入临界区
    29. /* 调用线程清理函数 */
    30. if (thread->cleanup != RT_NULL)
    31. thread->cleanup(thread);
    32. #ifdef RT_USING_SIGNALS
    33. rt_thread_free_sig(thread);
    34. #endif
    35. /* 如果是系统对象 */
    36. if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
    37. {
    38. rt_object_detach((rt_object_t)thread); //脱离对象
    39. rt_exit_critical(); //退出临界区
    40. rt_hw_interrupt_enable(lock); //开中断
    41. return;
    42. }
    43. rt_exit_critical(); //退出临界区
    44. }
    45. else
    46. {
    47. rt_hw_interrupt_enable(lock); //开中断
    48. return;
    49. }
    50. rt_hw_interrupt_enable(lock); //开中断
    51. #ifdef RT_USING_HEAP
    52. RT_KERNEL_FREE(thread->stack_addr); //释放动态线程栈内存
    53. rt_object_delete((rt_object_t)thread); //删除动态线程对象
    54. #endif
    55. }
    56. }

    4.1、2次调用_has_defunct_thread()解析

    第一处while (_has_defunct_thread()),用于循环处理所有僵尸线程

    第二处if (_has_defunct_thread()),用于确认存在僵尸线程。在第一处和第二处之间未关中断前,可能因为调度,僵尸线程被其他线程从僵尸链表中移除.所以需要二次确认。

    4.2、关中断为什么在二处之间,而不是循环外说明

    为了实时性,在循环期间可以被抢占。

    5、rt_thread_idle_gethandler()函数

    返回空闲线程控制块。

    1. rt_thread_t rt_thread_idle_gethandler(void)
    2. {
    3. return (rt_thread_t)(&idle);
    4. }

    6、rt_thread_idle_sethook()函数

    设置空闲钩子函数。最多可有RT_IDEL_HOOK_LIST_SIZE个空闲钩子函数

    1. rt_err_t rt_thread_idle_sethook(void (*hook)(void))
    2. {
    3. rt_size_t i;
    4. rt_base_t level;
    5. rt_err_t ret = -RT_EFULL;
    6. level = rt_hw_interrupt_disable(); //关中断
    7. /* 将钩子函数放入钩子函数数组中 */
    8. for (i = 0; i < RT_IDEL_HOOK_LIST_SIZE; i++)
    9. {
    10. if (idle_hook_list[i] == RT_NULL)
    11. {
    12. idle_hook_list[i] = hook;
    13. ret = RT_EOK;
    14. break;
    15. }
    16. }
    17. rt_hw_interrupt_enable(level); //开中断
    18. return ret;
    19. }

    7、rt_thread_idle_delhook()函数

    从空闲钩子函数数组删除指定空闲钩子函数。

    1. rt_err_t rt_thread_idle_delhook(void (*hook)(void))
    2. {
    3. rt_size_t i;
    4. rt_base_t level;
    5. rt_err_t ret = -RT_ENOSYS;
    6. level = rt_hw_interrupt_disable(); //关中断
    7. /* 从空闲钩子函数数组删除指定空闲钩子函数 */
    8. for (i = 0; i < RT_IDEL_HOOK_LIST_SIZE; i++)
    9. {
    10. if (idle_hook_list[i] == hook)
    11. {
    12. idle_hook_list[i] = RT_NULL;
    13. ret = RT_EOK;
    14. break;
    15. }
    16. }
    17. rt_hw_interrupt_enable(level); //开中断
    18. return ret;
    19. }

  • 相关阅读:
    10、斐波那契数列
    git 进阶系列教程--pull
    linux搭建pyspark环境,本地pycharm使用远程连接
    Mysql加锁流程详解
    Java内存区域与内存溢出异常
    代码随想录算法训练营第一天|LeetCode704二分查找、LeetCode27移除元素
    解析企业绩效通系统架构:构建高效管理与激励平台
    视频汇聚平台EasyCVR从一分屏切换到四分屏后加载记录显示黑屏该如何解决?
    C++经典笔试题
    猿创征文|【设备云】FlexManager和阿里云MQTT通讯实例详解
  • 原文地址:https://blog.csdn.net/qq_37932504/article/details/126549408