Linux 内核基础知识

实验:GCC 编译

本实验使用交叉编译器演示一下 gcc 的编译过程。首先编写一个简单的 C 语言程序,如代码清单 1 所示,并将其命名为 test.c

代码清单 1 test.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #define PAGE_SIZE 4096
  6. #define MAX_SIZE 100*PAGE_SIZE
  7.  
  8. int main()
  9. {
  10.     char* buf = (char*)malloc(MAX_SIZE);
  11.     memset(buf, 0, MAX_SIZE);
  12.     printf("buffer address=0x%p\n", buf);
  13.     free(buf);
  14.     return 0;
  15. }

1. 预处理

gcc 的 -E 选项表示,只进行预处理阶段,不进行汇编、编译、链接的后续步骤。

  • tim@tim-vmwarevirtualplatform:~$ aarch64-linux-gnu-gcc -E test.c -o test.i

打开生成的 test.i 文件,可以看到其中添加了包含的头文件信息。

-E 可以简单记忆成 prEprocessing。

2. 汇编

gcc 的 -S 选项表示生成汇编代码。

  • tim@tim-vmwarevirtualplatform:~$ aarch64-linux-gnu-gcc -E test.i -o test.s

打开生成的 test.s 文件,可以看到生成的汇编代码。

-S 可以简单记忆成 aSsembly。

3. 编译

gcc 的 -c 选项表示编译生成二进制文件。

  • tim@tim-vmwarevirtualplatform:~$ aarch64-linux-gnu-gcc -c test.s -o test.o

-c 可以简单记忆成 compile。

4. 链接

最后一步是链接操作,将多个二进制文件(比如包含 printf 实现的二进制文件)链接到一起。此处我们使用静态链接,防止目标平台的库文件和我们交叉编译环境的库文件不一致。

  • tim@tim-vmwarevirtualplatform:~$ aarch64-linux-gnu-gcc test.o -o test --static

本地实验会提示找不到文件的链接错误,应该是链接环境有误,可以通过 --sysroot 指定。

但是我直接下载了发布好的交叉编译环境,发现直接没有问题了。

我们将最终生成的可执行文件放到 qemu 上执行。在 《Linux 系统基础知识》 中已经配置好,可以将文件放在 kmodules 目录中进行“共享”。

  • benshushu:mnt# ./test
  • buffer address=0x0xffffbb342010

实验:内核链表

本实验学习 Linux 内核中的链表机制,其相关接口函数定义在 include/linux/list.h 头文件中。此处,我们学习它的途径是将其移植到用户态中,并加以使用。

Linux 链表和我们平时使用的模板链表有些区别,它只定义链接信息,而不定义数据信息。

代码清单 2 include/linux/types.h
  1. struct list_head {
  2.     struct list_head* next, * prev;
  3. };

使用不同数据的话,需要将 list_head 封装其中。

  1. struct num {
  2.     int i;
  3.     struct list_head list;
  4. };

这涉及到一个问题,如何通过 list_head 获取到包含数据信息的结构体?如代码清单 3 所示,Linux 中采取的方法是使用当前 list_head 所在的位置,减去它在结构体中的偏移位置,就是整个结构体的首地址。我们可以通过完整的结构体访问各种想要的信息。

代码清单 3 include/linux/kernel.h
  1. #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
  2. #define container_of(ptr, type, member) ({               \
  3.     void *__mptr = (void *)(ptr);                   \
  4.     ((type *)(__mptr - offsetof(type, member))); })

最关键的思路就是 container_of() 函数。其他接口我们了解一下,当成 STL 的接口函数来进行使用就可以。这边介绍一下几个后续使用到的接口函数:

1. LIST_HEAD :定义一个初始化好了的头节点。其前指针和后指针都指向头节点自己。

2. list_add_tail(new, head) :将指定的新节点(new)添加到指定链表中(链表头节点 head)。

3. list_for_each_entry(pos, head, member) :循环遍历指定的链表(链表头节点 head)。pos 是迭代的变量,它是包含 list_head 的完整结构体变量名;member 是 list_head 在 pos 结构体中的成员名称。

4. list_for_each_entry_safe(pos, n, head, member) :和 list_for_each_entry 一样也是循环遍历指定的链表(链表头节点 head)。加了 safe 后缀,主要是用于删除节点场景,它能安全的删除当前遍历的节点,而不影响后续的遍历。实现方式就是传入的 n 这个临时指针,它会预先存储下一个节点的信息。

5. list_del(entry) :删除指定节点。

移植工作

头文件的移植主要是删除不必要的内核头文件,以及手动添加需要的定义。操作并不复杂,没移植好编译也会报错,依据报错信息进行调整修改即可。

