• 【STM32F4】【银杏科技ARM+FPGA】iCore3移植RT-Thread--内核之空闲线程和钩子函数


    一、空闲线程

      空闲线程是系统线程中一个比较特殊的线程,它具有最低的优先级,当系统中无其他线程可运行时,调度器将调度到空闲线程。空闲线程通常是一个死循环,永远不被挂起,例如rt_thread_delay() , rt_sem_take() 等可能会导致线程挂起的函数都不能使用。RT-Thread实时操作系统为空闲线程提供了钩子函数(钩子函数:用户提供的一段代码,在系统运行的某一路径上设置一个钩子,当系统经过这个位置时,转而执行这个钩子函数,然后再返回到它的正常路径上),可以让系统在空闲的时候执行一些特定的任务,例如系统运行指示灯闪烁,电源管理等。

    二、钩子函数

      空闲钩子函数是空闲线程的钩子函数,由于空闲线程具有系统最低优先级,所以只有在CPU空闲的时候才会执行此钩子函数。

    三、空闲线程代码分析

    1. 空闲线程初始化
    void rt_thread_idle_init(void)
    {
        rt_ubase_t i;
        char tidle_name[RT_NAME_MAX];
    
        for (i = 0; i < _CPUS_NR; i++)
        {
            rt_sprintf(tidle_name, "tidle%d", i);
            rt_thread_init(&idle[i],
                           tidle_name,
                           rt_thread_idle_entry,           //空闲线程入口函数       
                           RT_NULL,                        //入口函数参数为空
                           &rt_thread_stack[i][0],         //空闲线程栈地址
                           sizeof(rt_thread_stack[i]),     //栈大小
                           RT_THREAD_PRIORITY_MAX - 1,     //优先级
                           32);                            //时间片为32个时钟节拍
            /* startup */
            rt_thread_startup(&idle[i]);
        }
    }

      2.空闲线程执行函数

    void rt_thread_idle_excute(void)
    {
        /* Loop until there is no dead thread. So one call to rt_thread_idle_excute
         * will do all the cleanups. */
        while (_has_defunct_thread())        //检查僵尸线程链表中是否存在僵尸线程,以前的版本中用if (!rt_list_isempty(&rt_thread_defunct))来判断,这样每次只能清除一个僵尸线程
        {
            rt_base_t lock;
            rt_thread_t thread;
    #ifdef RT_USING_MODULE
            rt_module_t module = RT_NULL;
    #endif
            RT_DEBUG_NOT_IN_INTERRUPT;      //确保此函数不是在中断服务中,若RT_DEBUG_CONTEXT_CHECK is 1 in rtdebug.h,则该宏表示这个函数不能用于中断ISR中。通过检查rt_interrupt_nest中断嵌套计数器是否为0来判断
    
            /* disable interrupt */
            lock = rt_hw_interrupt_disable();
    
            /* re-check whether list is empty */
            if (_has_defunct_thread())      //再次判断rt_thread_defunct是否为空,若不为空
            {
                /* get defunct thread */
                thread = rt_list_entry(rt_thread_defunct.next,
                                       struct rt_thread,
                                       tlist);          //获取待回收的僵尸线程 
    #ifdef RT_USING_MODULE
                /* get thread's parent module */
                module = (rt_module_t)thread->module_id;//得到模块ID
    
                /* if the thread is module's main thread */
                if (module != RT_NULL && module->module_thread == thread)
                {
                    /* detach module's main thread */
                    module->module_thread = RT_NULL;    //清空模块线程  
                }
    #endif
                /* remove defunct thread */
                rt_list_remove(&(thread->tlist));       //重置线程链表节点为初始值,即节点next与prev均指向自身节点,即将线程从僵尸线程链表中移除  
                /* invoke thread cleanup */
                if (thread->cleanup != RT_NULL)
                    thread->cleanup(thread);            //执行线程清理函数 
    
                /* if it's a system object, not delete it */
                if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)//若该僵尸线程内核对象为静态对象,则不删除该对程内核对象
                {
                    /* enable interrupt */
                    rt_hw_interrupt_enable(lock);
    
                    return;
                }
            }
            else                        //若再次判断rt_thread_defunct僵尸线程链表为空
            {
                /* enable interrupt */
                rt_hw_interrupt_enable(lock);
    
                /* may the defunct thread list is removed by others, just return */
                return;
            }
    
            /* enable interrupt */
            rt_hw_interrupt_enable(lock);
    
    #ifdef RT_USING_HEAP                //程序运行到这,说明上文处理的僵尸线程为动态创建的线程
    #if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
            /* the thread belongs to an application module */
            if (thread->flags & RT_OBJECT_FLAG_MODULE)
                rt_module_free((rt_module_t)thread->module_id, thread->stack_addr);//释放模块主线程栈所占内存
            else
    #endif
            /* release thread's stack */
            RT_KERNEL_FREE(thread->stack_addr);   //释放动态线程栈所占内存
            /* delete thread object */
            rt_object_delete((rt_object_t)thread);//删除动态线程内核对象,即从当前类型的内核对象链表中移除,同时释放内核对象所占空间(若使用了模块功能,还要释放模块ID所占空间)
    #endif
    
    #ifdef RT_USING_MODULE
            if (module != RT_NULL)
            {
                extern rt_err_t rt_module_destroy(rt_module_t module);
    
                          /* if sub thread list and main thread are all empty */  //若模块主线程为空,且子线程对象链表为空
                if ((module->module_thread == RT_NULL) &&
                    rt_list_isempty(&module->module_object[RT_Object_Class_Thread].object_list))
                {
                    module->nref --;
                }
    
                /* destroy module */
                if (module->nref == 0)
                    rt_module_destroy(module);//销毁模块  
            }
    #endif
        }
    }
  • 相关阅读:
    Difference between sendRedirect, include, forward
    Selenium Study Notes
    Java基础知识2
    JSP上的JavaBeans
    Java Socket 7部曲
    Javascript版本排序1
    Java基础知识1
    JavaBean的属性
    测试基础
    annotation本质
  • 原文地址:https://www.cnblogs.com/xiaomagee/p/13029650.html
Copyright © 2020-2023  润新知