zoukankan      html  css  js  c++  java
  • 【RTThread】内核线程调度算法(基于位图的线程调度算法)

    • 在实时操作系统中,对时间的要求度很高,所以在线程调度算法RT-Thread采用的是位图调度算法,时间复杂度为O(1)。本篇采用最大优先级为32的情况进行讲解,256与之类似。
    /* Maximum priority level, 32 */
    rt_uint32_t rt_thread_ready_priority_group;  //[0:31]每一位代表一个线程优先级

    1. rt_thread_ready_priority_group是一个32位全局变量,如果有新的线程创建,则会把对应的线程优先级在rt_thread_ready_priority_group对应的bit位置1。

    例如:新创建的线程优先级为8,则由1,2可以看出将rt_thread_ready_priority_group的第8位置位1。

    2.接下来在rt_schedule中看rt_thread_ready_priority_group变量的使用。

    const rt_uint8_t __lowest_bit_bitmap[] =
    {
        /* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
        /* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
    };
    
    /**
     * This function finds the first bit set (beginning with the least significant bit)
     * in value and return the index of that bit.
     *
     * Bits are numbered starting at 1 (the least significant bit).  A return value of
     * zero from any of these functions means that the argument was zero.
     *
     * @return return the index of the first bit set. If value is 0, then this function
     * shall return 0.
     */
    int __rt_ffs(int value)
    {
        if (value == 0) return 0;
        if (value & 0xff)
            return __lowest_bit_bitmap[value & 0xff] + 1;
    
        if (value & 0xff00)
            return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9;
    
        if (value & 0xff0000)
            return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17;
    
        return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;
    }

    源码中的__lowest_bit_bitmap数组是根据线程优先级进行提前推算出来的。value也即rt_thread_ready_priority_group。

    例如: value = 8, 8的二进制为1000,从右往左数,第一个为1的位在第3位(默认从0开始)。所以__lowest_bit_bitmap[8]为3。

               value = 5,   5的二进制为101,从右往走数,第一个为1的位在第0位。所以__lowest_bit_bitmap[5]为0。

       value = 16,   5的二进制为10000,从右往走数,第一个为1的位在第4位。所以__lowest_bit_bitmap[16]为4。

     由数组可以找到rt_thread_ready_priority_group数值对应的最高优先级数为多少,也就找到了最高优先级线程所在的链表。

    而通过3求得的highest_ready_priority有如下作用:

    RT-Thread中的TCB数据结构,我们暂时只记住tlist成员:

    struct rt_thread
    {
        /* rt object */
        char        name[RT_NAME_MAX];                      /**< the name of thread */
        rt_uint8_t  type;                                   /**< type of object */
        rt_uint8_t  flags;                                  /**< thread's flags */
    
    #ifdef RT_USING_MODULE
        void       *module_id;                              /**< id of application module */
    #endif
    
        rt_list_t   list;                                   /**< the object list */
        rt_list_t   tlist;                                  /**< the thread list */
    
        /* stack point and entry */
        void       *sp;                                     /**< stack point */
        void       *entry;                                  /**< entry */
        void       *parameter;                              /**< parameter */
        void       *stack_addr;                             /**< stack address */
        rt_uint32_t stack_size;                             /**< stack size */
    
        /* error code */
        rt_err_t    error;                                  /**< error code */
    
        rt_uint8_t  stat;                                   /**< thread status */
    
        /* priority */
        rt_uint8_t  current_priority;                       /**< current priority */
        rt_uint8_t  init_priority;                          /**< initialized priority */
    #if RT_THREAD_PRIORITY_MAX > 32
        rt_uint8_t  number;
        rt_uint8_t  high_mask;
    #endif
        rt_uint32_t number_mask;
    
    #if defined(RT_USING_EVENT)
        /* thread event */
        rt_uint32_t event_set;
        rt_uint8_t  event_info;
    #endif
    
    #if defined(RT_USING_SIGNALS)
        rt_sigset_t     sig_pending;                        /**< the pending signals */
        rt_sigset_t     sig_mask;                           /**< the mask bits of signal */
    
        void            *sig_ret;                           /**< the return stack pointer from signal */
        rt_sighandler_t *sig_vectors;                       /**< vectors of signal handler */
        void            *si_list;                           /**< the signal infor list */
    #endif
    
        rt_ubase_t  init_tick;                              /**< thread's initialized tick */
        rt_ubase_t  remaining_tick;                         /**< remaining tick */
    
        struct rt_timer thread_timer;                       /**< built-in thread timer */
    
        void (*cleanup)(struct rt_thread *tid);             /**< cleanup function when thread exit */
    
        /* light weight process if present */
    #ifdef RT_USING_LWP
        void        *lwp;
    #endif
    
        rt_uint32_t user_data;                             /**< private user data beyond this thread */
    };

    优先级链表:

    rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX]; //每一个优先级对应一个链表。是通过rt_thread结构中的tlist成员来进行相同优先级线程的链接

    通过tlist成员来获取对应的rt_thread结构体的首地址信息。

    /* get switch to thread */
    /*/ to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next, struct rt_thread, tlist);

                       
    #define rt_list_entry(node, type, member) \ rt_container_of(node, type, member) #define rt_container_of(ptr, type, member) \ //在linux内核中该用法有很多 ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
    该成员所在的地址 - 该成员相对于结构体偏移的地址 = 该结构体的首地址

    综上,就可以找到对应的优先级数最高的线程进行调度。由于表是提前计算好的,所以时间复杂度为o(1)。

  • 相关阅读:
    could not read data from '/Users/lelight/Desktop/ViewControllerLife/ViewControllerLife/Info.plist': The file “Info.plist” couldn’t be opened because there is no such file.
    NSNotification 消息通知的3种方式
    按钮点击播放音效
    字符串变枚举变量
    Flutter的使用教学笔记
    UI控件的位置
    博客园大佬主页跳转
    retain, copy, assign区别
    OC自定义文档头部注释
    OC语言自定义打印
  • 原文地址:https://www.cnblogs.com/Raowz/p/13163120.html
Copyright © 2011-2022 走看看