代码清单 4 移植的 list.h
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _LINUX_LIST_H
  3. #define _LINUX_LIST_H
  4.  
  5. /*
  6.  * Simple doubly linked list implementation.
  7.  *
  8.  * Some of the internal functions ("__xxx") are useful when
  9.  * manipulating whole lists rather than single entries, as
  10.  * sometimes we already know the next/prev entries and we can
  11.  * generate better code by using them directly rather than
  12.  * using the generic single-entry routines.
  13.  */
  14.  
  15. struct list_head {
  16.     struct list_head* next, * prev;
  17. };
  18.  
  19. #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
  20. #define container_of(ptr, type, member) ({               \
  21.     void *__mptr = (void *)(ptr);                   \
  22.     ((type *)(__mptr - offsetof(type, member))); })
  23.  
  24. # define POISON_POINTER_DELTA 0
  25. #define LIST_POISON1  ((void *) 0x100 + POISON_POINTER_DELTA)
  26. #define LIST_POISON2  ((void *) 0x200 + POISON_POINTER_DELTA)
  27.  
  28. #define WRITE_ONCE(x, val) (*((volatile typeof(x) *) &(x)) = (val))
  29. #define READ_ONCE(x) (*((volatile typeof(x) *)&(x)))
  30.  
  31. #define LIST_HEAD_INIT(name) { &(name), &(name) }
  32.  
  33. #define LIST_HEAD(name) \
  34.     struct list_head name = LIST_HEAD_INIT(name)
  35.  
  36. static inline void INIT_LIST_HEAD(struct list_head* list)
  37. {
  38.     WRITE_ONCE(list->next, list);
  39.     list->prev = list;
  40. }
  41.  
  42. static inline int __list_add_valid(struct list_head* new,
  43.     struct list_head* prev,
  44.     struct list_head* next)
  45. {
  46.     return 1;
  47. }
  48. static inline int __list_del_entry_valid(struct list_head* entry)
  49. {
  50.     return 1;
  51. }
  52.  
  53. /*
  54.  * Insert a new entry between two known consecutive entries.
  55.  *
  56.  * This is only for internal list manipulation where we know
  57.  * the prev/next entries already!
  58.  */
  59. static inline void __list_add(struct list_head* new,
  60.     struct list_head* prev,
  61.     struct list_head* next)
  62. {
  63.     if (!__list_add_valid(new, prev, next))
  64.          return;
  65.  
  66.     next->prev = new;
  67.     new->next = next;
  68.     new->prev = prev;
  69.     WRITE_ONCE(prev->next, new);
  70. }
  71.  
  72. /**
  73.  * list_add - add a new entry
  74.  * @new: new entry to be added
  75.  * @head: list head to add it after
  76.  *
  77.  * Insert a new entry after the specified head.
  78.  * This is good for implementing stacks.
  79.  */
  80. static inline void list_add(struct list_head* new, struct list_head* head)
  81. {
  82.     __list_add(new, head, head->next);
  83. }
  84.  
  85.  
  86. /**
  87.  * list_add_tail - add a new entry
  88.  * @new: new entry to be added
  89.  * @head: list head to add it before
  90.  *
  91.  * Insert a new entry before the specified head.
  92.  * This is useful for implementing queues.
  93.  */
  94. static inline void list_add_tail(struct list_head* new, struct list_head* head)
  95. {
  96.     __list_add(new, head->prev, head);
  97. }
  98.  
  99. /*
  100.  * Delete a list entry by making the prev/next entries
  101. * point to each other.
  102.  *
  103.  * This is only for internal list manipulation where we know
  104.  * the prev/next entries already!
  105.  */
  106. static inline void __list_del(struct list_head* prev, struct list_head* next)
  107. {
  108.     next->prev = prev;
  109.     WRITE_ONCE(prev->next, next);
  110. }
  111.  
  112. /**
  113.  * list_del - deletes entry from list.
  114.  * @entry: the element to delete from the list.
  115.  * Note: list_empty() on entry does not return true after this, the entry is
  116.  * in an undefined state.
  117.  */
  118. static inline void __list_del_entry(struct list_head* entry)
  119. {
  120.     if (!__list_del_entry_valid(entry))
  121.          return;
  122.  
  123.     __list_del(entry->prev, entry->next);
  124. }
  125.  
  126. static inline void list_del(struct list_head* entry)
  127. {
  128.     __list_del_entry(entry);
  129.     entry->next = LIST_POISON1;
  130.     entry->prev = LIST_POISON2;
  131. }
  132.  
  133. /**
  134.  * list_replace - replace old entry by new one
  135.  * @old : the element to be replaced
  136.  * @new : the new element to insert
  137.  *
  138.  * If @old was empty, it will be overwritten.
  139.  */
  140. static inline void list_replace(struct list_head* old,
  141.     struct list_head* new)
  142. {
  143.     new->next = old->next;
  144.     new->next->prev = new;
  145.     new->prev = old->prev;
  146.     new->prev->next = new;
  147. }
  148.  
  149. static inline void list_replace_init(struct list_head* old,
  150.     struct list_head* new)
  151. {
  152.     list_replace(old, new);
  153.     INIT_LIST_HEAD(old);
  154. }
  155.  
  156. /**
  157.  * list_del_init - deletes entry from list and reinitialize it.
  158.  * @entry: the element to delete from the list.
  159.  */
  160. static inline void list_del_init(struct list_head* entry)
  161. {
  162.     __list_del_entry(entry);
  163.     INIT_LIST_HEAD(entry);
  164. }
  165.  
  166. /**
  167.  * list_move - delete from one list and add as another's head
  168.  * @list: the entry to move
  169.  * @head: the head that will precede our entry
  170.  */
  171. static inline void list_move(struct list_head* list, struct list_head* head)
  172. {
  173.     __list_del_entry(list);
  174.     list_add(list, head);
  175. }
  176.  
  177. /**
  178.  * list_move_tail - delete from one list and add as another's tail
  179.  * @list: the entry to move
  180.  * @head: the head that will follow our entry
  181.  */
  182. static inline void list_move_tail(struct list_head* list,
  183.     struct list_head* head)
  184. {
  185.     __list_del_entry(list);
  186.     list_add_tail(list, head);
  187. }
  188.  
  189. /**
  190.  * list_bulk_move_tail - move a subsection of a list to its tail
  191.  * @head: the head that will follow our entry
  192.  * @first: first entry to move
  193.  * @last: last entry to move, can be the same as first
  194.  *
  195.  * Move all entries between @first and including @last before @head.
  196.  * All three entries must belong to the same linked list.
  197.  */
  198. static inline void list_bulk_move_tail(struct list_head* head,
  199.     struct list_head* first,
  200.     struct list_head* last)
  201. {
  202.     first->prev->next = last->next;
  203.     last->next->prev = first->prev;
  204.  
  205.     head->prev->next = first;
  206.     first->prev = head->prev;
  207.  
  208.     last->next = head;
  209.     head->prev = last;
  210. }
  211.  
  212. /**
  213.  * list_is_last - tests whether @list is the last entry in list @head
  214.  * @list: the entry to test
  215.  * @head: the head of the list
  216.  */
  217. static inline int list_is_last(const struct list_head* list,
  218.     const struct list_head* head)
  219. {
  220.     return list->next == head;
  221. }
  222.  
  223. /**
  224.  * list_empty - tests whether a list is empty
  225.  * @head: the list to test.
  226.  */
  227. static inline int list_empty(const struct list_head* head)
  228. {
  229.     return READ_ONCE(head->next) == head;
  230. }
  231.  
  232. /**
  233.  * list_empty_careful - tests whether a list is empty and not being modified
  234.  * @head: the list to test
  235.  *
  236.  * Description:
  237.  * tests whether a list is empty _and_ checks that no other CPU might be
  238.  * in the process of modifying either member (next or prev)
  239.  *
  240.  * NOTE: using list_empty_careful() without synchronization
  241.  * can only be safe if the only activity that can happen
  242.  * to the list entry is list_del_init(). Eg. it cannot be used
  243.  * if another CPU could re-list_add() it.
  244.  */
  245. static inline int list_empty_careful(const struct list_head* head)
  246. {
  247.     struct list_head* next = head->next;
  248.     return (next == head) && (next == head->prev);
  249. }
  250.  
  251. /**
  252.  * list_rotate_left - rotate the list to the left
  253.  * @head: the head of the list
  254.  */
  255. static inline void list_rotate_left(struct list_head* head)
  256. {
  257.     struct list_head* first;
  258.  
  259.     if (!list_empty(head)) {
  260.          first = head->next;
  261.          list_move_tail(first, head);
  262.     }
  263. }
  264.  
  265. /**
  266.  * list_is_singular - tests whether a list has just one entry.
  267.  * @head: the list to test.
  268.  */
  269. static inline int list_is_singular(const struct list_head* head)
  270. {
  271.     return !list_empty(head) && (head->next == head->prev);
  272. }
  273.  
  274. static inline void __list_cut_position(struct list_head* list,
  275.     struct list_head* head, struct list_head* entry)
  276. {
  277.     struct list_head* new_first = entry->next;
  278.     list->next = head->next;
  279.     list->next->prev = list;
  280.     list->prev = entry;
  281.     entry->next = list;
  282.     head->next = new_first;
  283.     new_first->prev = head;
  284. }
  285.  
  286. /**
  287.  * list_cut_position - cut a list into two
  288.  * @list: a new list to add all removed entries
  289.  * @head: a list with entries
  290.  * @entry: an entry within head, could be the head itself
  291.  *  and if so we won't cut the list
  292.  *
  293.  * This helper moves the initial part of @head, up to and
  294.  * including @entry, from @head to @list. You should
  295.  * pass on @entry an element you know is on @head. @list
  296.  * should be an empty list or a list you do not care about
  297.  * losing its data.
  298.  *
  299.  */
  300. static inline void list_cut_position(struct list_head* list,
  301.     struct list_head* head, struct list_head* entry)
  302. {
  303.     if (list_empty(head))
  304.          return;
  305.     if (list_is_singular(head) &&
  306.          (head->next != entry && head != entry))
  307.          return;
  308.     if (entry == head)
  309.          INIT_LIST_HEAD(list);
  310.     else
  311.          __list_cut_position(list, head, entry);
  312. }
  313.  
  314. /**
  315.  * list_cut_before - cut a list into two, before given entry
  316.  * @list: a new list to add all removed entries
  317.  * @head: a list with entries
  318.  * @entry: an entry within head, could be the head itself
  319.  *
  320.  * This helper moves the initial part of @head, up to but
  321.  * excluding @entry, from @head to @list.  You should pass
  322.  * in @entry an element you know is on @head.  @list should
  323.  * be an empty list or a list you do not care about losing
  324.  * its data.
  325.  * If @entry == @head, all entries on @head are moved to
  326.  * @list.
  327.  */
  328. static inline void list_cut_before(struct list_head* list,
  329.     struct list_head* head,
  330.     struct list_head* entry)
  331. {
  332.     if (head->next == entry) {
  333.          INIT_LIST_HEAD(list);
  334.          return;
  335.     }
  336.     list->next = head->next;
  337.     list->next->prev = list;
  338.     list->prev = entry->prev;
  339.     list->prev->next = list;
  340.     head->next = entry;
  341.     entry->prev = head;
  342. }
  343.  
  344. static inline void __list_splice(const struct list_head* list,
  345.     struct list_head* prev,
  346.     struct list_head* next)
  347. {
  348.     struct list_head* first = list->next;
  349.     struct list_head* last = list->prev;
  350.  
  351.     first->prev = prev;
  352.     prev->next = first;
  353.  
  354.     last->next = next;
  355.     next->prev = last;
  356. }
  357.  
  358. /**
  359.  * list_splice - join two lists, this is designed for stacks
  360.  * @list: the new list to add.
  361.  * @head: the place to add it in the first list.
  362.  */
  363. static inline void list_splice(const struct list_head* list,
  364.     struct list_head* head)
  365. {
  366.     if (!list_empty(list))
  367.          __list_splice(list, head, head->next);
  368. }
  369.  
  370. /**
  371.  * list_splice_tail - join two lists, each list being a queue
  372.  * @list: the new list to add.
  373.  * @head: the place to add it in the first list.
  374.  */
  375. static inline void list_splice_tail(struct list_head* list,
  376.     struct list_head* head)
  377. {
  378.     if (!list_empty(list))
  379.          __list_splice(list, head->prev, head);
  380. }
  381.  
  382. /**
  383.  * list_splice_init - join two lists and reinitialise the emptied list.
  384.  * @list: the new list to add.
  385.  * @head: the place to add it in the first list.
  386.  *
  387.  * The list at @list is reinitialised
  388.  */
  389. static inline void list_splice_init(struct list_head* list,
  390.     struct list_head* head)
  391. {
  392.     if (!list_empty(list)) {
  393.          __list_splice(list, head, head->next);
  394.          INIT_LIST_HEAD(list);
  395.     }
  396. }
  397.  
  398. /**
  399.  * list_splice_tail_init - join two lists and reinitialise the emptied list
  400.  * @list: the new list to add.
  401. * @head: the place to add it in the first list.
  402.  *
  403.  * Each of the lists is a queue.
  404.  * The list at @list is reinitialised
  405.  */
  406. static inline void list_splice_tail_init(struct list_head* list,
  407.     struct list_head* head)
  408. {
  409.     if (!list_empty(list)) {
  410.          __list_splice(list, head->prev, head);
  411.          INIT_LIST_HEAD(list);
  412.     }
  413. }
  414.  
  415. /**
  416.  * list_entry - get the struct for this entry
  417.  * @ptr: the &struct list_head pointer.
  418.  * @type:    the type of the struct this is embedded in.
  419.  * @member:  the name of the list_head within the struct.
  420.  */
  421. #define list_entry(ptr, type, member) \
  422.     container_of(ptr, type, member)
  423.  
  424.  /**
  425.   * list_first_entry - get the first element from a list
  426.   * @ptr:    the list head to take the element from.
  427.   * @type:   the type of the struct this is embedded in.
  428.   * @member: the name of the list_head within the struct.
  429.   *
  430.   * Note, that list is expected to be not empty.
  431.   */
  432. #define list_first_entry(ptr, type, member) \
  433.     list_entry((ptr)->next, type, member)
  434.  
  435.   /**
  436.    * list_last_entry - get the last element from a list
  437.    * @ptr:   the list head to take the element from.
  438.    * @type:  the type of the struct this is embedded in.
  439.    * @member: the name of the list_head within the struct.
  440.    *
  441.    * Note, that list is expected to be not empty.
  442.    */
  443. #define list_last_entry(ptr, type, member) \
  444.     list_entry((ptr)->prev, type, member)
  445.  
  446.    /**
  447.     * list_first_entry_or_null - get the first element from a list
  448.     * @ptr:  the list head to take the element from.
  449.     * @type: the type of the struct this is embedded in.
  450.     * @member:   the name of the list_head within the struct.
  451.     *
  452.     * Note that if the list is empty, it returns NULL.
  453.     */
  454. #define list_first_entry_or_null(ptr, type, member) ({ \
  455.     struct list_head *head__ = (ptr); \
  456.     struct list_head *pos__ = READ_ONCE(head__->next); \
  457.     pos__ != head__ ? list_entry(pos__, type, member) : NULL; \
  458. })
  459.  
  460.     /**
  461.      * list_next_entry - get the next element in list
  462.      * @pos: the type * to cursor
  463.      * @member:  the name of the list_head within the struct.
  464.      */
  465. #define list_next_entry(pos, member) \
  466.     list_entry((pos)->member.next, typeof(*(pos)), member)
  467.  
  468.      /**
  469.       * list_prev_entry - get the prev element in list
  470.       * @pos:    the type * to cursor
  471.       * @member: the name of the list_head within the struct.
  472.       */
  473. #define list_prev_entry(pos, member) \
  474.     list_entry((pos)->member.prev, typeof(*(pos)), member)
  475.  
  476.       /**
  477.        * list_for_each    -   iterate over a list
  478.        * @pos:   the &struct list_head to use as a loop cursor.
  479.        * @head:  the head for your list.
  480.        */
  481. #define list_for_each(pos, head) \
  482.     for (pos = (head)->next; pos != (head); pos = pos->next)
  483.  
  484.        /**
  485.          * list_for_each_prev  -   iterate over a list backwards
  486.          * @pos:  the &struct list_head to use as a loop cursor.
  487.          * @head: the head for your list.
  488.          */
  489. #define list_for_each_prev(pos, head) \
  490.     for (pos = (head)->prev; pos != (head); pos = pos->prev)
  491.  
  492.          /**
  493.           * list_for_each_safe - iterate over a list safe against removal of list entry
  494.           * @pos: the &struct list_head to use as a loop cursor.
  495.           * @n:       another &struct list_head to use as temporary storage
  496.           * @head:    the head for your list.
  497.           */
  498. #define list_for_each_safe(pos, n, head) \
  499.     for (pos = (head)->next, n = pos->next; pos != (head); \
  500.          pos = n, n = pos->next)
  501.  
  502.           /**
  503.            * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
  504.            * @pos:    the &struct list_head to use as a loop cursor.
  505.            * @n:      another &struct list_head to use as temporary storage
  506.            * @head:   the head for your list.
  507.            */
  508. #define list_for_each_prev_safe(pos, n, head) \
  509.     for (pos = (head)->prev, n = pos->prev; \
  510.          pos != (head); \
  511.          pos = n, n = pos->prev)
  512.  
  513.            /**
  514.             * list_for_each_entry  -   iterate over list of given type
  515.             * @pos:   the type * to use as a loop cursor.
  516.             * @head:  the head for your list.
  517.             * @member: the name of the list_head within the struct.
  518.             */
  519. #define list_for_each_entry(pos, head, member)                \
  520.     for (pos = list_first_entry(head, typeof(*pos), member); \
  521.          &pos->member != (head);                    \
  522.          pos = list_next_entry(pos, member))
  523.  
  524.             /**
  525.              * list_for_each_entry_reverse - iterate backwards over list of given type.
  526.              * @pos:  the type * to use as a loop cursor.
  527.              * @head: the head for your list.
  528.              * @member:   the name of the list_head within the struct.
  529.              */
  530. #define list_for_each_entry_reverse(pos, head, member)            \
  531.     for (pos = list_last_entry(head, typeof(*pos), member);       \
  532.          &pos->member != (head);                    \
  533.          pos = list_prev_entry(pos, member))
  534.  
  535.              /**
  536.               * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
  537.               * @pos: the type * to use as a start point
  538.               * @head:    the head of the list
  539.               * @member:  the name of the list_head within the struct.
  540.               *
  541.               * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
  542.               */
  543. #define list_prepare_entry(pos, head, member) \
  544.     ((pos) ? : list_entry(head, typeof(*pos), member))
  545.  
  546.               /**
  547.                * list_for_each_entry_continue - continue iteration over list of given type
  548.                * @pos:    the type * to use as a loop cursor.
  549.                * @head:   the head for your list.
  550.                * @member: the name of the list_head within the struct.
  551.                *
  552.                * Continue to iterate over list of given type, continuing after
  553.                * the current position.
  554.                */
  555. #define list_for_each_entry_continue(pos, head, member)       \
  556.     for (pos = list_next_entry(pos, member);             \
  557.          &pos->member != (head);                    \
  558.          pos = list_next_entry(pos, member))
  559.  
  560.                /**
  561.                 * list_for_each_entry_continue_reverse - iterate backwards from the given point
  562.                 * @pos:   the type * to use as a loop cursor.
  563.                 * @head:  the head for your list.
  564.                 * @member: the name of the list_head within the struct.
  565.                 *
  566.                 * Start to iterate over list of given type backwards, continuing after
  567.                 * the current position.
  568.                 */
  569. #define list_for_each_entry_continue_reverse(pos, head, member)        \
  570.     for (pos = list_prev_entry(pos, member);             \
  571.          &pos->member != (head);                    \
  572.          pos = list_prev_entry(pos, member))
  573.  
  574.                 /**
  575.                   * list_for_each_entry_from - iterate over list of given type from the current point
  576.                   * @pos:  the type * to use as a loop cursor.
  577.                   * @head: the head for your list.
  578.                   * @member:   the name of the list_head within the struct.
  579.                   *
  580.                   * Iterate over list of given type, continuing from current position.
  581.                   */
  582. #define list_for_each_entry_from(pos, head, member)           \
  583.     for (; &pos->member != (head);                  \
  584.          pos = list_next_entry(pos, member))
  585.  
  586.                   /**
  587.                    * list_for_each_entry_from_reverse - iterate backwards over list of given type
  588.                    *                                    from the current point
  589.                    * @pos: the type * to use as a loop cursor.
  590.                    * @head:    the head for your list.
  591.                    * @member:  the name of the list_head within the struct.
  592.                    *
  593.                    * Iterate backwards over list of given type, continuing from current position.
  594.                   */
  595. #define list_for_each_entry_from_reverse(pos, head, member)       \
  596.     for (; &pos->member != (head);                  \
  597.          pos = list_prev_entry(pos, member))
  598.  
  599.                    /**
  600.                     * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
  601.                     * @pos:    the type * to use as a loop cursor.
  602.                     * @n:      another type * to use as temporary storage
  603.                     * @head:   the head for your list.
  604.                     * @member: the name of the list_head within the struct.
  605.                     */
  606. #define list_for_each_entry_safe(pos, n, head, member)            \
  607.     for (pos = list_first_entry(head, typeof(*pos), member), \
  608.          n = list_next_entry(pos, member);           \
  609.          &pos->member != (head);                    \
  610.          pos = n, n = list_next_entry(n, member))
  611.  
  612.                     /**
  613.                      * list_for_each_entry_safe_continue - continue list iteration safe against removal
  614.                      * @pos:   the type * to use as a loop cursor.
  615.                      * @n:     another type * to use as temporary storage
  616.                      * @head:  the head for your list.
  617.                      * @member: the name of the list_head within the struct.
  618.                      *
  619.                      * Iterate over list of given type, continuing after current point,
  620.                      * safe against removal of list entry.
  621.                      */
  622. #define list_for_each_entry_safe_continue(pos, n, head, member)        \
  623.     for (pos = list_next_entry(pos, member),                 \
  624.          n = list_next_entry(pos, member);               \
  625.          &pos->member != (head);                         \
  626.          pos = n, n = list_next_entry(n, member))
  627.  
  628.                      /**
  629.                       * list_for_each_entry_safe_from - iterate over list from current point safe against removal
  630.                       * @pos:  the type * to use as a loop cursor.
  631.                       * @n:        another type * to use as temporary storage
  632.                       * @head: the head for your list.
  633.                       * @member:   the name of the list_head within the struct.
  634.                       *
  635.                       * Iterate over list of given type from current point, safe against
  636.                       * removal of list entry.
  637.                       */
  638. #define list_for_each_entry_safe_from(pos, n, head, member)            \
  639.     for (n = list_next_entry(pos, member);                   \
  640.          &pos->member != (head);                         \
  641.          pos = n, n = list_next_entry(n, member))
  642.  
  643.                       /**
  644.                        * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
  645.                        * @pos: the type * to use as a loop cursor.
  646.                        * @n:       another type * to use as temporary storage
  647.                        * @head:    the head for your list.
  648.                        * @member:  the name of the list_head within the struct.
  649.                        *
  650.                        * Iterate backwards over list of given type, safe against removal
  651.                        * of list entry.
  652.                        */
  653. #define list_for_each_entry_safe_reverse(pos, n, head, member)         \
  654.     for (pos = list_last_entry(head, typeof(*pos), member),       \
  655.          n = list_prev_entry(pos, member);           \
  656.          &pos->member != (head);                    \
  657.          pos = n, n = list_prev_entry(n, member))
  658.  
  659.                        /**
  660.                         * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
  661.                         * @pos:    the loop cursor used in the list_for_each_entry_safe loop
  662.                         * @n:      temporary storage used in list_for_each_entry_safe
  663.                         * @member: the name of the list_head within the struct.
  664.                         *
  665.                         * list_safe_reset_next is not safe to use in general if the list may be
  666.                         * modified concurrently (eg. the lock is dropped in the loop body). An
  667.                         * exception to this is if the cursor element (pos) is pinned in the list,
  668.                         * and list_safe_reset_next is called after re-taking the lock and before
  669.                         * completing the current iteration of the loop body.
  670.                         */
  671. #define list_safe_reset_next(pos, n, member)             \
  672.     n = list_next_entry(pos, member)
  673.  
  674.                         /*
  675.                          * Double linked lists with a single pointer list head.
  676.                          * Mostly useful for hash tables where the two pointer list head is
  677.                          * too wasteful.
  678.                          * You lose the ability to access the tail in O(1).
  679.                          */
  680.  
  681. #endif

