linux 用红黑树来存runqueue上的struct task_struct, 是内核中一个很重要的结构体,在runqueue中,红黑树的值为task的vruntime,最左节点即为vruntime最小的节点,在pick下一个task时就选择这个task执行.

    rbtree的实现

    1. struct rb_node {
    2. unsigned long __rb_parent_color;
    3. struct rb_node *rb_right;
    4. struct rb_node *rb_left;
    5. } __attribute__((aligned(sizeof(long))));
    6. /* The alignment might seem pointless, but allegedly CRIS needs it */

    rb_node代表红黑树的节点,3个字段,rb_right rb_left 分别代表节点的左右子节点,__rb_parent_color 比较诡异,为啥不是一个指针?红黑树的color字段存哪儿了?看下去

    #define rb_parent(r)   ((struct rb_node *)((r)->__rb_parent_color & ~3))
    

    rb_parent是一个宏,返回传入node的parent node,rb_parent_color & ~3 的意思是 mask掉 rb_parent_color 的最后2位,例如:__rb_parent_color: 1101, 1101 & ~3 = 1100

    #define    RB_RED        0
    #define    RB_BLACK    1
    
    static inline void rb_set_black(struct rb_node *rb)
    {
        rb->__rb_parent_color |= RB_BLACK;
    }
    

    rb_set_black 将node的 color设置为 RB_BLACK, 这里看出,是将color放在了rb_parent_color 最后一位上,结合 rb_parent的宏,可以判断出,rb_parent_color 的最后2位存放的是color,RED是0,即默认的color,BLACK是1,为什么可以这样做?__rb_parent_color的类型是unsigned long, 存放的是指向struct rb_node的指针,指针的长度也是 unsigned long, 两个长度是一样的,为什么会有2个多与的bit来存color?

    因为kmalloc是4/8字节对其的,就是说,指针的地址一定是4/8字节的倍数,也就是说,指正最后一定是以 100 1100 … 结尾,例如node_pointer 地址为 0xF724315C, 最后2个bit一定是 00,这样就可以用这个地址的最后2个bit来存color。可以看到linux kernel对内存是“扣”到了极点