How does the thread scheduler of RT thread find the task with the highest priority?

Posted by rg_22uk on Wed, 02 Feb 2022 14:37:00 +0100

One life, two sports, three geomantic omens, four accumulation of Yin virtue, five reading, six seven aspects, eight worship God, nine to noble people and ten health preservation.
----Folk products
Feng Tang's interpretation of the ten elements of success: one life, two movements, three Feng Shui, four accumulation of Yin virtue, five reading, six names, seven aspects and eight reverence for God

Open scheduler in RT thread kernel c. We can see the following code:

rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
#if RT_THREAD_PRIORITY_MAX > 32
/* Maximum priority level, 256 */
rt_uint32_t rt_thread_ready_priority_group;
rt_uint8_t rt_thread_ready_table[32];
#else
/* Maximum priority level, 32 */
rt_uint32_t rt_thread_ready_priority_group;
#endif

Where rt_thread_priority_table[RT_THREAD_PRIORITY_MAX] is an array whose size is set according to the maximum priority set, and the threads corresponding to the priority will be mounted to the corresponding location.

rt_thread_ready_priority_group and rt_thread_ready_table[32] indicates the priority of all ready threads at this time. The values of these two variables will be updated in real time when the thread enters the ready state and when the thread leaves the ready state.

  • First discuss the case when the maximum priority number is less than or equal to 32.

    rt_thread_ready_priority_group is a 32-bit variable. Each bit corresponds to a priority. For example, bit 0 corresponds to priority 0. This bit is 1, indicating that the thread with priority 0 is ready. The smaller the number, the higher the priority.

    So the question is, when there are multiple different threads ready at the same time, how to find the thread with the highest priority?

    Let's first look at how to find the lowest 1 RT thread if it is an 8-bit variable. The bitmap query method is used. This is a space for time strategy, that is, maintain the following query array:

    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
    };
    

    8bit variable means that there are 256 cases, so this is a 256 size array. The content of the array is that no matter which number you enter between 0-255, you can return the position of the lowest bit, so that we can get the highest priority result in O(1) time.

    So 32-bit is simple. Why don't we build such an array? If you want to meet the requirements, you need 2^32 * byte = 4GB of storage space. How can you carry the weak body of your MCU?

    RT thread adopts to split 32bit into four 8bit, which can save a lot of space. Let's see how RT thread is implemented?

    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;
    }
    

    In fact, it means adding a few more judgments. Although it can't be achieved in one step, it can be regarded as a better compromise method.

    The method to find the current highest priority is as follows:

    highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1;
    
  • When the priority number of threads is greater than 32 (RT thread supports 256 at most, which is absolutely enough)

    In this case, RT thread adopts the algorithm of secondary bitmap.

    Looking at the source code, we can see that RT is more defined at this time_ thread_ ready_ Table [32] this array, from the bit perspective, that is, 32*8 = 256 bit, is the maximum number of priorities.

    Actually rt_thread_ready_table[32] plays the role of identifying which priority has task ready at this time.

    And RT_ thread_ ready_ priority_ The 32-bit variable group acts as a lookup rt_thread_ready_table[32] which byte of the 32 size array has the thread in the ready state.

    At this time, the algorithm for finding the highest priority is as follows:

    register rt_ubase_t number;
    //Find the highest priority first_ thread_ ready_ Table [number] where
    number = __rt_ffs(rt_thread_ready_priority_group) - 1;
    //Combine number and rt_thread_ready_table gets the highest priority
    //Shifting 3 bits to the right is equivalent to multiplying 8
    highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1;
    

Summary: RT thread's priority search algorithm can find the highest priority thread within the time complexity of O(1), which ensures the real-time performance of thread scheduling. At the same time, it is better to use the maximum number of priorities within 32, which not only saves space, but also uses only the first level bitmap, and can run faster.

There is an article on the Internet, which is written in more detail. You can check: Bitmap scheduling algorithm analysis of RT thread (latest version)

Topics: Algorithm rt-thread