验证

移植好头文件之后,我们就可以写样例进行测试了。

如代码清单 5 所示,我们先初始化链表 test_list;然后往其中依次添加 100 个元素(list_add_tail);接着进行遍历打印(list_for_each_entry);最后释放链表分配的内存(list_for_each_entry_safe、list_del)。

代码清单 5 list 样例
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. #include "list.h"
  5.  
  6. struct num {
  7.     int i;
  8.     struct list_head list;
  9. };
  10.  
  11. int main()
  12. {
  13.     LIST_HEAD(test_list);
  14.     int i;
  15.     struct num* num;
  16.     struct num* num1;
  17.  
  18.     /* Add */
  19.     printf("add 100 element into list\n");
  20.     for (i = 0; i < 100; i++)
  21.     {
  22.          num = (struct num*)malloc(sizeof(struct num));
  23.          num->i = i;
  24.          list_add_tail(&num->list, &test_list);
  25.     }
  26.  
  27.     i = 0;
  28.     /* print list */
  29.     printf("print the list\n");
  30.     list_for_each_entry(num, &test_list, list)
  31.     {
  32.          printf("%2d ", num->i);
  33.          if ((i + 1) % 10 == 0)
  34.              printf("\n");
  35.          i++;
  36.     }
  37.     printf("\n");
  38.  
  39.     /* Delete */
  40.     list_for_each_entry_safe(num, num1, &test_list, list)
  41.     {
  42.          list_del(&num->list);
  43.          free(num);
  44.     }
  45.  
  46.     if (list_empty(&test_list))
  47.          printf("Free test_list successfully\n");
  48.  
  49.     return 0;
  50. }

机制中会利用到 typeof。这是 GNU C 扩展特有的,所以虽然是移植到用户态,VS编译器还是不能使用。

在 linux 上编译验证。

  • tim@tim-vmwarevirtualplatform:~$ gcc list.c -o list
  • tim@tim-vmwarevirtualplatform:~$ ./list
  • add 100 element into list
  • print the list
  •  0  1  2  3  4  5  6  7  8  9
  • 10 11 12 13 14 15 16 17 18 19
  • 20 21 22 23 24 25 26 27 28 29
  • 30 31 32 33 34 35 36 37 38 39
  • 40 41 42 43 44 45 46 47 48 49
  • 50 51 52 53 54 55 56 57 58 59
  • 60 61 62 63 64 65 66 67 68 69
  • 70 71 72 73 74 75 76 77 78 79
  • 80 81 82 83 84 85 86 87 88 89
  • 90 91 92 93 94 95 96 97 98 99
  •  
  • Free test_list successfully

实验:红黑树

本实验介绍 Linux 内核中的红黑树。红黑树的具体实现和概念就不介绍了,可以参考《算法导论》,这边介绍一下内核中定义的接口。相关接口函数在 include/linux/rbtree.h 头文件中定义。

1. rb_node :红黑树节点的定义,包含左、右子节点指针,以及父节点的颜色。

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

__rb_parent_color 即存储父节点的颜色,也存储父节点的指针。

低两位是存储颜色信息的。可以这么做的原因是 aligned(sizeof(long)) 对齐的缘故。

2. RB_ROOT :定义红黑树的根节点。其实就是一个指向指向 NULL 的 rb_node。

3. rb_link_noderb_insert_color :插入的基本操作组合,和《算法导论》里的操作是一样的。rb_link_node 先将新节点插入到红黑树指定的位置,不涉及平衡调整。rb_insert_color 进行平衡调整。

4. rb_erase :删除一个节点,并进行平衡调整。

5. rb_entry :根据节点指针获取节点所属的结构体指针。这在上一节链表中已经了解过,是通过 container_of 实现的。

6. rb_firstrb_next :rb_first 返回红黑树中的第一个节点。rb_next 返回指定节点的下一个节点。红黑树的遍历可以通过先获取 rb_first,在通过 rb_next 迭代实现。

这边可以学习一下 rb_next 的源码思路,因为之前写的二叉树遍历都是递归实现的。

首先 Linux 内核红黑树的大小存储顺序也是先序遍历的:先左子树、再根节点、再右子树。能迭代获取是因为存储了父节点信息。

