···41414242#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))43434444+#include <linux/types.h>4545+4646+static __always_inline void __read_once_size(const volatile void *p, void *res, int size)4747+{4848+ switch (size) {4949+ case 1: *(__u8 *)res = *(volatile __u8 *)p; break;5050+ case 2: *(__u16 *)res = *(volatile __u16 *)p; break;5151+ case 4: *(__u32 *)res = *(volatile __u32 *)p; break;5252+ case 8: *(__u64 *)res = *(volatile __u64 *)p; break;5353+ default:5454+ barrier();5555+ __builtin_memcpy((void *)res, (const void *)p, size);5656+ barrier();5757+ }5858+}5959+6060+static __always_inline void __write_once_size(volatile void *p, void *res, int size)6161+{6262+ switch (size) {6363+ case 1: *(volatile __u8 *)p = *(__u8 *)res; break;6464+ case 2: *(volatile __u16 *)p = *(__u16 *)res; break;6565+ case 4: *(volatile __u32 *)p = *(__u32 *)res; break;6666+ case 8: *(volatile __u64 *)p = *(__u64 *)res; break;6767+ default:6868+ barrier();6969+ __builtin_memcpy((void *)p, (const void *)res, size);7070+ barrier();7171+ }7272+}7373+7474+/*7575+ * Prevent the compiler from merging or refetching reads or writes. The7676+ * compiler is also forbidden from reordering successive instances of7777+ * READ_ONCE, WRITE_ONCE and ACCESS_ONCE (see below), but only when the7878+ * compiler is aware of some particular ordering. One way to make the7979+ * compiler aware of ordering is to put the two invocations of READ_ONCE,8080+ * WRITE_ONCE or ACCESS_ONCE() in different C statements.8181+ *8282+ * In contrast to ACCESS_ONCE these two macros will also work on aggregate8383+ * data types like structs or unions. If the size of the accessed data8484+ * type exceeds the word size of the machine (e.g., 32 bits or 64 bits)8585+ * READ_ONCE() and WRITE_ONCE() will fall back to memcpy and print a8686+ * compile-time warning.8787+ *8888+ * Their two major use cases are: (1) Mediating communication between8989+ * process-level code and irq/NMI handlers, all running on the same CPU,9090+ * and (2) Ensuring that the compiler does not fold, spindle, or otherwise9191+ * mutilate accesses that either do not require ordering or that interact9292+ * with an explicit memory barrier or atomic instruction that provides the9393+ * required ordering.9494+ */9595+9696+#define READ_ONCE(x) \9797+ ({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })9898+9999+#define WRITE_ONCE(x, val) \100100+ ({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })101101+44102#endif /* _TOOLS_LINUX_COMPILER_H */
···11+/*22+ Red Black Trees33+ (C) 1999 Andrea Arcangeli <andrea@suse.de>44+55+ This program is free software; you can redistribute it and/or modify66+ it under the terms of the GNU General Public License as published by77+ the Free Software Foundation; either version 2 of the License, or88+ (at your option) any later version.99+1010+ This program is distributed in the hope that it will be useful,1111+ but WITHOUT ANY WARRANTY; without even the implied warranty of1212+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313+ GNU General Public License for more details.1414+1515+ You should have received a copy of the GNU General Public License1616+ along with this program; if not, write to the Free Software1717+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA1818+1919+ linux/include/linux/rbtree.h2020+2121+ To use rbtrees you'll have to implement your own insert and search cores.2222+ This will avoid us to use callbacks and to drop drammatically performances.2323+ I know it's not the cleaner way, but in C (not in C++) to get2424+ performances and genericity...2525+2626+ See Documentation/rbtree.txt for documentation and samples.2727+*/2828+2929+#ifndef __TOOLS_LINUX_PERF_RBTREE_H3030+#define __TOOLS_LINUX_PERF_RBTREE_H3131+3232+#include <linux/kernel.h>3333+#include <linux/stddef.h>3434+3535+struct rb_node {3636+ unsigned long __rb_parent_color;3737+ struct rb_node *rb_right;3838+ struct rb_node *rb_left;3939+} __attribute__((aligned(sizeof(long))));4040+ /* The alignment might seem pointless, but allegedly CRIS needs it */4141+4242+struct rb_root {4343+ struct rb_node *rb_node;4444+};4545+4646+4747+#define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3))4848+4949+#define RB_ROOT (struct rb_root) { NULL, }5050+#define rb_entry(ptr, type, member) container_of(ptr, type, member)5151+5252+#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)5353+5454+/* 'empty' nodes are nodes that are known not to be inserted in an rbtree */5555+#define RB_EMPTY_NODE(node) \5656+ ((node)->__rb_parent_color == (unsigned long)(node))5757+#define RB_CLEAR_NODE(node) \5858+ ((node)->__rb_parent_color = (unsigned long)(node))5959+6060+6161+extern void rb_insert_color(struct rb_node *, struct rb_root *);6262+extern void rb_erase(struct rb_node *, struct rb_root *);6363+6464+6565+/* Find logical next and previous nodes in a tree */6666+extern struct rb_node *rb_next(const struct rb_node *);6767+extern struct rb_node *rb_prev(const struct rb_node *);6868+extern struct rb_node *rb_first(const struct rb_root *);6969+extern struct rb_node *rb_last(const struct rb_root *);7070+7171+/* Postorder iteration - always visit the parent after its children */7272+extern struct rb_node *rb_first_postorder(const struct rb_root *);7373+extern struct rb_node *rb_next_postorder(const struct rb_node *);7474+7575+/* Fast replacement of a single node without remove/rebalance/add/rebalance */7676+extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,7777+ struct rb_root *root);7878+7979+static inline void rb_link_node(struct rb_node *node, struct rb_node *parent,8080+ struct rb_node **rb_link)8181+{8282+ node->__rb_parent_color = (unsigned long)parent;8383+ node->rb_left = node->rb_right = NULL;8484+8585+ *rb_link = node;8686+}8787+8888+#define rb_entry_safe(ptr, type, member) \8989+ ({ typeof(ptr) ____ptr = (ptr); \9090+ ____ptr ? rb_entry(____ptr, type, member) : NULL; \9191+ })9292+9393+9494+/*9595+ * Handy for checking that we are not deleting an entry that is9696+ * already in a list, found in block/{blk-throttle,cfq-iosched}.c,9797+ * probably should be moved to lib/rbtree.c...9898+ */9999+static inline void rb_erase_init(struct rb_node *n, struct rb_root *root)100100+{101101+ rb_erase(n, root);102102+ RB_CLEAR_NODE(n);103103+}104104+#endif /* __TOOLS_LINUX_PERF_RBTREE_H */
+245
tools/include/linux/rbtree_augmented.h
···11+/*22+ Red Black Trees33+ (C) 1999 Andrea Arcangeli <andrea@suse.de>44+ (C) 2002 David Woodhouse <dwmw2@infradead.org>55+ (C) 2012 Michel Lespinasse <walken@google.com>66+77+ This program is free software; you can redistribute it and/or modify88+ it under the terms of the GNU General Public License as published by99+ the Free Software Foundation; either version 2 of the License, or1010+ (at your option) any later version.1111+1212+ This program is distributed in the hope that it will be useful,1313+ but WITHOUT ANY WARRANTY; without even the implied warranty of1414+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515+ GNU General Public License for more details.1616+1717+ You should have received a copy of the GNU General Public License1818+ along with this program; if not, write to the Free Software1919+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA2020+2121+ tools/linux/include/linux/rbtree_augmented.h2222+2323+ Copied from:2424+ linux/include/linux/rbtree_augmented.h2525+*/2626+2727+#ifndef _TOOLS_LINUX_RBTREE_AUGMENTED_H2828+#define _TOOLS_LINUX_RBTREE_AUGMENTED_H2929+3030+#include <linux/compiler.h>3131+#include <linux/rbtree.h>3232+3333+/*3434+ * Please note - only struct rb_augment_callbacks and the prototypes for3535+ * rb_insert_augmented() and rb_erase_augmented() are intended to be public.3636+ * The rest are implementation details you are not expected to depend on.3737+ *3838+ * See Documentation/rbtree.txt for documentation and samples.3939+ */4040+4141+struct rb_augment_callbacks {4242+ void (*propagate)(struct rb_node *node, struct rb_node *stop);4343+ void (*copy)(struct rb_node *old, struct rb_node *new);4444+ void (*rotate)(struct rb_node *old, struct rb_node *new);4545+};4646+4747+extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,4848+ void (*augment_rotate)(struct rb_node *old, struct rb_node *new));4949+/*5050+ * Fixup the rbtree and update the augmented information when rebalancing.5151+ *5252+ * On insertion, the user must update the augmented information on the path5353+ * leading to the inserted node, then call rb_link_node() as usual and5454+ * rb_augment_inserted() instead of the usual rb_insert_color() call.5555+ * If rb_augment_inserted() rebalances the rbtree, it will callback into5656+ * a user provided function to update the augmented information on the5757+ * affected subtrees.5858+ */5959+static inline void6060+rb_insert_augmented(struct rb_node *node, struct rb_root *root,6161+ const struct rb_augment_callbacks *augment)6262+{6363+ __rb_insert_augmented(node, root, augment->rotate);6464+}6565+6666+#define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \6767+ rbtype, rbaugmented, rbcompute) \6868+static inline void \6969+rbname ## _propagate(struct rb_node *rb, struct rb_node *stop) \7070+{ \7171+ while (rb != stop) { \7272+ rbstruct *node = rb_entry(rb, rbstruct, rbfield); \7373+ rbtype augmented = rbcompute(node); \7474+ if (node->rbaugmented == augmented) \7575+ break; \7676+ node->rbaugmented = augmented; \7777+ rb = rb_parent(&node->rbfield); \7878+ } \7979+} \8080+static inline void \8181+rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \8282+{ \8383+ rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \8484+ rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \8585+ new->rbaugmented = old->rbaugmented; \8686+} \8787+static void \8888+rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \8989+{ \9090+ rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \9191+ rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \9292+ new->rbaugmented = old->rbaugmented; \9393+ old->rbaugmented = rbcompute(old); \9494+} \9595+rbstatic const struct rb_augment_callbacks rbname = { \9696+ rbname ## _propagate, rbname ## _copy, rbname ## _rotate \9797+};9898+9999+100100+#define RB_RED 0101101+#define RB_BLACK 1102102+103103+#define __rb_parent(pc) ((struct rb_node *)(pc & ~3))104104+105105+#define __rb_color(pc) ((pc) & 1)106106+#define __rb_is_black(pc) __rb_color(pc)107107+#define __rb_is_red(pc) (!__rb_color(pc))108108+#define rb_color(rb) __rb_color((rb)->__rb_parent_color)109109+#define rb_is_red(rb) __rb_is_red((rb)->__rb_parent_color)110110+#define rb_is_black(rb) __rb_is_black((rb)->__rb_parent_color)111111+112112+static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)113113+{114114+ rb->__rb_parent_color = rb_color(rb) | (unsigned long)p;115115+}116116+117117+static inline void rb_set_parent_color(struct rb_node *rb,118118+ struct rb_node *p, int color)119119+{120120+ rb->__rb_parent_color = (unsigned long)p | color;121121+}122122+123123+static inline void124124+__rb_change_child(struct rb_node *old, struct rb_node *new,125125+ struct rb_node *parent, struct rb_root *root)126126+{127127+ if (parent) {128128+ if (parent->rb_left == old)129129+ parent->rb_left = new;130130+ else131131+ parent->rb_right = new;132132+ } else133133+ root->rb_node = new;134134+}135135+136136+extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root,137137+ void (*augment_rotate)(struct rb_node *old, struct rb_node *new));138138+139139+static __always_inline struct rb_node *140140+__rb_erase_augmented(struct rb_node *node, struct rb_root *root,141141+ const struct rb_augment_callbacks *augment)142142+{143143+ struct rb_node *child = node->rb_right, *tmp = node->rb_left;144144+ struct rb_node *parent, *rebalance;145145+ unsigned long pc;146146+147147+ if (!tmp) {148148+ /*149149+ * Case 1: node to erase has no more than 1 child (easy!)150150+ *151151+ * Note that if there is one child it must be red due to 5)152152+ * and node must be black due to 4). We adjust colors locally153153+ * so as to bypass __rb_erase_color() later on.154154+ */155155+ pc = node->__rb_parent_color;156156+ parent = __rb_parent(pc);157157+ __rb_change_child(node, child, parent, root);158158+ if (child) {159159+ child->__rb_parent_color = pc;160160+ rebalance = NULL;161161+ } else162162+ rebalance = __rb_is_black(pc) ? parent : NULL;163163+ tmp = parent;164164+ } else if (!child) {165165+ /* Still case 1, but this time the child is node->rb_left */166166+ tmp->__rb_parent_color = pc = node->__rb_parent_color;167167+ parent = __rb_parent(pc);168168+ __rb_change_child(node, tmp, parent, root);169169+ rebalance = NULL;170170+ tmp = parent;171171+ } else {172172+ struct rb_node *successor = child, *child2;173173+ tmp = child->rb_left;174174+ if (!tmp) {175175+ /*176176+ * Case 2: node's successor is its right child177177+ *178178+ * (n) (s)179179+ * / \ / \180180+ * (x) (s) -> (x) (c)181181+ * \182182+ * (c)183183+ */184184+ parent = successor;185185+ child2 = successor->rb_right;186186+ augment->copy(node, successor);187187+ } else {188188+ /*189189+ * Case 3: node's successor is leftmost under190190+ * node's right child subtree191191+ *192192+ * (n) (s)193193+ * / \ / \194194+ * (x) (y) -> (x) (y)195195+ * / /196196+ * (p) (p)197197+ * / /198198+ * (s) (c)199199+ * \200200+ * (c)201201+ */202202+ do {203203+ parent = successor;204204+ successor = tmp;205205+ tmp = tmp->rb_left;206206+ } while (tmp);207207+ parent->rb_left = child2 = successor->rb_right;208208+ successor->rb_right = child;209209+ rb_set_parent(child, successor);210210+ augment->copy(node, successor);211211+ augment->propagate(parent, successor);212212+ }213213+214214+ successor->rb_left = tmp = node->rb_left;215215+ rb_set_parent(tmp, successor);216216+217217+ pc = node->__rb_parent_color;218218+ tmp = __rb_parent(pc);219219+ __rb_change_child(node, successor, tmp, root);220220+ if (child2) {221221+ successor->__rb_parent_color = pc;222222+ rb_set_parent_color(child2, parent, RB_BLACK);223223+ rebalance = NULL;224224+ } else {225225+ unsigned long pc2 = successor->__rb_parent_color;226226+ successor->__rb_parent_color = pc;227227+ rebalance = __rb_is_black(pc2) ? parent : NULL;228228+ }229229+ tmp = successor;230230+ }231231+232232+ augment->propagate(tmp, NULL);233233+ return rebalance;234234+}235235+236236+static __always_inline void237237+rb_erase_augmented(struct rb_node *node, struct rb_root *root,238238+ const struct rb_augment_callbacks *augment)239239+{240240+ struct rb_node *rebalance = __rb_erase_augmented(node, root, augment);241241+ if (rebalance)242242+ __rb_erase_color(rebalance, root, augment->rotate);243243+}244244+245245+#endif /* _TOOLS_LINUX_RBTREE_AUGMENTED_H */
+548
tools/lib/rbtree.c
···11+/*22+ Red Black Trees33+ (C) 1999 Andrea Arcangeli <andrea@suse.de>44+ (C) 2002 David Woodhouse <dwmw2@infradead.org>55+ (C) 2012 Michel Lespinasse <walken@google.com>66+77+ This program is free software; you can redistribute it and/or modify88+ it under the terms of the GNU General Public License as published by99+ the Free Software Foundation; either version 2 of the License, or1010+ (at your option) any later version.1111+1212+ This program is distributed in the hope that it will be useful,1313+ but WITHOUT ANY WARRANTY; without even the implied warranty of1414+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1515+ GNU General Public License for more details.1616+1717+ You should have received a copy of the GNU General Public License1818+ along with this program; if not, write to the Free Software1919+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA2020+2121+ linux/lib/rbtree.c2222+*/2323+2424+#include <linux/rbtree_augmented.h>2525+2626+/*2727+ * red-black trees properties: http://en.wikipedia.org/wiki/Rbtree2828+ *2929+ * 1) A node is either red or black3030+ * 2) The root is black3131+ * 3) All leaves (NULL) are black3232+ * 4) Both children of every red node are black3333+ * 5) Every simple path from root to leaves contains the same number3434+ * of black nodes.3535+ *3636+ * 4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two3737+ * consecutive red nodes in a path and every red node is therefore followed by3838+ * a black. So if B is the number of black nodes on every simple path (as per3939+ * 5), then the longest possible path due to 4 is 2B.4040+ *4141+ * We shall indicate color with case, where black nodes are uppercase and red4242+ * nodes will be lowercase. Unknown color nodes shall be drawn as red within4343+ * parentheses and have some accompanying text comment.4444+ */4545+4646+static inline void rb_set_black(struct rb_node *rb)4747+{4848+ rb->__rb_parent_color |= RB_BLACK;4949+}5050+5151+static inline struct rb_node *rb_red_parent(struct rb_node *red)5252+{5353+ return (struct rb_node *)red->__rb_parent_color;5454+}5555+5656+/*5757+ * Helper function for rotations:5858+ * - old's parent and color get assigned to new5959+ * - old gets assigned new as a parent and 'color' as a color.6060+ */6161+static inline void6262+__rb_rotate_set_parents(struct rb_node *old, struct rb_node *new,6363+ struct rb_root *root, int color)6464+{6565+ struct rb_node *parent = rb_parent(old);6666+ new->__rb_parent_color = old->__rb_parent_color;6767+ rb_set_parent_color(old, new, color);6868+ __rb_change_child(old, new, parent, root);6969+}7070+7171+static __always_inline void7272+__rb_insert(struct rb_node *node, struct rb_root *root,7373+ void (*augment_rotate)(struct rb_node *old, struct rb_node *new))7474+{7575+ struct rb_node *parent = rb_red_parent(node), *gparent, *tmp;7676+7777+ while (true) {7878+ /*7979+ * Loop invariant: node is red8080+ *8181+ * If there is a black parent, we are done.8282+ * Otherwise, take some corrective action as we don't8383+ * want a red root or two consecutive red nodes.8484+ */8585+ if (!parent) {8686+ rb_set_parent_color(node, NULL, RB_BLACK);8787+ break;8888+ } else if (rb_is_black(parent))8989+ break;9090+9191+ gparent = rb_red_parent(parent);9292+9393+ tmp = gparent->rb_right;9494+ if (parent != tmp) { /* parent == gparent->rb_left */9595+ if (tmp && rb_is_red(tmp)) {9696+ /*9797+ * Case 1 - color flips9898+ *9999+ * G g100100+ * / \ / \101101+ * p u --> P U102102+ * / /103103+ * n n104104+ *105105+ * However, since g's parent might be red, and106106+ * 4) does not allow this, we need to recurse107107+ * at g.108108+ */109109+ rb_set_parent_color(tmp, gparent, RB_BLACK);110110+ rb_set_parent_color(parent, gparent, RB_BLACK);111111+ node = gparent;112112+ parent = rb_parent(node);113113+ rb_set_parent_color(node, parent, RB_RED);114114+ continue;115115+ }116116+117117+ tmp = parent->rb_right;118118+ if (node == tmp) {119119+ /*120120+ * Case 2 - left rotate at parent121121+ *122122+ * G G123123+ * / \ / \124124+ * p U --> n U125125+ * \ /126126+ * n p127127+ *128128+ * This still leaves us in violation of 4), the129129+ * continuation into Case 3 will fix that.130130+ */131131+ parent->rb_right = tmp = node->rb_left;132132+ node->rb_left = parent;133133+ if (tmp)134134+ rb_set_parent_color(tmp, parent,135135+ RB_BLACK);136136+ rb_set_parent_color(parent, node, RB_RED);137137+ augment_rotate(parent, node);138138+ parent = node;139139+ tmp = node->rb_right;140140+ }141141+142142+ /*143143+ * Case 3 - right rotate at gparent144144+ *145145+ * G P146146+ * / \ / \147147+ * p U --> n g148148+ * / \149149+ * n U150150+ */151151+ gparent->rb_left = tmp; /* == parent->rb_right */152152+ parent->rb_right = gparent;153153+ if (tmp)154154+ rb_set_parent_color(tmp, gparent, RB_BLACK);155155+ __rb_rotate_set_parents(gparent, parent, root, RB_RED);156156+ augment_rotate(gparent, parent);157157+ break;158158+ } else {159159+ tmp = gparent->rb_left;160160+ if (tmp && rb_is_red(tmp)) {161161+ /* Case 1 - color flips */162162+ rb_set_parent_color(tmp, gparent, RB_BLACK);163163+ rb_set_parent_color(parent, gparent, RB_BLACK);164164+ node = gparent;165165+ parent = rb_parent(node);166166+ rb_set_parent_color(node, parent, RB_RED);167167+ continue;168168+ }169169+170170+ tmp = parent->rb_left;171171+ if (node == tmp) {172172+ /* Case 2 - right rotate at parent */173173+ parent->rb_left = tmp = node->rb_right;174174+ node->rb_right = parent;175175+ if (tmp)176176+ rb_set_parent_color(tmp, parent,177177+ RB_BLACK);178178+ rb_set_parent_color(parent, node, RB_RED);179179+ augment_rotate(parent, node);180180+ parent = node;181181+ tmp = node->rb_left;182182+ }183183+184184+ /* Case 3 - left rotate at gparent */185185+ gparent->rb_right = tmp; /* == parent->rb_left */186186+ parent->rb_left = gparent;187187+ if (tmp)188188+ rb_set_parent_color(tmp, gparent, RB_BLACK);189189+ __rb_rotate_set_parents(gparent, parent, root, RB_RED);190190+ augment_rotate(gparent, parent);191191+ break;192192+ }193193+ }194194+}195195+196196+/*197197+ * Inline version for rb_erase() use - we want to be able to inline198198+ * and eliminate the dummy_rotate callback there199199+ */200200+static __always_inline void201201+____rb_erase_color(struct rb_node *parent, struct rb_root *root,202202+ void (*augment_rotate)(struct rb_node *old, struct rb_node *new))203203+{204204+ struct rb_node *node = NULL, *sibling, *tmp1, *tmp2;205205+206206+ while (true) {207207+ /*208208+ * Loop invariants:209209+ * - node is black (or NULL on first iteration)210210+ * - node is not the root (parent is not NULL)211211+ * - All leaf paths going through parent and node have a212212+ * black node count that is 1 lower than other leaf paths.213213+ */214214+ sibling = parent->rb_right;215215+ if (node != sibling) { /* node == parent->rb_left */216216+ if (rb_is_red(sibling)) {217217+ /*218218+ * Case 1 - left rotate at parent219219+ *220220+ * P S221221+ * / \ / \222222+ * N s --> p Sr223223+ * / \ / \224224+ * Sl Sr N Sl225225+ */226226+ parent->rb_right = tmp1 = sibling->rb_left;227227+ sibling->rb_left = parent;228228+ rb_set_parent_color(tmp1, parent, RB_BLACK);229229+ __rb_rotate_set_parents(parent, sibling, root,230230+ RB_RED);231231+ augment_rotate(parent, sibling);232232+ sibling = tmp1;233233+ }234234+ tmp1 = sibling->rb_right;235235+ if (!tmp1 || rb_is_black(tmp1)) {236236+ tmp2 = sibling->rb_left;237237+ if (!tmp2 || rb_is_black(tmp2)) {238238+ /*239239+ * Case 2 - sibling color flip240240+ * (p could be either color here)241241+ *242242+ * (p) (p)243243+ * / \ / \244244+ * N S --> N s245245+ * / \ / \246246+ * Sl Sr Sl Sr247247+ *248248+ * This leaves us violating 5) which249249+ * can be fixed by flipping p to black250250+ * if it was red, or by recursing at p.251251+ * p is red when coming from Case 1.252252+ */253253+ rb_set_parent_color(sibling, parent,254254+ RB_RED);255255+ if (rb_is_red(parent))256256+ rb_set_black(parent);257257+ else {258258+ node = parent;259259+ parent = rb_parent(node);260260+ if (parent)261261+ continue;262262+ }263263+ break;264264+ }265265+ /*266266+ * Case 3 - right rotate at sibling267267+ * (p could be either color here)268268+ *269269+ * (p) (p)270270+ * / \ / \271271+ * N S --> N Sl272272+ * / \ \273273+ * sl Sr s274274+ * \275275+ * Sr276276+ */277277+ sibling->rb_left = tmp1 = tmp2->rb_right;278278+ tmp2->rb_right = sibling;279279+ parent->rb_right = tmp2;280280+ if (tmp1)281281+ rb_set_parent_color(tmp1, sibling,282282+ RB_BLACK);283283+ augment_rotate(sibling, tmp2);284284+ tmp1 = sibling;285285+ sibling = tmp2;286286+ }287287+ /*288288+ * Case 4 - left rotate at parent + color flips289289+ * (p and sl could be either color here.290290+ * After rotation, p becomes black, s acquires291291+ * p's color, and sl keeps its color)292292+ *293293+ * (p) (s)294294+ * / \ / \295295+ * N S --> P Sr296296+ * / \ / \297297+ * (sl) sr N (sl)298298+ */299299+ parent->rb_right = tmp2 = sibling->rb_left;300300+ sibling->rb_left = parent;301301+ rb_set_parent_color(tmp1, sibling, RB_BLACK);302302+ if (tmp2)303303+ rb_set_parent(tmp2, parent);304304+ __rb_rotate_set_parents(parent, sibling, root,305305+ RB_BLACK);306306+ augment_rotate(parent, sibling);307307+ break;308308+ } else {309309+ sibling = parent->rb_left;310310+ if (rb_is_red(sibling)) {311311+ /* Case 1 - right rotate at parent */312312+ parent->rb_left = tmp1 = sibling->rb_right;313313+ sibling->rb_right = parent;314314+ rb_set_parent_color(tmp1, parent, RB_BLACK);315315+ __rb_rotate_set_parents(parent, sibling, root,316316+ RB_RED);317317+ augment_rotate(parent, sibling);318318+ sibling = tmp1;319319+ }320320+ tmp1 = sibling->rb_left;321321+ if (!tmp1 || rb_is_black(tmp1)) {322322+ tmp2 = sibling->rb_right;323323+ if (!tmp2 || rb_is_black(tmp2)) {324324+ /* Case 2 - sibling color flip */325325+ rb_set_parent_color(sibling, parent,326326+ RB_RED);327327+ if (rb_is_red(parent))328328+ rb_set_black(parent);329329+ else {330330+ node = parent;331331+ parent = rb_parent(node);332332+ if (parent)333333+ continue;334334+ }335335+ break;336336+ }337337+ /* Case 3 - right rotate at sibling */338338+ sibling->rb_right = tmp1 = tmp2->rb_left;339339+ tmp2->rb_left = sibling;340340+ parent->rb_left = tmp2;341341+ if (tmp1)342342+ rb_set_parent_color(tmp1, sibling,343343+ RB_BLACK);344344+ augment_rotate(sibling, tmp2);345345+ tmp1 = sibling;346346+ sibling = tmp2;347347+ }348348+ /* Case 4 - left rotate at parent + color flips */349349+ parent->rb_left = tmp2 = sibling->rb_right;350350+ sibling->rb_right = parent;351351+ rb_set_parent_color(tmp1, sibling, RB_BLACK);352352+ if (tmp2)353353+ rb_set_parent(tmp2, parent);354354+ __rb_rotate_set_parents(parent, sibling, root,355355+ RB_BLACK);356356+ augment_rotate(parent, sibling);357357+ break;358358+ }359359+ }360360+}361361+362362+/* Non-inline version for rb_erase_augmented() use */363363+void __rb_erase_color(struct rb_node *parent, struct rb_root *root,364364+ void (*augment_rotate)(struct rb_node *old, struct rb_node *new))365365+{366366+ ____rb_erase_color(parent, root, augment_rotate);367367+}368368+369369+/*370370+ * Non-augmented rbtree manipulation functions.371371+ *372372+ * We use dummy augmented callbacks here, and have the compiler optimize them373373+ * out of the rb_insert_color() and rb_erase() function definitions.374374+ */375375+376376+static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {}377377+static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {}378378+static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {}379379+380380+static const struct rb_augment_callbacks dummy_callbacks = {381381+ dummy_propagate, dummy_copy, dummy_rotate382382+};383383+384384+void rb_insert_color(struct rb_node *node, struct rb_root *root)385385+{386386+ __rb_insert(node, root, dummy_rotate);387387+}388388+389389+void rb_erase(struct rb_node *node, struct rb_root *root)390390+{391391+ struct rb_node *rebalance;392392+ rebalance = __rb_erase_augmented(node, root, &dummy_callbacks);393393+ if (rebalance)394394+ ____rb_erase_color(rebalance, root, dummy_rotate);395395+}396396+397397+/*398398+ * Augmented rbtree manipulation functions.399399+ *400400+ * This instantiates the same __always_inline functions as in the non-augmented401401+ * case, but this time with user-defined callbacks.402402+ */403403+404404+void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,405405+ void (*augment_rotate)(struct rb_node *old, struct rb_node *new))406406+{407407+ __rb_insert(node, root, augment_rotate);408408+}409409+410410+/*411411+ * This function returns the first node (in sort order) of the tree.412412+ */413413+struct rb_node *rb_first(const struct rb_root *root)414414+{415415+ struct rb_node *n;416416+417417+ n = root->rb_node;418418+ if (!n)419419+ return NULL;420420+ while (n->rb_left)421421+ n = n->rb_left;422422+ return n;423423+}424424+425425+struct rb_node *rb_last(const struct rb_root *root)426426+{427427+ struct rb_node *n;428428+429429+ n = root->rb_node;430430+ if (!n)431431+ return NULL;432432+ while (n->rb_right)433433+ n = n->rb_right;434434+ return n;435435+}436436+437437+struct rb_node *rb_next(const struct rb_node *node)438438+{439439+ struct rb_node *parent;440440+441441+ if (RB_EMPTY_NODE(node))442442+ return NULL;443443+444444+ /*445445+ * If we have a right-hand child, go down and then left as far446446+ * as we can.447447+ */448448+ if (node->rb_right) {449449+ node = node->rb_right;450450+ while (node->rb_left)451451+ node=node->rb_left;452452+ return (struct rb_node *)node;453453+ }454454+455455+ /*456456+ * No right-hand children. Everything down and left is smaller than us,457457+ * so any 'next' node must be in the general direction of our parent.458458+ * Go up the tree; any time the ancestor is a right-hand child of its459459+ * parent, keep going up. First time it's a left-hand child of its460460+ * parent, said parent is our 'next' node.461461+ */462462+ while ((parent = rb_parent(node)) && node == parent->rb_right)463463+ node = parent;464464+465465+ return parent;466466+}467467+468468+struct rb_node *rb_prev(const struct rb_node *node)469469+{470470+ struct rb_node *parent;471471+472472+ if (RB_EMPTY_NODE(node))473473+ return NULL;474474+475475+ /*476476+ * If we have a left-hand child, go down and then right as far477477+ * as we can.478478+ */479479+ if (node->rb_left) {480480+ node = node->rb_left;481481+ while (node->rb_right)482482+ node=node->rb_right;483483+ return (struct rb_node *)node;484484+ }485485+486486+ /*487487+ * No left-hand children. Go up till we find an ancestor which488488+ * is a right-hand child of its parent.489489+ */490490+ while ((parent = rb_parent(node)) && node == parent->rb_left)491491+ node = parent;492492+493493+ return parent;494494+}495495+496496+void rb_replace_node(struct rb_node *victim, struct rb_node *new,497497+ struct rb_root *root)498498+{499499+ struct rb_node *parent = rb_parent(victim);500500+501501+ /* Set the surrounding nodes to point to the replacement */502502+ __rb_change_child(victim, new, parent, root);503503+ if (victim->rb_left)504504+ rb_set_parent(victim->rb_left, new);505505+ if (victim->rb_right)506506+ rb_set_parent(victim->rb_right, new);507507+508508+ /* Copy the pointers/colour from the victim to the replacement */509509+ *new = *victim;510510+}511511+512512+static struct rb_node *rb_left_deepest_node(const struct rb_node *node)513513+{514514+ for (;;) {515515+ if (node->rb_left)516516+ node = node->rb_left;517517+ else if (node->rb_right)518518+ node = node->rb_right;519519+ else520520+ return (struct rb_node *)node;521521+ }522522+}523523+524524+struct rb_node *rb_next_postorder(const struct rb_node *node)525525+{526526+ const struct rb_node *parent;527527+ if (!node)528528+ return NULL;529529+ parent = rb_parent(node);530530+531531+ /* If we're sitting on node, we've already seen our children */532532+ if (parent && node == parent->rb_left && parent->rb_right) {533533+ /* If we are the parent's left node, go to the parent's right534534+ * node then all the way down to the left */535535+ return rb_left_deepest_node(parent->rb_right);536536+ } else537537+ /* Otherwise we are the parent's right node, and the parent538538+ * should be next */539539+ return (struct rb_node *)parent;540540+}541541+542542+struct rb_node *rb_first_postorder(const struct rb_root *root)543543+{544544+ if (!root->rb_node)545545+ return NULL;546546+547547+ return rb_left_deepest_node(root->rb_node);548548+}
···11-#ifndef __TOOLS_LINUX_PERF_RBTREE_H22-#define __TOOLS_LINUX_PERF_RBTREE_H33-#include <stdbool.h>44-#include "../../../../include/linux/rbtree.h"55-66-/*77- * Handy for checking that we are not deleting an entry that is88- * already in a list, found in block/{blk-throttle,cfq-iosched}.c,99- * probably should be moved to lib/rbtree.c...1010- */1111-static inline void rb_erase_init(struct rb_node *n, struct rb_root *root)1212-{1313- rb_erase(n, root);1414- RB_CLEAR_NODE(n);1515-}1616-#endif /* __TOOLS_LINUX_PERF_RBTREE_H */