获取一个节点的下一个节点:首先下一个节点肯定在右子树中,而且是右子树中最小的,即最左边的节点。如果没有右子树,从递归的流程上看,此时要进行递归回升了。如何判断是回升的哪个阶段:首先获取当前节点的父节点,如果当前节点是父节点的左孩子,那么下一个节点就是父节点(因为顺序是 左子树->根);如果当前节点是父节点的右孩子,代表本轮 左子树->根->右子树 的遍历已经完成,还需要继续递归回升,即继续查看父节点的父节点。以此类推。

内核中使用红黑树

我们先学习在内核环境使用红黑树。如代码清单 1 所示,在模块加载时我们往红黑树中插入节点,并打印遍历;模块卸载时,删除红黑树中的各个节点,并释放相关内存。

代码清单 6 内核中使用红黑树
  1. #include <linux/init.h>
  2. #include <linux/list.h>
  3. #include <linux/module.h>
  4. #include <linux/kernel.h>
  5. #include <linux/slab.h>
  6. #include <linux/mm.h>
  7. #include <linux/rbtree.h>
  8.  
  9. MODULE_AUTHOR("Tim");
  10. MODULE_DESCRIPTION(" ");
  11. MODULE_LICENSE("GPL");
  12.  
  13. struct mytype
  14. {
  15.     struct rb_node node;
  16.     int key;
  17. };
  18.  
  19. struct rb_root mytree = RB_ROOT;
  20.  
  21. struct mytype* my_search(struct rb_root* root, int new)
  22. {
  23.     struct rb_node* node = root->rb_node;
  24.  
  25.     while (node)
  26.     {
  27.         struct mytype* data = container_of(node, struct mytype, node);
  28.  
  29.         if (data->key > new)
  30.             node = node->rb_left;
  31.         else if (data->key < new)
  32.             node = node->rb_right;
  33.         else
  34.             return data;
  35.     }
  36.  
  37.     return NULL;
  38. }
  39.  
  40. int my_insert(struct rb_root* root, struct mytype* data)
  41. {
  42.     struct rb_node** new = &(root->rb_node), * parent = NULL;
  43.  
  44.     /* Figure out where to put new node */
  45.     while (*new)
  46.     {
  47.         struct mytype* this = container_of(*new, struct mytype, node);
  48.  
  49.         parent = *new;
  50.         if (this->key > data->key)
  51.             new = &((*new)->rb_left);
  52.         else if (this->key < data->key)
  53.             new = &((*new)->rb_right);
  54.         else
  55.             return -1;
  56.     }
  57.  
  58.     /* Add new node and rebalance tree */
  59.     rb_link_node(&data->node, parent, new);
  60.     rb_insert_color(&data->node, root);
  61.  
  62.     return 0;
  63. }
  64.  
  65. static int __init my_init(void)
  66. {
  67.     int i;
  68.     struct mytype* data;
  69.     struct rb_node* node;
  70.  
  71.     for (i = 0; i < 20; i += 2)
  72.     {
  73.         data = kmalloc(sizeof(struct mytype), GFP_KERNEL);
  74.         data->key = i;
  75.         my_insert(&mytree, data);
  76.     }
  77.  
  78.     /* list all tree */
  79.     for (node = rb_first(&mytree); node; node = rb_next(node))
  80.         printk("key=%d\n", rb_entry(node, struct mytype, node)->key);
  81.  
  82.     return 0;
  83. }
  84.  
  85. static void __exit my_exit(void)
  86. {
  87.     struct mytype* data;
  88.     struct rb_node* node;
  89.     for (node = rb_first(&mytree); node; )
  90.     {
  91.         data = rb_entry(node, struct mytype, node);
  92.         node = rb_next(node);
  93.         if (data)
  94.         {
  95.             rb_erase(&data->node, &mytree);
  96.             printk("erase key=%d\n", data->key);
  97.             kfree(data);
  98.         }
  99.     }
  100. }
  101.  
  102. module_init(my_init);
  103. module_exit(my_exit);

代码清单 2 时配套的 Makefile,编译后可以得到后缀为 ko 的内核模块文件。

代码清单 7 Makefile
  1. BASEINCLUDE ?= /lib/modules/`uname -r`/build
  2.  
  3. obj-m   :=   kernel_rbtree.o
  4. all :
  5.     $(MAKE) -C $(BASEINCLUDE) M=$(PWD) modules;
  6.  
  7. clean:
  8.     $(MAKE) -C $(BASEINCLUDE) M=$(PWD) clean;
  9.     rm -f *.ko;

我们依次执行加载模块(insmod 命令)和卸载模块(rmmod 命令),观察打印的日志。

  • benshushu:mnt# insmod kernel_rbtree.ko
  • [  397.092774] kernel_rbtree: loading out-of-tree module taints kernel.
  • [  397.218984] key=0
  • [  397.220627] key=2
  • [  397.220743] key=4
  • [  397.220825] key=6
  • [  397.220916] key=8
  • [  397.221032] key=10
  • [  397.221143] key=12
  • [  397.222381] key=14
  • [  397.231708] key=16
  • [  397.231900] key=18
  • benshushu:mnt# rmmod kernel_rbtree
  • [  412.039057] erase key=0
  • [  412.055859] erase key=2
  • [  412.056499] erase key=4
  • [  412.057642] erase key=6
  • [  412.075173] erase key=8
  • [  412.075880] erase key=10
  • [  412.076525] erase key=12
  • [  412.077179] erase key=14
  • [  412.077854] erase key=16
  • [  412.086132] erase key=18

移植红黑树

接着我们跟链表一样,将内核的红黑树代码移植到内核态使用。移植的操作和链表移植的操作是一样的。

代码清单 8 移植的 rbtree.h
  1. /*
  2.   Red Black Trees
  3.   (C) 1999  Andrea Arcangeli <andrea@suse.de>
  4.  
  5.   This program is free software; you can redistribute it and/or modify
  6.   it under the terms of the GNU General Public License as published by
  7.   the Free Software Foundation; either version 2 of the License, or
  8.   (at your option) any later version.
  9.  
  10.   This program is distributed in the hope that it will be useful,
  11.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.   GNU General Public License for more details.
  14.  
  15.   You should have received a copy of the GNU General Public License
  16.   along with this program; if not, write to the Free Software
  17.   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19.   linux/include/linux/rbtree.h
  20.  
  21.   To use rbtrees you'll have to implement your own insert and search cores.
  22.   This will avoid us to use callbacks and to drop drammatically performances.
  23.   I know it's not the cleaner way,  but in C (not in C++) to get
  24.   performances and genericity...
  25.  
  26.   See Documentation/rbtree.txt for documentation and samples.
  27. */
  28.  
  29. #ifndef _LINUX_RBTREE_H
  30. #define _LINUX_RBTREE_H
  31.  
  32. #define NULL ((void *)0)
  33. #define bool int
  34. #define true 1
  35. #define false 0
  36. #define rcu_assign_pointer(p, v) (p) = (v)
  37. #define WRITE_ONCE(x, val) (*((volatile typeof(x) *) &(x)) = (val))
  38. #define unlikely(x)     __builtin_expect(!!(x), 0)
  39. #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
  40. #define container_of(ptr, type, member) ({              \
  41.     void *__mptr = (void *)(ptr);                 \
  42.     ((type *)(__mptr - offsetof(type, member))); })
  43.  
  44. struct rb_node {
  45.     unsigned long  __rb_parent_color;
  46.     struct rb_node* rb_right;
  47.     struct rb_node* rb_left;
  48. } __attribute__((aligned(sizeof(long))));
  49. /* The alignment might seem pointless, but allegedly CRIS needs it */
  50.  
  51. struct rb_root {
  52.     struct rb_node* rb_node;
  53. };
  54.  
  55. /*
  56.  * Leftmost-cached rbtrees.
  57.  *
  58.  * We do not cache the rightmost node based on footprint
  59.  * size vs number of potential users that could benefit
  60.  * from O(1) rb_last(). Just not worth it, users that want
  61.  * this feature can always implement the logic explicitly.
  62.  * Furthermore, users that want to cache both pointers may
  63.  * find it a bit asymmetric, but that's ok.
  64.  */
  65. struct rb_root_cached {
  66.     struct rb_root rb_root;
  67.     struct rb_node* rb_leftmost;
  68. };
  69.  
  70. #define rb_parent(r)   ((struct rb_node *)((r)->__rb_parent_color & ~3))
  71.  
  72. #define RB_ROOT  (struct rb_root) { NULL, }
  73. #define RB_ROOT_CACHED (struct rb_root_cached) { {NULL, }, NULL }
  74. #define rb_entry(ptr, type, member) container_of(ptr, type, member)
  75.  
  76. #define RB_EMPTY_ROOT(root)  (READ_ONCE((root)->rb_node) == NULL)
  77.  
  78. /* 'empty' nodes are nodes that are known not to be inserted in an rbtree */
  79. #define RB_EMPTY_NODE(node)  \
  80.     ((node)->__rb_parent_color == (unsigned long)(node))
  81. #define RB_CLEAR_NODE(node)  \
  82.     ((node)->__rb_parent_color = (unsigned long)(node))
  83.  
  84.  
  85. extern void rb_insert_color(struct rb_node*, struct rb_root*);
  86. extern void rb_erase(struct rb_node*, struct rb_root*);
  87.  
  88.  
  89. /* Find logical next and previous nodes in a tree */
  90. extern struct rb_node* rb_next(const struct rb_node*);
  91. extern struct rb_node* rb_prev(const struct rb_node*);
  92. extern struct rb_node* rb_first(const struct rb_root*);
  93. extern struct rb_node* rb_last(const struct rb_root*);
  94.  
  95. extern void rb_insert_color_cached(struct rb_node*,
  96.     struct rb_root_cached*, bool);
  97. extern void rb_erase_cached(struct rb_node* node, struct rb_root_cached*);
  98. /* Same as rb_first(), but O(1) */
  99. #define rb_first_cached(root) (root)->rb_leftmost
  100.  
  101. /* Postorder iteration - always visit the parent after its children */
  102. extern struct rb_node* rb_first_postorder(const struct rb_root*);
  103. extern struct rb_node* rb_next_postorder(const struct rb_node*);
  104.  
  105. /* Fast replacement of a single node without remove/rebalance/add/rebalance */
  106. extern void rb_replace_node(struct rb_node* victim, struct rb_node* new,
  107.     struct rb_root* root);
  108. extern void rb_replace_node_rcu(struct rb_node* victim, struct rb_node* new,
  109.     struct rb_root* root);
  110. extern void rb_replace_node_cached(struct rb_node* victim, struct rb_node* new,
  111.     struct rb_root_cached* root);
  112.  
  113. static inline void rb_link_node(struct rb_node* node, struct rb_node* parent,
  114.     struct rb_node** rb_link)
  115. {
  116.     node->__rb_parent_color = (unsigned long)parent;
  117.     node->rb_left = node->rb_right = NULL;
  118.  
  119.     *rb_link = node;
  120. }
  121.  
  122. static inline void rb_link_node_rcu(struct rb_node* node, struct rb_node* parent,
  123.     struct rb_node** rb_link)
  124. {
  125.     node->__rb_parent_color = (unsigned long)parent;
  126.     node->rb_left = node->rb_right = NULL;
  127.  
  128.     rcu_assign_pointer(*rb_link, node);
  129. }
  130.  
  131. #define rb_entry_safe(ptr, type, member) \
  132.     ({ typeof(ptr) ____ptr = (ptr); \
  133.        ____ptr ? rb_entry(____ptr, type, member) : NULL; \
  134.     })
  135.  
  136. /**
  137.  * rbtree_postorder_for_each_entry_safe - iterate in post-order over rb_root of
  138.  * given type allowing the backing memory of @pos to be invalidated
  139.  *
  140.  * @pos: the 'type *' to use as a loop cursor.
  141.  * @n:      another 'type *' to use as temporary storage
  142.  * @root:   'rb_root *' of the rbtree.
  143.  * @field:   the name of the rb_node field within 'type'.
  144.  *
  145.  * rbtree_postorder_for_each_entry_safe() provides a similar guarantee as
  146.  * list_for_each_entry_safe() and allows the iteration to continue independent
  147.  * of changes to @pos by the body of the loop.
  148.  *
  149.  * Note, however, that it cannot handle other modifications that re-order the
  150.  * rbtree it is iterating over. This includes calling rb_erase() on @pos, as
  151.  * rb_erase() may rebalance the tree, causing us to miss some nodes.
  152.  */
  153. #define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \
  154.     for (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \
  155.          pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \
  156.             typeof(*pos), field); 1; }); \
  157.          pos = n)
  158.  
  159. #endif  /* _LINUX_RBTREE_H */

代码清单 9 移植的 rbtree_augmented.h
  1. #pragma once
  2. /*
  3.   Red Black Trees
  4.   (C) 1999  Andrea Arcangeli <andrea@suse.de>
  5.   (C) 2002  David Woodhouse <dwmw2@infradead.org>
  6.   (C) 2012  Michel Lespinasse <walken@google.com>
  7.  
  8.   This program is free software; you can redistribute it and/or modify
  9.   it under the terms of the GNU General Public License as published by
  10.   the Free Software Foundation; either version 2 of the License, or
  11.   (at your option) any later version.
  12.  
  13.   This program is distributed in the hope that it will be useful,
  14.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.   GNU General Public License for more details.
  17.  
  18.   You should have received a copy of the GNU General Public License
  19.   along with this program; if not, write to the Free Software
  20.   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21.  
  22.   linux/include/linux/rbtree_augmented.h
  23. */
  24.  
  25. #ifndef _LINUX_RBTREE_AUGMENTED_H
  26. #define _LINUX_RBTREE_AUGMENTED_H
  27.  
  28. #include "rbtree.h"
  29. # define __always_inline inline
  30. /*
  31.  * Please note - only struct rb_augment_callbacks and the prototypes for
  32.  * rb_insert_augmented() and rb_erase_augmented() are intended to be public.
  33.  * The rest are implementation details you are not expected to depend on.
  34.  *
  35.  * See Documentation/rbtree.txt for documentation and samples.
  36.  */
  37.  
  38. struct rb_augment_callbacks {
  39.     void (*propagate)(struct rb_node* node, struct rb_node* stop);
  40.     void (*copy)(struct rb_node* old, struct rb_node* new);
  41.     void (*rotate)(struct rb_node* old, struct rb_node* new);
  42. };
  43.  
  44. extern void __rb_insert_augmented(struct rb_node* node,
  45.     struct rb_root* root,
  46.     bool newleft, struct rb_node** leftmost,
  47.     void (*augment_rotate)(struct rb_node* old, struct rb_node* new));
  48. /*
  49.  * Fixup the rbtree and update the augmented information when rebalancing.
  50.  *
  51.  * On insertion, the user must update the augmented information on the path
  52.  * leading to the inserted node, then call rb_link_node() as usual and
  53.  * rb_insert_augmented() instead of the usual rb_insert_color() call.
  54.  * If rb_insert_augmented() rebalances the rbtree, it will callback into
  55.  * a user provided function to update the augmented information on the
  56.  * affected subtrees.
  57.  */
  58. static inline void
  59. rb_insert_augmented(struct rb_node* node, struct rb_root* root,
  60.     const struct rb_augment_callbacks* augment)
  61. {
  62.     __rb_insert_augmented(node, root, false, NULL, augment->rotate);
  63. }
  64.  
  65. static inline void
  66. rb_insert_augmented_cached(struct rb_node* node,
  67.     struct rb_root_cached* root, bool newleft,
  68.     const struct rb_augment_callbacks* augment)
  69. {
  70.     __rb_insert_augmented(node, &root->rb_root,
  71.         newleft, &root->rb_leftmost, augment->rotate);
  72. }
  73.  
  74. #define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \
  75.                  rbtype, rbaugmented, rbcompute)       \
  76. static void                          \
  77. rbname ## _propagate(struct rb_node *rb, struct rb_node *stop)       \
  78. {                                   \
  79.     while (rb != stop) {                      \
  80.         rbstruct *node = rb_entry(rb, rbstruct, rbfield);   \
  81.         rbtype augmented = rbcompute(node);        \
  82.         if (node->rbaugmented == augmented)        \
  83.             break;                      \
  84.         node->rbaugmented = augmented;            \
  85.         rb = rb_parent(&node->rbfield);                \
  86.     }                               \
  87. }                                   \
  88. static void                          \
  89. rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new)       \
  90. {                                   \
  91.     rbstruct *old = rb_entry(rb_old, rbstruct, rbfield);     \
  92.     rbstruct *new = rb_entry(rb_new, rbstruct, rbfield);     \
  93.     new->rbaugmented = old->rbaugmented;               \
  94. }                                   \
  95. static void                              \
  96. rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \
  97. {                                   \
  98.     rbstruct *old = rb_entry(rb_old, rbstruct, rbfield);     \
  99.     rbstruct *new = rb_entry(rb_new, rbstruct, rbfield);     \
  100.     new->rbaugmented = old->rbaugmented;               \
  101.     old->rbaugmented = rbcompute(old);             \
  102. }                                   \
  103. rbstatic const struct rb_augment_callbacks rbname = {        \
  104.     .propagate = rbname ## _propagate,             \
  105.     .copy = rbname ## _copy,                  \
  106.     .rotate = rbname ## _rotate                   \
  107. };
  108.  
  109.  
  110. #define RB_RED      0
  111. #define RB_BLACK 1
  112.  
  113. #define __rb_parent(pc)    ((struct rb_node *)(pc & ~3))
  114.  
  115. #define __rb_color(pc)     ((pc) & 1)
  116. #define __rb_is_black(pc)  __rb_color(pc)
  117. #define __rb_is_red(pc)    (!__rb_color(pc))
  118. #define rb_color(rb)       __rb_color((rb)->__rb_parent_color)
  119. #define rb_is_red(rb)      __rb_is_red((rb)->__rb_parent_color)
  120. #define rb_is_black(rb)    __rb_is_black((rb)->__rb_parent_color)
  121.  
  122. static inline void rb_set_parent(struct rb_node* rb, struct rb_node* p)
  123. {
  124.     rb->__rb_parent_color = rb_color(rb) | (unsigned long)p;
  125. }
  126.  
  127. static inline void rb_set_parent_color(struct rb_node* rb,
  128.     struct rb_node* p, int color)
  129. {
  130.     rb->__rb_parent_color = (unsigned long)p | color;
  131. }
  132.  
  133. static inline void
  134. __rb_change_child(struct rb_node* old, struct rb_node* new,
  135.     struct rb_node* parent, struct rb_root* root)
  136. {
  137.     if (parent) {
  138.         if (parent->rb_left == old)
  139.             WRITE_ONCE(parent->rb_left, new);
  140.         else
  141.             WRITE_ONCE(parent->rb_right, new);
  142.     }
  143.     else
  144.         WRITE_ONCE(root->rb_node, new);
  145. }
  146.  
  147. static inline void
  148. __rb_change_child_rcu(struct rb_node* old, struct rb_node* new,
  149.     struct rb_node* parent, struct rb_root* root)
  150. {
  151.     if (parent) {
  152.         if (parent->rb_left == old)
  153.             rcu_assign_pointer(parent->rb_left, new);
  154.         else
  155.             rcu_assign_pointer(parent->rb_right, new);
  156.     }
  157.     else
  158.         rcu_assign_pointer(root->rb_node, new);
  159. }
  160.  
  161. extern void __rb_erase_color(struct rb_node* parent, struct rb_root* root,
  162.     void (*augment_rotate)(struct rb_node* old, struct rb_node* new));
  163.  
  164. static __always_inline struct rb_node*
  165. __rb_erase_augmented(struct rb_node* node, struct rb_root* root,
  166.     struct rb_node** leftmost,
  167.     const struct rb_augment_callbacks* augment)
  168. {
  169.     struct rb_node* child = node->rb_right;
  170.     struct rb_node* tmp = node->rb_left;
  171.     struct rb_node* parent, * rebalance;
  172.     unsigned long pc;
  173.  
  174.     if (leftmost && node == *leftmost)
  175.         *leftmost = rb_next(node);
  176.  
  177.     if (!tmp) {
  178.         /*
  179.          * Case 1: node to erase has no more than 1 child (easy!)
  180.          *
  181.          * Note that if there is one child it must be red due to 5)
  182.          * and node must be black due to 4). We adjust colors locally
  183.          * so as to bypass __rb_erase_color() later on.
  184.          */
  185.         pc = node->__rb_parent_color;
  186.         parent = __rb_parent(pc);
  187.         __rb_change_child(node, child, parent, root);
  188.         if (child) {
  189.             child->__rb_parent_color = pc;
  190.             rebalance = NULL;
  191.         }
  192.         else
  193.             rebalance = __rb_is_black(pc) ? parent : NULL;
  194.         tmp = parent;
  195.     }
  196.     else if (!child) {
  197.         /* Still case 1, but this time the child is node->rb_left */
  198.         tmp->__rb_parent_color = pc = node->__rb_parent_color;
  199.         parent = __rb_parent(pc);
  200.         __rb_change_child(node, tmp, parent, root);
  201.         rebalance = NULL;
  202.         tmp = parent;
  203.     }
  204.     else {
  205.         struct rb_node* successor = child, * child2;
  206.  
  207.         tmp = child->rb_left;
  208.         if (!tmp) {
  209.             /*
  210.              * Case 2: node's successor is its right child
  211.              *
  212.              *    (n)          (s)
  213.              *    / \          / \
  214.              *  (x) (s)  ->  (x) (c)
  215.              *        \
  216.              *        (c)
  217.              */
  218.             parent = successor;
  219.             child2 = successor->rb_right;
  220.  
  221.             augment->copy(node, successor);
  222.         }
  223.         else {
  224.             /*
  225.              * Case 3: node's successor is leftmost under
  226.              * node's right child subtree
  227.              *
  228.              *    (n)          (s)
  229.              *    / \          / \
  230.              *  (x) (y)  ->  (x) (y)
  231.              *      /            /
  232.              *    (p)          (p)
  233.              *    /            /
  234.              *  (s)          (c)
  235.              *    \
  236.              *    (c)
  237.              */
  238.             do {
  239.                 parent = successor;
  240.                 successor = tmp;
  241.                 tmp = tmp->rb_left;
  242.             } while (tmp);
  243.             child2 = successor->rb_right;
  244.             WRITE_ONCE(parent->rb_left, child2);
  245.             WRITE_ONCE(successor->rb_right, child);
  246.             rb_set_parent(child, successor);
  247.  
  248.             augment->copy(node, successor);
  249.             augment->propagate(parent, successor);
  250.         }
  251.  
  252.         tmp = node->rb_left;
  253.         WRITE_ONCE(successor->rb_left, tmp);
  254.         rb_set_parent(tmp, successor);
  255.  
  256.         pc = node->__rb_parent_color;
  257.         tmp = __rb_parent(pc);
  258.         __rb_change_child(node, successor, tmp, root);
  259.  
  260.         if (child2) {
  261.             successor->__rb_parent_color = pc;
  262.             rb_set_parent_color(child2, parent, RB_BLACK);
  263.             rebalance = NULL;
  264.         }
  265.         else {
  266.             unsigned long pc2 = successor->__rb_parent_color;
  267.             successor->__rb_parent_color = pc;
  268.             rebalance = __rb_is_black(pc2) ? parent : NULL;
  269.         }
  270.         tmp = successor;
  271.     }
  272.  
  273.     augment->propagate(tmp, NULL);
  274.     return rebalance;
  275. }
  276.  
  277. static __always_inline void
  278. rb_erase_augmented(struct rb_node* node, struct rb_root* root,
  279.     const struct rb_augment_callbacks* augment)
  280. {
  281.     struct rb_node* rebalance = __rb_erase_augmented(node, root,
  282.         NULL, augment);
  283.     if (rebalance)
  284.         __rb_erase_color(rebalance, root, augment->rotate);
  285. }
  286.  
  287. static __always_inline void
  288. rb_erase_augmented_cached(struct rb_node* node, struct rb_root_cached* root,
  289.     const struct rb_augment_callbacks* augment)
  290. {
  291.     struct rb_node* rebalance = __rb_erase_augmented(node, &root->rb_root,
  292.         &root->rb_leftmost,
  293.         augment);
  294.     if (rebalance)
  295.         __rb_erase_color(rebalance, &root->rb_root, augment->rotate);
  296. }
  297.  
  298. #endif  /* _LINUX_RBTREE_AUGMENTED_H */

代码清单 10 移植的 rbtree.c
  1. /*
  2.   Red Black Trees
  3.   (C) 1999  Andrea Arcangeli <andrea@suse.de>
  4.   (C) 2002  David Woodhouse <dwmw2@infradead.org>
  5.   (C) 2012  Michel Lespinasse <walken@google.com>
  6.  
  7.   This program is free software; you can redistribute it and/or modify
  8.   it under the terms of the GNU General Public License as published by
  9.   the Free Software Foundation; either version 2 of the License, or
  10.   (at your option) any later version.
  11.  
  12.   This program is distributed in the hope that it will be useful,
  13.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.   GNU General Public License for more details.
  16.  
  17.   You should have received a copy of the GNU General Public License
  18.   along with this program; if not, write to the Free Software
  19.   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  
  21.   linux/lib/rbtree.c
  22. */
  23.  
  24. #include "rbtree_augmented.h"
  25. #define EXPORT_SYMBOL(x)
  26.  
  27. /*
  28.  * red-black trees properties:  http://en.wikipedia.org/wiki/Rbtree
  29.  *
  30.  *  1) A node is either red or black
  31.  *  2) The root is black
  32.  *  3) All leaves (NULL) are black
  33.  *  4) Both children of every red node are black
  34.  *  5) Every simple path from root to leaves contains the same number
  35.  *     of black nodes.
  36.  *
  37.  *  4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two
  38.  *  consecutive red nodes in a path and every red node is therefore followed by
  39.  *  a black. So if B is the number of black nodes on every simple path (as per
  40.  *  5), then the longest possible path due to 4 is 2B.
  41.  *
  42.  *  We shall indicate color with case, where black nodes are uppercase and red
  43.  *  nodes will be lowercase. Unknown color nodes shall be drawn as red within
  44.  *  parentheses and have some accompanying text comment.
  45.  */
  46.  
  47.  /*
  48.   * Notes on lockless lookups:
  49.   *
  50.   * All stores to the tree structure (rb_left and rb_right) must be done using
  51.   * WRITE_ONCE(). And we must not inadvertently cause (temporary) loops in the
  52.   * tree structure as seen in program order.
  53.   *
  54.   * These two requirements will allow lockless iteration of the tree -- not
  55.   * correct iteration mind you, tree rotations are not atomic so a lookup might
  56.   * miss entire subtrees.
  57.   *
  58.   * But they do guarantee that any such traversal will only see valid elements
  59.   * and that it will indeed complete -- does not get stuck in a loop.
  60.   *
  61.   * It also guarantees that if the lookup returns an element it is the 'correct'
  62.   * one. But not returning an element does _NOT_ mean it's not present.
  63.   *
  64.   * NOTE:
  65.   *
  66.   * Stores to __rb_parent_color are not important for simple lookups so those
  67.   * are left undone as of now. Nor did I check for loops involving parent
  68.   * pointers.
  69.   */
  70.  
  71. static inline void rb_set_black(struct rb_node* rb)
  72. {
  73.     rb->__rb_parent_color |= RB_BLACK;
  74. }
  75.  
  76. static inline struct rb_node* rb_red_parent(struct rb_node* red)
  77. {
  78.     return (struct rb_node*)red->__rb_parent_color;
  79. }
  80.  
  81. /*
  82.  * Helper function for rotations:
  83.  * - old's parent and color get assigned to new
  84.  * - old gets assigned new as a parent and 'color' as a color.
  85.  */
  86. static inline void
  87. __rb_rotate_set_parents(struct rb_node* old, struct rb_node* new,
  88.     struct rb_root* root, int color)
  89. {
  90.     struct rb_node* parent = rb_parent(old);
  91.     new->__rb_parent_color = old->__rb_parent_color;
  92.     rb_set_parent_color(old, new, color);
  93.     __rb_change_child(old, new, parent, root);
  94. }
  95.  
  96. static __always_inline void
  97. __rb_insert(struct rb_node* node, struct rb_root* root,
  98.     bool newleft, struct rb_node** leftmost,
  99.     void (*augment_rotate)(struct rb_node* old, struct rb_node* new))
  100. {
  101.     struct rb_node* parent = rb_red_parent(node), * gparent, * tmp;
  102.  
  103.     if (newleft)
  104.         *leftmost = node;
  105.  
  106.     while (true) {
  107.         /*
  108.          * Loop invariant: node is red.
  109.          */
  110.         if (unlikely(!parent)) {
  111.             /*
  112.              * The inserted node is root. Either this is the
  113.              * first node, or we recursed at Case 1 below and
  114.              * are no longer violating 4).
  115.              */
  116.             rb_set_parent_color(node, NULL, RB_BLACK);
  117.             break;
  118.         }
  119.  
  120.         /*
  121.          * If there is a black parent, we are done.
  122.          * Otherwise, take some corrective action as,
  123.          * per 4), we don't want a red root or two
  124.          * consecutive red nodes.
  125.          */
  126.         if (rb_is_black(parent))
  127.             break;
  128.  
  129.         gparent = rb_red_parent(parent);
  130.  
  131.         tmp = gparent->rb_right;
  132.         if (parent != tmp) {  /* parent == gparent->rb_left */
  133.             if (tmp && rb_is_red(tmp)) {
  134.                 /*
  135.                  * Case 1 - node's uncle is red (color flips).
  136.                  *
  137.                  *       G            g
  138.                  *      / \          / \
  139.                  *     p   u  -->   P   U
  140.                  *    /            /
  141.                  *   n            n
  142.                  *
  143.                  * However, since g's parent might be red, and
  144.                  * 4) does not allow this, we need to recurse
  145.                  * at g.
  146.                  */
  147.                 rb_set_parent_color(tmp, gparent, RB_BLACK);
  148.                 rb_set_parent_color(parent, gparent, RB_BLACK);
  149.                 node = gparent;
  150.                 parent = rb_parent(node);
  151.                 rb_set_parent_color(node, parent, RB_RED);
  152.                 continue;
  153.             }
  154.  
  155.             tmp = parent->rb_right;
  156.             if (node == tmp) {
  157.                 /*
  158.                  * Case 2 - node's uncle is black and node is
  159.                  * the parent's right child (left rotate at parent).
  160.                  *
  161.                  *      G             G
  162.                  *     / \           / \
  163.                  *    p   U  -->    n   U
  164.                  *     \           /
  165.                  *      n         p
  166.                  *
  167.                  * This still leaves us in violation of 4), the
  168.                  * continuation into Case 3 will fix that.
  169.                  */
  170.                 tmp = node->rb_left;
  171.                 WRITE_ONCE(parent->rb_right, tmp);
  172.                 WRITE_ONCE(node->rb_left, parent);
  173.                 if (tmp)
  174.                     rb_set_parent_color(tmp, parent,
  175.                         RB_BLACK);
  176.                 rb_set_parent_color(parent, node, RB_RED);
  177.                 augment_rotate(parent, node);
  178.                 parent = node;
  179.                 tmp = node->rb_right;
  180.             }
  181.  
  182.             /*
  183.              * Case 3 - node's uncle is black and node is
  184.              * the parent's left child (right rotate at gparent).
  185.              *
  186.              *        G           P
  187.              *       / \         / \
  188.              *      p   U  -->  n   g
  189.              *     /                 \
  190.              *    n                   U
  191.              */
  192.             WRITE_ONCE(gparent->rb_left, tmp); /* == parent->rb_right */
  193.             WRITE_ONCE(parent->rb_right, gparent);
  194.             if (tmp)
  195.                 rb_set_parent_color(tmp, gparent, RB_BLACK);
  196.             __rb_rotate_set_parents(gparent, parent, root, RB_RED);
  197.             augment_rotate(gparent, parent);
  198.             break;
  199.         }
  200.         else {
  201.             tmp = gparent->rb_left;
  202.             if (tmp && rb_is_red(tmp)) {
  203.                 /* Case 1 - color flips */
  204.                 rb_set_parent_color(tmp, gparent, RB_BLACK);
  205.                 rb_set_parent_color(parent, gparent, RB_BLACK);
  206.                 node = gparent;
  207.                 parent = rb_parent(node);
  208.                 rb_set_parent_color(node, parent, RB_RED);
  209.                 continue;
  210.             }
  211.  
  212.             tmp = parent->rb_left;
  213.             if (node == tmp) {
  214.                 /* Case 2 - right rotate at parent */
  215.                 tmp = node->rb_right;
  216.                 WRITE_ONCE(parent->rb_left, tmp);
  217.                 WRITE_ONCE(node->rb_right, parent);
  218.                 if (tmp)
  219.                     rb_set_parent_color(tmp, parent,
  220.                         RB_BLACK);
  221.                 rb_set_parent_color(parent, node, RB_RED);
  222.                 augment_rotate(parent, node);
  223.                 parent = node;
  224.                 tmp = node->rb_left;
  225.             }
  226.  
  227.             /* Case 3 - left rotate at gparent */
  228.             WRITE_ONCE(gparent->rb_right, tmp); /* == parent->rb_left */
  229.             WRITE_ONCE(parent->rb_left, gparent);
  230.             if (tmp)
  231.                 rb_set_parent_color(tmp, gparent, RB_BLACK);
  232.             __rb_rotate_set_parents(gparent, parent, root, RB_RED);
  233.             augment_rotate(gparent, parent);
  234.             break;
  235.         }
  236.     }
  237. }
  238.  
  239. /*
  240.  * Inline version for rb_erase() use - we want to be able to inline
  241.  * and eliminate the dummy_rotate callback there
  242.  */
  243. static __always_inline void
  244. ____rb_erase_color(struct rb_node* parent, struct rb_root* root,
  245.     void (*augment_rotate)(struct rb_node* old, struct rb_node* new))
  246. {
  247.     struct rb_node* node = NULL, * sibling, * tmp1, * tmp2;
  248.  
  249.     while (true) {
  250.         /*
  251.          * Loop invariants:
  252.          * - node is black (or NULL on first iteration)
  253.          * - node is not the root (parent is not NULL)
  254.          * - All leaf paths going through parent and node have a
  255.          *   black node count that is 1 lower than other leaf paths.
  256.          */
  257.         sibling = parent->rb_right;
  258.         if (node != sibling) { /* node == parent->rb_left */
  259.             if (rb_is_red(sibling)) {
  260.                 /*
  261.                  * Case 1 - left rotate at parent
  262.                  *
  263.                  *     P               S
  264.                  *    / \             / \
  265.                  *   N   s    -->    p   Sr
  266.                  *      / \         / \
  267.                  *     Sl  Sr      N   Sl
  268.                  */
  269.                 tmp1 = sibling->rb_left;
  270.                 WRITE_ONCE(parent->rb_right, tmp1);
  271.                 WRITE_ONCE(sibling->rb_left, parent);
  272.                 rb_set_parent_color(tmp1, parent, RB_BLACK);
  273.                 __rb_rotate_set_parents(parent, sibling, root,
  274.                     RB_RED);
  275.                 augment_rotate(parent, sibling);
  276.                 sibling = tmp1;
  277.             }
  278.             tmp1 = sibling->rb_right;
  279.             if (!tmp1 || rb_is_black(tmp1)) {
  280.                 tmp2 = sibling->rb_left;
  281.                 if (!tmp2 || rb_is_black(tmp2)) {
  282.                     /*
  283.                      * Case 2 - sibling color flip
  284.                      * (p could be either color here)
  285.                      *
  286.                      *    (p)           (p)
  287.                      *    / \           / \
  288.                      *   N   S    -->  N   s
  289.                      *      / \           / \
  290.                      *     Sl  Sr        Sl  Sr
  291.                      *
  292.                      * This leaves us violating 5) which
  293.                      * can be fixed by flipping p to black
  294.                      * if it was red, or by recursing at p.
  295.                      * p is red when coming from Case 1.
  296.                      */
  297.                     rb_set_parent_color(sibling, parent,
  298.                         RB_RED);
  299.                     if (rb_is_red(parent))
  300.                         rb_set_black(parent);
  301.                     else {
  302.                         node = parent;
  303.                         parent = rb_parent(node);
  304.                         if (parent)
  305.                             continue;
  306.                     }
  307.                     break;
  308.                 }
  309.                 /*
  310.                  * Case 3 - right rotate at sibling
  311.                  * (p could be either color here)
  312.                  *
  313.                  *   (p)           (p)
  314.                  *   / \           / \
  315.                  *  N   S    -->  N   sl
  316.                  *     / \             \
  317.                  *    sl  Sr            S
  318.                  *                       \
  319.                  *                        Sr
  320.                  *
  321.                  * Note: p might be red, and then both
  322.                  * p and sl are red after rotation(which
  323.                  * breaks property 4). This is fixed in
  324.                  * Case 4 (in __rb_rotate_set_parents()
  325.                  *         which set sl the color of p
  326.                  *         and set p RB_BLACK)
  327.                  *
  328.                  *   (p)            (sl)
  329.                  *   / \            /  \
  330.                  *  N   sl   -->   P    S
  331.                  *       \        /      \
  332.                  *        S      N        Sr
  333.                  *         \
  334.                  *          Sr
  335.                  */
  336.                 tmp1 = tmp2->rb_right;
  337.                 WRITE_ONCE(sibling->rb_left, tmp1);
  338.                 WRITE_ONCE(tmp2->rb_right, sibling);
  339.                 WRITE_ONCE(parent->rb_right, tmp2);
  340.                 if (tmp1)
  341.                     rb_set_parent_color(tmp1, sibling,
  342.                         RB_BLACK);
  343.                 augment_rotate(sibling, tmp2);
  344.                 tmp1 = sibling;
  345.                 sibling = tmp2;
  346.             }
  347.             /*
  348.              * Case 4 - left rotate at parent + color flips
  349.              * (p and sl could be either color here.
  350.              *  After rotation, p becomes black, s acquires
  351.              *  p's color, and sl keeps its color)
  352.              *
  353.              *      (p)             (s)
  354.              *      / \             / \
  355.              *     N   S     -->   P   Sr
  356.              *        / \         / \
  357.              *      (sl) sr      N  (sl)
  358.              */
  359.             tmp2 = sibling->rb_left;
  360.             WRITE_ONCE(parent->rb_right, tmp2);
  361.             WRITE_ONCE(sibling->rb_left, parent);
  362.             rb_set_parent_color(tmp1, sibling, RB_BLACK);
  363.             if (tmp2)
  364.                 rb_set_parent(tmp2, parent);
  365.             __rb_rotate_set_parents(parent, sibling, root,
  366.                 RB_BLACK);
  367.             augment_rotate(parent, sibling);
  368.             break;
  369.         }
  370.         else {
  371.             sibling = parent->rb_left;
  372.             if (rb_is_red(sibling)) {
  373.                 /* Case 1 - right rotate at parent */
  374.                 tmp1 = sibling->rb_right;
  375.                 WRITE_ONCE(parent->rb_left, tmp1);
  376.                 WRITE_ONCE(sibling->rb_right, parent);
  377.                 rb_set_parent_color(tmp1, parent, RB_BLACK);
  378.                 __rb_rotate_set_parents(parent, sibling, root,
  379.                     RB_RED);
  380.                 augment_rotate(parent, sibling);
  381.                 sibling = tmp1;
  382.             }
  383.             tmp1 = sibling->rb_left;
  384.             if (!tmp1 || rb_is_black(tmp1)) {
  385.                 tmp2 = sibling->rb_right;
  386.                 if (!tmp2 || rb_is_black(tmp2)) {
  387.                     /* Case 2 - sibling color flip */
  388.                     rb_set_parent_color(sibling, parent,
  389.                         RB_RED);
  390.                     if (rb_is_red(parent))
  391.                         rb_set_black(parent);
  392.                     else {
  393.                         node = parent;
  394.                         parent = rb_parent(node);
  395.                         if (parent)
  396.                             continue;
  397.                     }
  398.                     break;
  399.                 }
  400.                 /* Case 3 - left rotate at sibling */
  401.                 tmp1 = tmp2->rb_left;
  402.                 WRITE_ONCE(sibling->rb_right, tmp1);
  403.                 WRITE_ONCE(tmp2->rb_left, sibling);
  404.                 WRITE_ONCE(parent->rb_left, tmp2);
  405.                 if (tmp1)
  406.                     rb_set_parent_color(tmp1, sibling,
  407.                         RB_BLACK);
  408.                 augment_rotate(sibling, tmp2);
  409.                 tmp1 = sibling;
  410.                 sibling = tmp2;
  411.             }
  412.             /* Case 4 - right rotate at parent + color flips */
  413.             tmp2 = sibling->rb_right;
  414.             WRITE_ONCE(parent->rb_left, tmp2);
  415.             WRITE_ONCE(sibling->rb_right, parent);
  416.             rb_set_parent_color(tmp1, sibling, RB_BLACK);
  417.             if (tmp2)
  418.                 rb_set_parent(tmp2, parent);
  419.             __rb_rotate_set_parents(parent, sibling, root,
  420.                 RB_BLACK);
  421.             augment_rotate(parent, sibling);
  422.             break;
  423.         }
  424.     }
  425. }
  426.  
  427. /* Non-inline version for rb_erase_augmented() use */
  428. void __rb_erase_color(struct rb_node* parent, struct rb_root* root,
  429.     void (*augment_rotate)(struct rb_node* old, struct rb_node* new))
  430. {
  431.     ____rb_erase_color(parent, root, augment_rotate);
  432. }
  433. EXPORT_SYMBOL(__rb_erase_color);
  434.  
  435. /*
  436.  * Non-augmented rbtree manipulation functions.
  437.  *
  438.  * We use dummy augmented callbacks here, and have the compiler optimize them
  439.  * out of the rb_insert_color() and rb_erase() function definitions.
  440.  */
  441.  
  442. static inline void dummy_propagate(struct rb_node* node, struct rb_node* stop) {}
  443. static inline void dummy_copy(struct rb_node* old, struct rb_node* new) {}
  444. static inline void dummy_rotate(struct rb_node* old, struct rb_node* new) {}
  445.  
  446. static const struct rb_augment_callbacks dummy_callbacks = {
  447.     .propagate = dummy_propagate,
  448.     .copy = dummy_copy,
  449.     .rotate = dummy_rotate
  450. };
  451.  
  452. void rb_insert_color(struct rb_node* node, struct rb_root* root)
  453. {
  454.     __rb_insert(node, root, false, NULL, dummy_rotate);
  455. }
  456. EXPORT_SYMBOL(rb_insert_color);
  457.  
  458. void rb_erase(struct rb_node* node, struct rb_root* root)
  459. {
  460.     struct rb_node* rebalance;
  461.     rebalance = __rb_erase_augmented(node, root,
  462.         NULL, &dummy_callbacks);
  463.     if (rebalance)
  464.         ____rb_erase_color(rebalance, root, dummy_rotate);
  465. }
  466. EXPORT_SYMBOL(rb_erase);
  467.  
  468. void rb_insert_color_cached(struct rb_node* node,
  469.     struct rb_root_cached* root, bool leftmost)
  470. {
  471.     __rb_insert(node, &root->rb_root, leftmost,
  472.         &root->rb_leftmost, dummy_rotate);
  473. }
  474. EXPORT_SYMBOL(rb_insert_color_cached);
  475.  
  476. void rb_erase_cached(struct rb_node* node, struct rb_root_cached* root)
  477. {
  478.     struct rb_node* rebalance;
  479.     rebalance = __rb_erase_augmented(node, &root->rb_root,
  480.         &root->rb_leftmost, &dummy_callbacks);
  481.     if (rebalance)
  482.         ____rb_erase_color(rebalance, &root->rb_root, dummy_rotate);
  483. }
  484. EXPORT_SYMBOL(rb_erase_cached);
  485.  
  486. /*
  487.  * Augmented rbtree manipulation functions.
  488.  *
  489.  * This instantiates the same __always_inline functions as in the non-augmented
  490.  * case, but this time with user-defined callbacks.
  491.  */
  492.  
  493. void __rb_insert_augmented(struct rb_node* node, struct rb_root* root,
  494.     bool newleft, struct rb_node** leftmost,
  495.     void (*augment_rotate)(struct rb_node* old, struct rb_node* new))
  496. {
  497.     __rb_insert(node, root, newleft, leftmost, augment_rotate);
  498. }
  499. EXPORT_SYMBOL(__rb_insert_augmented);
  500.  
  501. /*
  502.  * This function returns the first node (in sort order) of the tree.
  503.  */
  504. struct rb_node* rb_first(const struct rb_root* root)
  505. {
  506.     struct rb_node* n;
  507.  
  508.     n = root->rb_node;
  509.     if (!n)
  510.         return NULL;
  511.     while (n->rb_left)
  512.         n = n->rb_left;
  513.     return n;
  514. }
  515. EXPORT_SYMBOL(rb_first);
  516.  
  517. struct rb_node* rb_last(const struct rb_root* root)
  518. {
  519.     struct rb_node* n;
  520.  
  521.     n = root->rb_node;
  522.     if (!n)
  523.         return NULL;
  524.     while (n->rb_right)
  525.         n = n->rb_right;
  526.     return n;
  527. }
  528. EXPORT_SYMBOL(rb_last);
  529.  
  530. struct rb_node* rb_next(const struct rb_node* node)
  531. {
  532.     struct rb_node* parent;
  533.  
  534.     if (RB_EMPTY_NODE(node))
  535.         return NULL;
  536.  
  537.     /*
  538.      * If we have a right-hand child, go down and then left as far
  539.      * as we can.
  540.      */
  541.     if (node->rb_right) {
  542.         node = node->rb_right;
  543.         while (node->rb_left)
  544.             node = node->rb_left;
  545.         return (struct rb_node*)node;
  546.     }
  547.  
  548.     /*
  549.      * No right-hand children. Everything down and left is smaller than us,
  550.      * so any 'next' node must be in the general direction of our parent.
  551.      * Go up the tree; any time the ancestor is a right-hand child of its
  552.      * parent, keep going up. First time it's a left-hand child of its
  553.      * parent, said parent is our 'next' node.
  554.      */
  555.     while ((parent = rb_parent(node)) && node == parent->rb_right)
  556.         node = parent;
  557.  
  558.     return parent;
  559. }
  560. EXPORT_SYMBOL(rb_next);
  561.  
  562. struct rb_node* rb_prev(const struct rb_node* node)
  563. {
  564.     struct rb_node* parent;
  565.  
  566.     if (RB_EMPTY_NODE(node))
  567.         return NULL;
  568.  
  569.     /*
  570.      * If we have a left-hand child, go down and then right as far
  571.      * as we can.
  572.      */
  573.     if (node->rb_left) {
  574.         node = node->rb_left;
  575.         while (node->rb_right)
  576.             node = node->rb_right;
  577.         return (struct rb_node*)node;
  578.     }
  579.  
  580.     /*
  581.      * No left-hand children. Go up till we find an ancestor which
  582.      * is a right-hand child of its parent.
  583.      */
  584.     while ((parent = rb_parent(node)) && node == parent->rb_left)
  585.         node = parent;
  586.  
  587.     return parent;
  588. }
  589. EXPORT_SYMBOL(rb_prev);
  590.  
  591. void rb_replace_node(struct rb_node* victim, struct rb_node* new,
  592.     struct rb_root* root)
  593. {
  594.     struct rb_node* parent = rb_parent(victim);
  595.  
  596.     /* Copy the pointers/colour from the victim to the replacement */
  597.     *new = *victim;
  598.  
  599.     /* Set the surrounding nodes to point to the replacement */
  600.     if (victim->rb_left)
  601.         rb_set_parent(victim->rb_left, new);
  602.     if (victim->rb_right)
  603.         rb_set_parent(victim->rb_right, new);
  604.     __rb_change_child(victim, new, parent, root);
  605. }
  606. EXPORT_SYMBOL(rb_replace_node);
  607.  
  608. void rb_replace_node_cached(struct rb_node* victim, struct rb_node* new,
  609.     struct rb_root_cached* root)
  610. {
  611.     rb_replace_node(victim, new, &root->rb_root);
  612.  
  613.     if (root->rb_leftmost == victim)
  614.         root->rb_leftmost = new;
  615. }
  616. EXPORT_SYMBOL(rb_replace_node_cached);
  617.  
  618. void rb_replace_node_rcu(struct rb_node* victim, struct rb_node* new,
  619.     struct rb_root* root)
  620. {
  621.     struct rb_node* parent = rb_parent(victim);
  622.  
  623.     /* Copy the pointers/colour from the victim to the replacement */
  624.     *new = *victim;
  625.  
  626.     /* Set the surrounding nodes to point to the replacement */
  627.     if (victim->rb_left)
  628.         rb_set_parent(victim->rb_left, new);
  629.     if (victim->rb_right)
  630.         rb_set_parent(victim->rb_right, new);
  631.  
  632.     /* Set the parent's pointer to the new node last after an RCU barrier
  633.      * so that the pointers onwards are seen to be set correctly when doing
  634.      * an RCU walk over the tree.
  635.      */
  636.     __rb_change_child_rcu(victim, new, parent, root);
  637. }
  638. EXPORT_SYMBOL(rb_replace_node_rcu);
  639.  
  640. static struct rb_node* rb_left_deepest_node(const struct rb_node* node)
  641. {
  642.     for (;;) {
  643.         if (node->rb_left)
  644.             node = node->rb_left;
  645.         else if (node->rb_right)
  646.             node = node->rb_right;
  647.         else
  648.             return (struct rb_node*)node;
  649.     }
  650. }
  651.  
  652. struct rb_node* rb_next_postorder(const struct rb_node* node)
  653. {
  654.     const struct rb_node* parent;
  655.     if (!node)
  656.         return NULL;
  657.     parent = rb_parent(node);
  658.  
  659.     /* If we're sitting on node, we've already seen our children */
  660.     if (parent && node == parent->rb_left && parent->rb_right) {
  661.         /* If we are the parent's left node, go to the parent's right
  662.          * node then all the way down to the left */
  663.         return rb_left_deepest_node(parent->rb_right);
  664.     }
  665.     else
  666.         /* Otherwise we are the parent's right node, and the parent
  667.          * should be next */
  668.         return (struct rb_node*)parent;
  669. }
  670. EXPORT_SYMBOL(rb_next_postorder);
  671.  
  672. struct rb_node* rb_first_postorder(const struct rb_root* root)
  673. {
  674.     if (!root->rb_node)
  675.         return NULL;
  676.  
  677.     return rb_left_deepest_node(root->rb_node);
  678. }
  679. EXPORT_SYMBOL(rb_first_postorder);

代码清单 11 是移植好的测试代码,基本和内核测试代码是一样的使用。其中 check() 函数是新的,它的作用是检查红黑树的正确性。检查包括:插入的内容顺序是否正确;是否没有相邻的红色节点;根的左右子树的黑节点数量是否相等。

代码清单 11 用户态代码
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #include "rbtree_augmented.h"
  5.  
  6. #define NODES 10000
  7.  
  8. struct test_node
  9. {
  10.     struct rb_node rb;
  11.     int key;
  12.  
  13.     int val;
  14.     int augmented;
  15. };
  16.  
  17. static struct rb_root root = RB_ROOT;
  18. static struct test_node nodes[NODES];
  19.  
  20. static void insert(struct test_node* node, struct rb_root* root)
  21. {
  22.     struct rb_node** new = &(root->rb_node), * parent = NULL;
  23.  
  24.     int key = node->key;
  25.  
  26.     while (*new)
  27.     {
  28.         parent = *new;
  29.         if (key < rb_entry(parent, struct test_node, rb)->key)
  30.             new = &parent->rb_left;
  31.         else
  32.             new = &parent->rb_right;
  33.     }
  34.  
  35.     rb_link_node(&node->rb, parent, new);
  36.     rb_insert_color(&node->rb, root);
  37. }
  38.  
  39. void erase(struct test_node* node, struct rb_root* root)
  40. {
  41.     rb_erase(&node->rb, root);
  42. }
  43.  
  44. static int black_path_count(struct rb_node* rb)
  45. {
  46.     int count;
  47.     for (count = 0; rb; rb = rb_parent(rb))
  48.         count += !rb_is_red(rb);
  49.     return count;
  50. }
  51.  
  52. static void check(int nr_nodes)
  53. {
  54.     struct rb_node* rb;
  55.     int count = 0, blacks = 0;
  56.     int prev_key = 0;
  57.  
  58.     for (rb = rb_first(&root); rb; rb = rb_next(rb))
  59.     {
  60.         struct test_node* node = rb_entry(rb, struct test_node, rb);
  61.         if (node->key < prev_key)
  62.             printf("[WARN] node->key(%d) < prev_key(%d)\n", node->key, prev_key);
  63.         if (rb_is_red(rb) && (!rb_parent(rb) || rb_is_red(rb_parent(rb))))
  64.             printf("[WARN] two red nodes\n");
  65.         if (!count)
  66.             blacks = black_path_count(rb);
  67.         else if ((!rb->rb_left || !rb->rb_right) && (blacks != black_path_count(rb)))
  68.             printf("[WARN] black count wrong\n");
  69.  
  70.         prev_key = node->key;
  71.         count++;
  72.     }
  73. }
  74.  
  75. void print_rbtree(struct rb_root* tree)
  76. {
  77.     struct rb_node* node;
  78.  
  79.     for (node = rb_first(tree); node; node = rb_next(node))
  80.         printf("%d ", rb_entry(node, struct test_node, rb)->key);
  81.     printf("\n");
  82. }
  83.  
  84. int search_rbtree(struct rb_root* tree, int num)
  85. {
  86.     struct rb_node* node;
  87.  
  88.     for (node = rb_first(tree); node; node = rb_next(node))
  89.     {
  90.         if (num == rb_entry(node, struct test_node, rb)->key)
  91.             return true;
  92.     }
  93.  
  94.     return false;
  95. }
  96.  
  97. int main()
  98. {
  99.     int i, j;
  100.     int num;
  101.  
  102.     for (i = 0; i < NODES; i++)
  103.     {
  104.         nodes[i].key = i;
  105.         nodes[i].val = i;
  106.     }
  107.  
  108.     /* insert */
  109.     for (j = 0; j < NODES; j++)
  110.     {
  111.         insert(nodes + j, &root);
  112.     }
  113.  
  114.     /* check */
  115.     check(0);
  116.  
  117.     //print_rbtree(&root);
  118.     while (1)
  119.     {
  120.         num = -2;
  121.         printf("Please input the num which you want to search in rbtree.\n");
  122.         printf("The input num should be 0 <= input num < 10000\n");
  123.         printf("Input -1 to exit\n");
  124.         printf(">>> ");
  125.  
  126.         scanf("%d", &num);
  127.  
  128.         if (num == -1)
  129.             goto exit;
  130.  
  131.         if (num < 0 || num > 10000)
  132.         {
  133.             printf("WARNNING: Invalild input number!\n");
  134.             continue;
  135.         }
  136.  
  137.         if (search_rbtree(&root, num))
  138.             printf("RESULT: Found %d in the rbtree\n", num);
  139.         else
  140.             printf("RESULT: Not Found %d in the rbtree\n", num);
  141.     }
  142.  
  143. exit:
  144.     /* erase */
  145.     for (j = 0; j < NODES; j++)
  146.         erase(nodes + j, &root);
  147.  
  148.     return 0;
  149. }