/src/haproxy/include/import/eb64tree.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Elastic Binary Trees - macros and structures for operations on 64bit nodes. |
3 | | * Version 6.0.6 |
4 | | * (C) 2002-2011 - Willy Tarreau <w@1wt.eu> |
5 | | * |
6 | | * This library is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation, version 2.1 |
9 | | * exclusively. |
10 | | * |
11 | | * This library is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with this library; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | |
21 | | #ifndef _EB64TREE_H |
22 | | #define _EB64TREE_H |
23 | | |
24 | | #include "ebtree.h" |
25 | | |
26 | | |
27 | | /* Return the structure of type <type> whose member <member> points to <ptr> */ |
28 | 0 | #define eb64_entry(ptr, type, member) container_of(ptr, type, member) |
29 | | |
30 | | /* |
31 | | * Exported functions and macros. |
32 | | * Many of them are always inlined because they are extremely small, and |
33 | | * are generally called at most once or twice in a program. |
34 | | */ |
35 | | |
36 | | /* Return leftmost node in the tree, or NULL if none */ |
37 | | static inline struct eb64_node *eb64_first(struct eb_root *root) |
38 | 0 | { |
39 | 0 | return eb64_entry(eb_first(root), struct eb64_node, node); |
40 | 0 | } Unexecuted instantiation: cfgparse.c:eb64_first Unexecuted instantiation: connection.c:eb64_first Unexecuted instantiation: eb64tree.c:eb64_first Unexecuted instantiation: ebistree.c:eb64_first Unexecuted instantiation: filters.c:eb64_first Unexecuted instantiation: flt_http_comp.c:eb64_first Unexecuted instantiation: haproxy.c:eb64_first Unexecuted instantiation: http_ana.c:eb64_first Unexecuted instantiation: http_ext.c:eb64_first Unexecuted instantiation: http_htx.c:eb64_first Unexecuted instantiation: peers.c:eb64_first Unexecuted instantiation: proxy.c:eb64_first Unexecuted instantiation: resolvers.c:eb64_first Unexecuted instantiation: server.c:eb64_first Unexecuted instantiation: sock.c:eb64_first Unexecuted instantiation: sock_inet.c:eb64_first Unexecuted instantiation: stats.c:eb64_first Unexecuted instantiation: stick_table.c:eb64_first Unexecuted instantiation: stream.c:eb64_first Unexecuted instantiation: tcpcheck.c:eb64_first Unexecuted instantiation: tools.c:eb64_first Unexecuted instantiation: backend.c:eb64_first Unexecuted instantiation: cache.c:eb64_first Unexecuted instantiation: cfgparse-listen.c:eb64_first Unexecuted instantiation: check.c:eb64_first Unexecuted instantiation: dict.c:eb64_first Unexecuted instantiation: ebimtree.c:eb64_first Unexecuted instantiation: fcgi-app.c:eb64_first Unexecuted instantiation: http_fetch.c:eb64_first Unexecuted instantiation: pattern.c:eb64_first Unexecuted instantiation: h1_htx.c:eb64_first Unexecuted instantiation: lru.c:eb64_first |
41 | | |
42 | | /* Return rightmost node in the tree, or NULL if none */ |
43 | | static inline struct eb64_node *eb64_last(struct eb_root *root) |
44 | 0 | { |
45 | 0 | return eb64_entry(eb_last(root), struct eb64_node, node); |
46 | 0 | } Unexecuted instantiation: cfgparse.c:eb64_last Unexecuted instantiation: connection.c:eb64_last Unexecuted instantiation: eb64tree.c:eb64_last Unexecuted instantiation: ebistree.c:eb64_last Unexecuted instantiation: filters.c:eb64_last Unexecuted instantiation: flt_http_comp.c:eb64_last Unexecuted instantiation: haproxy.c:eb64_last Unexecuted instantiation: http_ana.c:eb64_last Unexecuted instantiation: http_ext.c:eb64_last Unexecuted instantiation: http_htx.c:eb64_last Unexecuted instantiation: peers.c:eb64_last Unexecuted instantiation: proxy.c:eb64_last Unexecuted instantiation: resolvers.c:eb64_last Unexecuted instantiation: server.c:eb64_last Unexecuted instantiation: sock.c:eb64_last Unexecuted instantiation: sock_inet.c:eb64_last Unexecuted instantiation: stats.c:eb64_last Unexecuted instantiation: stick_table.c:eb64_last Unexecuted instantiation: stream.c:eb64_last Unexecuted instantiation: tcpcheck.c:eb64_last Unexecuted instantiation: tools.c:eb64_last Unexecuted instantiation: backend.c:eb64_last Unexecuted instantiation: cache.c:eb64_last Unexecuted instantiation: cfgparse-listen.c:eb64_last Unexecuted instantiation: check.c:eb64_last Unexecuted instantiation: dict.c:eb64_last Unexecuted instantiation: ebimtree.c:eb64_last Unexecuted instantiation: fcgi-app.c:eb64_last Unexecuted instantiation: http_fetch.c:eb64_last Unexecuted instantiation: pattern.c:eb64_last Unexecuted instantiation: h1_htx.c:eb64_last Unexecuted instantiation: lru.c:eb64_last |
47 | | |
48 | | /* Return next node in the tree, or NULL if none */ |
49 | | static inline struct eb64_node *eb64_next(struct eb64_node *eb64) |
50 | 0 | { |
51 | 0 | return eb64_entry(eb_next(&eb64->node), struct eb64_node, node); |
52 | 0 | } Unexecuted instantiation: cfgparse.c:eb64_next Unexecuted instantiation: connection.c:eb64_next Unexecuted instantiation: eb64tree.c:eb64_next Unexecuted instantiation: ebistree.c:eb64_next Unexecuted instantiation: filters.c:eb64_next Unexecuted instantiation: flt_http_comp.c:eb64_next Unexecuted instantiation: haproxy.c:eb64_next Unexecuted instantiation: http_ana.c:eb64_next Unexecuted instantiation: http_ext.c:eb64_next Unexecuted instantiation: http_htx.c:eb64_next Unexecuted instantiation: peers.c:eb64_next Unexecuted instantiation: proxy.c:eb64_next Unexecuted instantiation: resolvers.c:eb64_next Unexecuted instantiation: server.c:eb64_next Unexecuted instantiation: sock.c:eb64_next Unexecuted instantiation: sock_inet.c:eb64_next Unexecuted instantiation: stats.c:eb64_next Unexecuted instantiation: stick_table.c:eb64_next Unexecuted instantiation: stream.c:eb64_next Unexecuted instantiation: tcpcheck.c:eb64_next Unexecuted instantiation: tools.c:eb64_next Unexecuted instantiation: backend.c:eb64_next Unexecuted instantiation: cache.c:eb64_next Unexecuted instantiation: cfgparse-listen.c:eb64_next Unexecuted instantiation: check.c:eb64_next Unexecuted instantiation: dict.c:eb64_next Unexecuted instantiation: ebimtree.c:eb64_next Unexecuted instantiation: fcgi-app.c:eb64_next Unexecuted instantiation: http_fetch.c:eb64_next Unexecuted instantiation: pattern.c:eb64_next Unexecuted instantiation: h1_htx.c:eb64_next Unexecuted instantiation: lru.c:eb64_next |
53 | | |
54 | | /* Return previous node in the tree, or NULL if none */ |
55 | | static inline struct eb64_node *eb64_prev(struct eb64_node *eb64) |
56 | 0 | { |
57 | 0 | return eb64_entry(eb_prev(&eb64->node), struct eb64_node, node); |
58 | 0 | } Unexecuted instantiation: cfgparse.c:eb64_prev Unexecuted instantiation: connection.c:eb64_prev Unexecuted instantiation: eb64tree.c:eb64_prev Unexecuted instantiation: ebistree.c:eb64_prev Unexecuted instantiation: filters.c:eb64_prev Unexecuted instantiation: flt_http_comp.c:eb64_prev Unexecuted instantiation: haproxy.c:eb64_prev Unexecuted instantiation: http_ana.c:eb64_prev Unexecuted instantiation: http_ext.c:eb64_prev Unexecuted instantiation: http_htx.c:eb64_prev Unexecuted instantiation: peers.c:eb64_prev Unexecuted instantiation: proxy.c:eb64_prev Unexecuted instantiation: resolvers.c:eb64_prev Unexecuted instantiation: server.c:eb64_prev Unexecuted instantiation: sock.c:eb64_prev Unexecuted instantiation: sock_inet.c:eb64_prev Unexecuted instantiation: stats.c:eb64_prev Unexecuted instantiation: stick_table.c:eb64_prev Unexecuted instantiation: stream.c:eb64_prev Unexecuted instantiation: tcpcheck.c:eb64_prev Unexecuted instantiation: tools.c:eb64_prev Unexecuted instantiation: backend.c:eb64_prev Unexecuted instantiation: cache.c:eb64_prev Unexecuted instantiation: cfgparse-listen.c:eb64_prev Unexecuted instantiation: check.c:eb64_prev Unexecuted instantiation: dict.c:eb64_prev Unexecuted instantiation: ebimtree.c:eb64_prev Unexecuted instantiation: fcgi-app.c:eb64_prev Unexecuted instantiation: http_fetch.c:eb64_prev Unexecuted instantiation: pattern.c:eb64_prev Unexecuted instantiation: h1_htx.c:eb64_prev Unexecuted instantiation: lru.c:eb64_prev |
59 | | |
60 | | /* Return next leaf node within a duplicate sub-tree, or NULL if none. */ |
61 | | static inline struct eb64_node *eb64_next_dup(struct eb64_node *eb64) |
62 | 0 | { |
63 | 0 | return eb64_entry(eb_next_dup(&eb64->node), struct eb64_node, node); |
64 | 0 | } Unexecuted instantiation: cfgparse.c:eb64_next_dup Unexecuted instantiation: connection.c:eb64_next_dup Unexecuted instantiation: eb64tree.c:eb64_next_dup Unexecuted instantiation: ebistree.c:eb64_next_dup Unexecuted instantiation: filters.c:eb64_next_dup Unexecuted instantiation: flt_http_comp.c:eb64_next_dup Unexecuted instantiation: haproxy.c:eb64_next_dup Unexecuted instantiation: http_ana.c:eb64_next_dup Unexecuted instantiation: http_ext.c:eb64_next_dup Unexecuted instantiation: http_htx.c:eb64_next_dup Unexecuted instantiation: peers.c:eb64_next_dup Unexecuted instantiation: proxy.c:eb64_next_dup Unexecuted instantiation: resolvers.c:eb64_next_dup Unexecuted instantiation: server.c:eb64_next_dup Unexecuted instantiation: sock.c:eb64_next_dup Unexecuted instantiation: sock_inet.c:eb64_next_dup Unexecuted instantiation: stats.c:eb64_next_dup Unexecuted instantiation: stick_table.c:eb64_next_dup Unexecuted instantiation: stream.c:eb64_next_dup Unexecuted instantiation: tcpcheck.c:eb64_next_dup Unexecuted instantiation: tools.c:eb64_next_dup Unexecuted instantiation: backend.c:eb64_next_dup Unexecuted instantiation: cache.c:eb64_next_dup Unexecuted instantiation: cfgparse-listen.c:eb64_next_dup Unexecuted instantiation: check.c:eb64_next_dup Unexecuted instantiation: dict.c:eb64_next_dup Unexecuted instantiation: ebimtree.c:eb64_next_dup Unexecuted instantiation: fcgi-app.c:eb64_next_dup Unexecuted instantiation: http_fetch.c:eb64_next_dup Unexecuted instantiation: pattern.c:eb64_next_dup Unexecuted instantiation: h1_htx.c:eb64_next_dup Unexecuted instantiation: lru.c:eb64_next_dup |
65 | | |
66 | | /* Return previous leaf node within a duplicate sub-tree, or NULL if none. */ |
67 | | static inline struct eb64_node *eb64_prev_dup(struct eb64_node *eb64) |
68 | 0 | { |
69 | 0 | return eb64_entry(eb_prev_dup(&eb64->node), struct eb64_node, node); |
70 | 0 | } Unexecuted instantiation: cfgparse.c:eb64_prev_dup Unexecuted instantiation: connection.c:eb64_prev_dup Unexecuted instantiation: eb64tree.c:eb64_prev_dup Unexecuted instantiation: ebistree.c:eb64_prev_dup Unexecuted instantiation: filters.c:eb64_prev_dup Unexecuted instantiation: flt_http_comp.c:eb64_prev_dup Unexecuted instantiation: haproxy.c:eb64_prev_dup Unexecuted instantiation: http_ana.c:eb64_prev_dup Unexecuted instantiation: http_ext.c:eb64_prev_dup Unexecuted instantiation: http_htx.c:eb64_prev_dup Unexecuted instantiation: peers.c:eb64_prev_dup Unexecuted instantiation: proxy.c:eb64_prev_dup Unexecuted instantiation: resolvers.c:eb64_prev_dup Unexecuted instantiation: server.c:eb64_prev_dup Unexecuted instantiation: sock.c:eb64_prev_dup Unexecuted instantiation: sock_inet.c:eb64_prev_dup Unexecuted instantiation: stats.c:eb64_prev_dup Unexecuted instantiation: stick_table.c:eb64_prev_dup Unexecuted instantiation: stream.c:eb64_prev_dup Unexecuted instantiation: tcpcheck.c:eb64_prev_dup Unexecuted instantiation: tools.c:eb64_prev_dup Unexecuted instantiation: backend.c:eb64_prev_dup Unexecuted instantiation: cache.c:eb64_prev_dup Unexecuted instantiation: cfgparse-listen.c:eb64_prev_dup Unexecuted instantiation: check.c:eb64_prev_dup Unexecuted instantiation: dict.c:eb64_prev_dup Unexecuted instantiation: ebimtree.c:eb64_prev_dup Unexecuted instantiation: fcgi-app.c:eb64_prev_dup Unexecuted instantiation: http_fetch.c:eb64_prev_dup Unexecuted instantiation: pattern.c:eb64_prev_dup Unexecuted instantiation: h1_htx.c:eb64_prev_dup Unexecuted instantiation: lru.c:eb64_prev_dup |
71 | | |
72 | | /* Return next node in the tree, skipping duplicates, or NULL if none */ |
73 | | static inline struct eb64_node *eb64_next_unique(struct eb64_node *eb64) |
74 | 0 | { |
75 | 0 | return eb64_entry(eb_next_unique(&eb64->node), struct eb64_node, node); |
76 | 0 | } Unexecuted instantiation: cfgparse.c:eb64_next_unique Unexecuted instantiation: connection.c:eb64_next_unique Unexecuted instantiation: eb64tree.c:eb64_next_unique Unexecuted instantiation: ebistree.c:eb64_next_unique Unexecuted instantiation: filters.c:eb64_next_unique Unexecuted instantiation: flt_http_comp.c:eb64_next_unique Unexecuted instantiation: haproxy.c:eb64_next_unique Unexecuted instantiation: http_ana.c:eb64_next_unique Unexecuted instantiation: http_ext.c:eb64_next_unique Unexecuted instantiation: http_htx.c:eb64_next_unique Unexecuted instantiation: peers.c:eb64_next_unique Unexecuted instantiation: proxy.c:eb64_next_unique Unexecuted instantiation: resolvers.c:eb64_next_unique Unexecuted instantiation: server.c:eb64_next_unique Unexecuted instantiation: sock.c:eb64_next_unique Unexecuted instantiation: sock_inet.c:eb64_next_unique Unexecuted instantiation: stats.c:eb64_next_unique Unexecuted instantiation: stick_table.c:eb64_next_unique Unexecuted instantiation: stream.c:eb64_next_unique Unexecuted instantiation: tcpcheck.c:eb64_next_unique Unexecuted instantiation: tools.c:eb64_next_unique Unexecuted instantiation: backend.c:eb64_next_unique Unexecuted instantiation: cache.c:eb64_next_unique Unexecuted instantiation: cfgparse-listen.c:eb64_next_unique Unexecuted instantiation: check.c:eb64_next_unique Unexecuted instantiation: dict.c:eb64_next_unique Unexecuted instantiation: ebimtree.c:eb64_next_unique Unexecuted instantiation: fcgi-app.c:eb64_next_unique Unexecuted instantiation: http_fetch.c:eb64_next_unique Unexecuted instantiation: pattern.c:eb64_next_unique Unexecuted instantiation: h1_htx.c:eb64_next_unique Unexecuted instantiation: lru.c:eb64_next_unique |
77 | | |
78 | | /* Return previous node in the tree, skipping duplicates, or NULL if none */ |
79 | | static inline struct eb64_node *eb64_prev_unique(struct eb64_node *eb64) |
80 | 0 | { |
81 | 0 | return eb64_entry(eb_prev_unique(&eb64->node), struct eb64_node, node); |
82 | 0 | } Unexecuted instantiation: cfgparse.c:eb64_prev_unique Unexecuted instantiation: connection.c:eb64_prev_unique Unexecuted instantiation: eb64tree.c:eb64_prev_unique Unexecuted instantiation: ebistree.c:eb64_prev_unique Unexecuted instantiation: filters.c:eb64_prev_unique Unexecuted instantiation: flt_http_comp.c:eb64_prev_unique Unexecuted instantiation: haproxy.c:eb64_prev_unique Unexecuted instantiation: http_ana.c:eb64_prev_unique Unexecuted instantiation: http_ext.c:eb64_prev_unique Unexecuted instantiation: http_htx.c:eb64_prev_unique Unexecuted instantiation: peers.c:eb64_prev_unique Unexecuted instantiation: proxy.c:eb64_prev_unique Unexecuted instantiation: resolvers.c:eb64_prev_unique Unexecuted instantiation: server.c:eb64_prev_unique Unexecuted instantiation: sock.c:eb64_prev_unique Unexecuted instantiation: sock_inet.c:eb64_prev_unique Unexecuted instantiation: stats.c:eb64_prev_unique Unexecuted instantiation: stick_table.c:eb64_prev_unique Unexecuted instantiation: stream.c:eb64_prev_unique Unexecuted instantiation: tcpcheck.c:eb64_prev_unique Unexecuted instantiation: tools.c:eb64_prev_unique Unexecuted instantiation: backend.c:eb64_prev_unique Unexecuted instantiation: cache.c:eb64_prev_unique Unexecuted instantiation: cfgparse-listen.c:eb64_prev_unique Unexecuted instantiation: check.c:eb64_prev_unique Unexecuted instantiation: dict.c:eb64_prev_unique Unexecuted instantiation: ebimtree.c:eb64_prev_unique Unexecuted instantiation: fcgi-app.c:eb64_prev_unique Unexecuted instantiation: http_fetch.c:eb64_prev_unique Unexecuted instantiation: pattern.c:eb64_prev_unique Unexecuted instantiation: h1_htx.c:eb64_prev_unique Unexecuted instantiation: lru.c:eb64_prev_unique |
83 | | |
84 | | /* Delete node from the tree if it was linked in. Mark the node unused. Note |
85 | | * that this function relies on a non-inlined generic function: eb_delete. |
86 | | */ |
87 | | static inline void eb64_delete(struct eb64_node *eb64) |
88 | 0 | { |
89 | 0 | eb_delete(&eb64->node); |
90 | 0 | } Unexecuted instantiation: cfgparse.c:eb64_delete Unexecuted instantiation: connection.c:eb64_delete Unexecuted instantiation: eb64tree.c:eb64_delete Unexecuted instantiation: ebistree.c:eb64_delete Unexecuted instantiation: filters.c:eb64_delete Unexecuted instantiation: flt_http_comp.c:eb64_delete Unexecuted instantiation: haproxy.c:eb64_delete Unexecuted instantiation: http_ana.c:eb64_delete Unexecuted instantiation: http_ext.c:eb64_delete Unexecuted instantiation: http_htx.c:eb64_delete Unexecuted instantiation: peers.c:eb64_delete Unexecuted instantiation: proxy.c:eb64_delete Unexecuted instantiation: resolvers.c:eb64_delete Unexecuted instantiation: server.c:eb64_delete Unexecuted instantiation: sock.c:eb64_delete Unexecuted instantiation: sock_inet.c:eb64_delete Unexecuted instantiation: stats.c:eb64_delete Unexecuted instantiation: stick_table.c:eb64_delete Unexecuted instantiation: stream.c:eb64_delete Unexecuted instantiation: tcpcheck.c:eb64_delete Unexecuted instantiation: tools.c:eb64_delete Unexecuted instantiation: backend.c:eb64_delete Unexecuted instantiation: cache.c:eb64_delete Unexecuted instantiation: cfgparse-listen.c:eb64_delete Unexecuted instantiation: check.c:eb64_delete Unexecuted instantiation: dict.c:eb64_delete Unexecuted instantiation: ebimtree.c:eb64_delete Unexecuted instantiation: fcgi-app.c:eb64_delete Unexecuted instantiation: http_fetch.c:eb64_delete Unexecuted instantiation: pattern.c:eb64_delete Unexecuted instantiation: h1_htx.c:eb64_delete Unexecuted instantiation: lru.c:eb64_delete |
91 | | |
92 | | /* |
93 | | * The following functions are not inlined by default. They are declared |
94 | | * in eb64tree.c, which simply relies on their inline version. |
95 | | */ |
96 | | struct eb64_node *eb64_lookup(struct eb_root *root, u64 x); |
97 | | struct eb64_node *eb64i_lookup(struct eb_root *root, s64 x); |
98 | | struct eb64_node *eb64_lookup_le(struct eb_root *root, u64 x); |
99 | | struct eb64_node *eb64_lookup_ge(struct eb_root *root, u64 x); |
100 | | struct eb64_node *eb64_insert(struct eb_root *root, struct eb64_node *new); |
101 | | struct eb64_node *eb64i_insert(struct eb_root *root, struct eb64_node *new); |
102 | | |
103 | | /* |
104 | | * The following functions are less likely to be used directly, because their |
105 | | * code is larger. The non-inlined version is preferred. |
106 | | */ |
107 | | |
108 | | /* Delete node from the tree if it was linked in. Mark the node unused. */ |
109 | | static forceinline void __eb64_delete(struct eb64_node *eb64) |
110 | 0 | { |
111 | 0 | __eb_delete(&eb64->node); |
112 | 0 | } Unexecuted instantiation: cfgparse.c:__eb64_delete Unexecuted instantiation: connection.c:__eb64_delete Unexecuted instantiation: eb64tree.c:__eb64_delete Unexecuted instantiation: ebistree.c:__eb64_delete Unexecuted instantiation: filters.c:__eb64_delete Unexecuted instantiation: flt_http_comp.c:__eb64_delete Unexecuted instantiation: haproxy.c:__eb64_delete Unexecuted instantiation: http_ana.c:__eb64_delete Unexecuted instantiation: http_ext.c:__eb64_delete Unexecuted instantiation: http_htx.c:__eb64_delete Unexecuted instantiation: peers.c:__eb64_delete Unexecuted instantiation: proxy.c:__eb64_delete Unexecuted instantiation: resolvers.c:__eb64_delete Unexecuted instantiation: server.c:__eb64_delete Unexecuted instantiation: sock.c:__eb64_delete Unexecuted instantiation: sock_inet.c:__eb64_delete Unexecuted instantiation: stats.c:__eb64_delete Unexecuted instantiation: stick_table.c:__eb64_delete Unexecuted instantiation: stream.c:__eb64_delete Unexecuted instantiation: tcpcheck.c:__eb64_delete Unexecuted instantiation: tools.c:__eb64_delete Unexecuted instantiation: backend.c:__eb64_delete Unexecuted instantiation: cache.c:__eb64_delete Unexecuted instantiation: cfgparse-listen.c:__eb64_delete Unexecuted instantiation: check.c:__eb64_delete Unexecuted instantiation: dict.c:__eb64_delete Unexecuted instantiation: ebimtree.c:__eb64_delete Unexecuted instantiation: fcgi-app.c:__eb64_delete Unexecuted instantiation: http_fetch.c:__eb64_delete Unexecuted instantiation: pattern.c:__eb64_delete Unexecuted instantiation: h1_htx.c:__eb64_delete Unexecuted instantiation: lru.c:__eb64_delete |
113 | | |
114 | | /* |
115 | | * Find the first occurrence of a key in the tree <root>. If none can be |
116 | | * found, return NULL. |
117 | | */ |
118 | | static forceinline struct eb64_node *__eb64_lookup(struct eb_root *root, u64 x) |
119 | 0 | { |
120 | 0 | struct eb64_node *node; |
121 | 0 | eb_troot_t *troot; |
122 | 0 | u64 y; |
123 | |
|
124 | 0 | troot = root->b[EB_LEFT]; |
125 | 0 | if (unlikely(troot == NULL)) |
126 | 0 | return NULL; |
127 | | |
128 | 0 | while (1) { |
129 | 0 | if ((eb_gettag(troot) == EB_LEAF)) { |
130 | 0 | node = container_of(eb_untag(troot, EB_LEAF), |
131 | 0 | struct eb64_node, node.branches); |
132 | 0 | if (node->key == x) |
133 | 0 | return node; |
134 | 0 | else |
135 | 0 | return NULL; |
136 | 0 | } |
137 | 0 | node = container_of(eb_untag(troot, EB_NODE), |
138 | 0 | struct eb64_node, node.branches); |
139 | |
|
140 | 0 | y = node->key ^ x; |
141 | 0 | if (!y) { |
142 | | /* Either we found the node which holds the key, or |
143 | | * we have a dup tree. In the later case, we have to |
144 | | * walk it down left to get the first entry. |
145 | | */ |
146 | 0 | if (node->node.bit < 0) { |
147 | 0 | troot = node->node.branches.b[EB_LEFT]; |
148 | 0 | while (eb_gettag(troot) != EB_LEAF) |
149 | 0 | troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; |
150 | 0 | node = container_of(eb_untag(troot, EB_LEAF), |
151 | 0 | struct eb64_node, node.branches); |
152 | 0 | } |
153 | 0 | return node; |
154 | 0 | } |
155 | | |
156 | 0 | if ((y >> node->node.bit) >= EB_NODE_BRANCHES) |
157 | 0 | return NULL; /* no more common bits */ |
158 | | |
159 | 0 | troot = node->node.branches.b[(x >> node->node.bit) & EB_NODE_BRANCH_MASK]; |
160 | 0 | } |
161 | 0 | } Unexecuted instantiation: cfgparse.c:__eb64_lookup Unexecuted instantiation: connection.c:__eb64_lookup Unexecuted instantiation: eb64tree.c:__eb64_lookup Unexecuted instantiation: ebistree.c:__eb64_lookup Unexecuted instantiation: filters.c:__eb64_lookup Unexecuted instantiation: flt_http_comp.c:__eb64_lookup Unexecuted instantiation: haproxy.c:__eb64_lookup Unexecuted instantiation: http_ana.c:__eb64_lookup Unexecuted instantiation: http_ext.c:__eb64_lookup Unexecuted instantiation: http_htx.c:__eb64_lookup Unexecuted instantiation: peers.c:__eb64_lookup Unexecuted instantiation: proxy.c:__eb64_lookup Unexecuted instantiation: resolvers.c:__eb64_lookup Unexecuted instantiation: server.c:__eb64_lookup Unexecuted instantiation: sock.c:__eb64_lookup Unexecuted instantiation: sock_inet.c:__eb64_lookup Unexecuted instantiation: stats.c:__eb64_lookup Unexecuted instantiation: stick_table.c:__eb64_lookup Unexecuted instantiation: stream.c:__eb64_lookup Unexecuted instantiation: tcpcheck.c:__eb64_lookup Unexecuted instantiation: tools.c:__eb64_lookup Unexecuted instantiation: backend.c:__eb64_lookup Unexecuted instantiation: cache.c:__eb64_lookup Unexecuted instantiation: cfgparse-listen.c:__eb64_lookup Unexecuted instantiation: check.c:__eb64_lookup Unexecuted instantiation: dict.c:__eb64_lookup Unexecuted instantiation: ebimtree.c:__eb64_lookup Unexecuted instantiation: fcgi-app.c:__eb64_lookup Unexecuted instantiation: http_fetch.c:__eb64_lookup Unexecuted instantiation: pattern.c:__eb64_lookup Unexecuted instantiation: h1_htx.c:__eb64_lookup Unexecuted instantiation: lru.c:__eb64_lookup |
162 | | |
163 | | /* |
164 | | * Find the first occurrence of a signed key in the tree <root>. If none can |
165 | | * be found, return NULL. |
166 | | */ |
167 | | static forceinline struct eb64_node *__eb64i_lookup(struct eb_root *root, s64 x) |
168 | 0 | { |
169 | 0 | struct eb64_node *node; |
170 | 0 | eb_troot_t *troot; |
171 | 0 | u64 key = x ^ (1ULL << 63); |
172 | 0 | u64 y; |
173 | |
|
174 | 0 | troot = root->b[EB_LEFT]; |
175 | 0 | if (unlikely(troot == NULL)) |
176 | 0 | return NULL; |
177 | | |
178 | 0 | while (1) { |
179 | 0 | if ((eb_gettag(troot) == EB_LEAF)) { |
180 | 0 | node = container_of(eb_untag(troot, EB_LEAF), |
181 | 0 | struct eb64_node, node.branches); |
182 | 0 | if (node->key == (u64)x) |
183 | 0 | return node; |
184 | 0 | else |
185 | 0 | return NULL; |
186 | 0 | } |
187 | 0 | node = container_of(eb_untag(troot, EB_NODE), |
188 | 0 | struct eb64_node, node.branches); |
189 | |
|
190 | 0 | y = node->key ^ x; |
191 | 0 | if (!y) { |
192 | | /* Either we found the node which holds the key, or |
193 | | * we have a dup tree. In the later case, we have to |
194 | | * walk it down left to get the first entry. |
195 | | */ |
196 | 0 | if (node->node.bit < 0) { |
197 | 0 | troot = node->node.branches.b[EB_LEFT]; |
198 | 0 | while (eb_gettag(troot) != EB_LEAF) |
199 | 0 | troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; |
200 | 0 | node = container_of(eb_untag(troot, EB_LEAF), |
201 | 0 | struct eb64_node, node.branches); |
202 | 0 | } |
203 | 0 | return node; |
204 | 0 | } |
205 | | |
206 | 0 | if ((y >> node->node.bit) >= EB_NODE_BRANCHES) |
207 | 0 | return NULL; /* no more common bits */ |
208 | | |
209 | 0 | troot = node->node.branches.b[(key >> node->node.bit) & EB_NODE_BRANCH_MASK]; |
210 | 0 | } |
211 | 0 | } Unexecuted instantiation: cfgparse.c:__eb64i_lookup Unexecuted instantiation: connection.c:__eb64i_lookup Unexecuted instantiation: eb64tree.c:__eb64i_lookup Unexecuted instantiation: ebistree.c:__eb64i_lookup Unexecuted instantiation: filters.c:__eb64i_lookup Unexecuted instantiation: flt_http_comp.c:__eb64i_lookup Unexecuted instantiation: haproxy.c:__eb64i_lookup Unexecuted instantiation: http_ana.c:__eb64i_lookup Unexecuted instantiation: http_ext.c:__eb64i_lookup Unexecuted instantiation: http_htx.c:__eb64i_lookup Unexecuted instantiation: peers.c:__eb64i_lookup Unexecuted instantiation: proxy.c:__eb64i_lookup Unexecuted instantiation: resolvers.c:__eb64i_lookup Unexecuted instantiation: server.c:__eb64i_lookup Unexecuted instantiation: sock.c:__eb64i_lookup Unexecuted instantiation: sock_inet.c:__eb64i_lookup Unexecuted instantiation: stats.c:__eb64i_lookup Unexecuted instantiation: stick_table.c:__eb64i_lookup Unexecuted instantiation: stream.c:__eb64i_lookup Unexecuted instantiation: tcpcheck.c:__eb64i_lookup Unexecuted instantiation: tools.c:__eb64i_lookup Unexecuted instantiation: backend.c:__eb64i_lookup Unexecuted instantiation: cache.c:__eb64i_lookup Unexecuted instantiation: cfgparse-listen.c:__eb64i_lookup Unexecuted instantiation: check.c:__eb64i_lookup Unexecuted instantiation: dict.c:__eb64i_lookup Unexecuted instantiation: ebimtree.c:__eb64i_lookup Unexecuted instantiation: fcgi-app.c:__eb64i_lookup Unexecuted instantiation: http_fetch.c:__eb64i_lookup Unexecuted instantiation: pattern.c:__eb64i_lookup Unexecuted instantiation: h1_htx.c:__eb64i_lookup Unexecuted instantiation: lru.c:__eb64i_lookup |
212 | | |
213 | | /* Insert eb64_node <new> into subtree starting at node root <root>. |
214 | | * Only new->key needs be set with the key. The eb64_node is returned. |
215 | | * If root->b[EB_RGHT]==1, the tree may only contain unique keys. |
216 | | */ |
217 | | static forceinline struct eb64_node * |
218 | 0 | __eb64_insert(struct eb_root *root, struct eb64_node *new) { |
219 | 0 | struct eb64_node *old; |
220 | 0 | unsigned int side; |
221 | 0 | eb_troot_t *troot; |
222 | 0 | u64 newkey; /* caching the key saves approximately one cycle */ |
223 | 0 | eb_troot_t *root_right; |
224 | 0 | int old_node_bit; |
225 | |
|
226 | 0 | side = EB_LEFT; |
227 | 0 | troot = root->b[EB_LEFT]; |
228 | 0 | root_right = root->b[EB_RGHT]; |
229 | 0 | if (unlikely(troot == NULL)) { |
230 | | /* Tree is empty, insert the leaf part below the left branch */ |
231 | 0 | root->b[EB_LEFT] = eb_dotag(&new->node.branches, EB_LEAF); |
232 | 0 | new->node.leaf_p = eb_dotag(root, EB_LEFT); |
233 | 0 | new->node.node_p = NULL; /* node part unused */ |
234 | 0 | return new; |
235 | 0 | } |
236 | | |
237 | | /* The tree descent is fairly easy : |
238 | | * - first, check if we have reached a leaf node |
239 | | * - second, check if we have gone too far |
240 | | * - third, reiterate |
241 | | * Everywhere, we use <new> for the node node we are inserting, <root> |
242 | | * for the node we attach it to, and <old> for the node we are |
243 | | * displacing below <new>. <troot> will always point to the future node |
244 | | * (tagged with its type). <side> carries the side the node <new> is |
245 | | * attached to below its parent, which is also where previous node |
246 | | * was attached. <newkey> carries the key being inserted. |
247 | | */ |
248 | 0 | newkey = new->key; |
249 | |
|
250 | 0 | while (1) { |
251 | 0 | if (unlikely(eb_gettag(troot) == EB_LEAF)) { |
252 | 0 | eb_troot_t *new_left, *new_rght; |
253 | 0 | eb_troot_t *new_leaf, *old_leaf; |
254 | |
|
255 | 0 | old = container_of(eb_untag(troot, EB_LEAF), |
256 | 0 | struct eb64_node, node.branches); |
257 | |
|
258 | 0 | new_left = eb_dotag(&new->node.branches, EB_LEFT); |
259 | 0 | new_rght = eb_dotag(&new->node.branches, EB_RGHT); |
260 | 0 | new_leaf = eb_dotag(&new->node.branches, EB_LEAF); |
261 | 0 | old_leaf = eb_dotag(&old->node.branches, EB_LEAF); |
262 | |
|
263 | 0 | new->node.node_p = old->node.leaf_p; |
264 | | |
265 | | /* Right here, we have 3 possibilities : |
266 | | - the tree does not contain the key, and we have |
267 | | new->key < old->key. We insert new above old, on |
268 | | the left ; |
269 | | |
270 | | - the tree does not contain the key, and we have |
271 | | new->key > old->key. We insert new above old, on |
272 | | the right ; |
273 | | |
274 | | - the tree does contain the key, which implies it |
275 | | is alone. We add the new key next to it as a |
276 | | first duplicate. |
277 | | |
278 | | The last two cases can easily be partially merged. |
279 | | */ |
280 | | |
281 | 0 | if (new->key < old->key) { |
282 | 0 | new->node.leaf_p = new_left; |
283 | 0 | old->node.leaf_p = new_rght; |
284 | 0 | new->node.branches.b[EB_LEFT] = new_leaf; |
285 | 0 | new->node.branches.b[EB_RGHT] = old_leaf; |
286 | 0 | } else { |
287 | | /* we may refuse to duplicate this key if the tree is |
288 | | * tagged as containing only unique keys. |
289 | | */ |
290 | 0 | if ((new->key == old->key) && eb_gettag(root_right)) |
291 | 0 | return old; |
292 | | |
293 | | /* new->key >= old->key, new goes the right */ |
294 | 0 | old->node.leaf_p = new_left; |
295 | 0 | new->node.leaf_p = new_rght; |
296 | 0 | new->node.branches.b[EB_LEFT] = old_leaf; |
297 | 0 | new->node.branches.b[EB_RGHT] = new_leaf; |
298 | |
|
299 | 0 | if (new->key == old->key) { |
300 | 0 | new->node.bit = -1; |
301 | 0 | root->b[side] = eb_dotag(&new->node.branches, EB_NODE); |
302 | 0 | return new; |
303 | 0 | } |
304 | 0 | } |
305 | 0 | break; |
306 | 0 | } |
307 | | |
308 | | /* OK we're walking down this link */ |
309 | 0 | old = container_of(eb_untag(troot, EB_NODE), |
310 | 0 | struct eb64_node, node.branches); |
311 | 0 | old_node_bit = old->node.bit; |
312 | | |
313 | | /* Stop going down when we don't have common bits anymore. We |
314 | | * also stop in front of a duplicates tree because it means we |
315 | | * have to insert above. |
316 | | */ |
317 | |
|
318 | 0 | if ((old_node_bit < 0) || /* we're above a duplicate tree, stop here */ |
319 | 0 | (((new->key ^ old->key) >> old_node_bit) >= EB_NODE_BRANCHES)) { |
320 | | /* The tree did not contain the key, so we insert <new> before the node |
321 | | * <old>, and set ->bit to designate the lowest bit position in <new> |
322 | | * which applies to ->branches.b[]. |
323 | | */ |
324 | 0 | eb_troot_t *new_left, *new_rght; |
325 | 0 | eb_troot_t *new_leaf, *old_node; |
326 | |
|
327 | 0 | new_left = eb_dotag(&new->node.branches, EB_LEFT); |
328 | 0 | new_rght = eb_dotag(&new->node.branches, EB_RGHT); |
329 | 0 | new_leaf = eb_dotag(&new->node.branches, EB_LEAF); |
330 | 0 | old_node = eb_dotag(&old->node.branches, EB_NODE); |
331 | |
|
332 | 0 | new->node.node_p = old->node.node_p; |
333 | |
|
334 | 0 | if (new->key < old->key) { |
335 | 0 | new->node.leaf_p = new_left; |
336 | 0 | old->node.node_p = new_rght; |
337 | 0 | new->node.branches.b[EB_LEFT] = new_leaf; |
338 | 0 | new->node.branches.b[EB_RGHT] = old_node; |
339 | 0 | } |
340 | 0 | else if (new->key > old->key) { |
341 | 0 | old->node.node_p = new_left; |
342 | 0 | new->node.leaf_p = new_rght; |
343 | 0 | new->node.branches.b[EB_LEFT] = old_node; |
344 | 0 | new->node.branches.b[EB_RGHT] = new_leaf; |
345 | 0 | } |
346 | 0 | else { |
347 | 0 | struct eb_node *ret; |
348 | 0 | ret = eb_insert_dup(&old->node, &new->node); |
349 | 0 | return container_of(ret, struct eb64_node, node); |
350 | 0 | } |
351 | 0 | break; |
352 | 0 | } |
353 | | |
354 | | /* walk down */ |
355 | 0 | root = &old->node.branches; |
356 | |
|
357 | 0 | if (sizeof(long) >= 8) { |
358 | 0 | side = newkey >> old_node_bit; |
359 | 0 | } else { |
360 | | /* note: provides the best code on low-register count archs |
361 | | * such as i386. |
362 | | */ |
363 | 0 | side = newkey; |
364 | 0 | side >>= old_node_bit; |
365 | 0 | if (old_node_bit >= 32) { |
366 | 0 | side = newkey >> 32; |
367 | 0 | side >>= old_node_bit & 0x1F; |
368 | 0 | } |
369 | 0 | } |
370 | 0 | side &= EB_NODE_BRANCH_MASK; |
371 | 0 | troot = root->b[side]; |
372 | 0 | } |
373 | | |
374 | | /* Ok, now we are inserting <new> between <root> and <old>. <old>'s |
375 | | * parent is already set to <new>, and the <root>'s branch is still in |
376 | | * <side>. Update the root's leaf till we have it. Note that we can also |
377 | | * find the side by checking the side of new->node.node_p. |
378 | | */ |
379 | | |
380 | | /* We need the common higher bits between new->key and old->key. |
381 | | * What differences are there between new->key and the node here ? |
382 | | * NOTE that bit(new) is always < bit(root) because highest |
383 | | * bit of new->key and old->key are identical here (otherwise they |
384 | | * would sit on different branches). |
385 | | */ |
386 | | // note that if EB_NODE_BITS > 1, we should check that it's still >= 0 |
387 | 0 | new->node.bit = fls64(new->key ^ old->key) - EB_NODE_BITS; |
388 | 0 | root->b[side] = eb_dotag(&new->node.branches, EB_NODE); |
389 | |
|
390 | 0 | return new; |
391 | 0 | } Unexecuted instantiation: cfgparse.c:__eb64_insert Unexecuted instantiation: connection.c:__eb64_insert Unexecuted instantiation: eb64tree.c:__eb64_insert Unexecuted instantiation: ebistree.c:__eb64_insert Unexecuted instantiation: filters.c:__eb64_insert Unexecuted instantiation: flt_http_comp.c:__eb64_insert Unexecuted instantiation: haproxy.c:__eb64_insert Unexecuted instantiation: http_ana.c:__eb64_insert Unexecuted instantiation: http_ext.c:__eb64_insert Unexecuted instantiation: http_htx.c:__eb64_insert Unexecuted instantiation: peers.c:__eb64_insert Unexecuted instantiation: proxy.c:__eb64_insert Unexecuted instantiation: resolvers.c:__eb64_insert Unexecuted instantiation: server.c:__eb64_insert Unexecuted instantiation: sock.c:__eb64_insert Unexecuted instantiation: sock_inet.c:__eb64_insert Unexecuted instantiation: stats.c:__eb64_insert Unexecuted instantiation: stick_table.c:__eb64_insert Unexecuted instantiation: stream.c:__eb64_insert Unexecuted instantiation: tcpcheck.c:__eb64_insert Unexecuted instantiation: tools.c:__eb64_insert Unexecuted instantiation: backend.c:__eb64_insert Unexecuted instantiation: cache.c:__eb64_insert Unexecuted instantiation: cfgparse-listen.c:__eb64_insert Unexecuted instantiation: check.c:__eb64_insert Unexecuted instantiation: dict.c:__eb64_insert Unexecuted instantiation: ebimtree.c:__eb64_insert Unexecuted instantiation: fcgi-app.c:__eb64_insert Unexecuted instantiation: http_fetch.c:__eb64_insert Unexecuted instantiation: pattern.c:__eb64_insert Unexecuted instantiation: h1_htx.c:__eb64_insert Unexecuted instantiation: lru.c:__eb64_insert |
392 | | |
393 | | /* Insert eb64_node <new> into subtree starting at node root <root>, using |
394 | | * signed keys. Only new->key needs be set with the key. The eb64_node |
395 | | * is returned. If root->b[EB_RGHT]==1, the tree may only contain unique keys. |
396 | | */ |
397 | | static forceinline struct eb64_node * |
398 | 0 | __eb64i_insert(struct eb_root *root, struct eb64_node *new) { |
399 | 0 | struct eb64_node *old; |
400 | 0 | unsigned int side; |
401 | 0 | eb_troot_t *troot; |
402 | 0 | u64 newkey; /* caching the key saves approximately one cycle */ |
403 | 0 | eb_troot_t *root_right; |
404 | 0 | int old_node_bit; |
405 | |
|
406 | 0 | side = EB_LEFT; |
407 | 0 | troot = root->b[EB_LEFT]; |
408 | 0 | root_right = root->b[EB_RGHT]; |
409 | 0 | if (unlikely(troot == NULL)) { |
410 | | /* Tree is empty, insert the leaf part below the left branch */ |
411 | 0 | root->b[EB_LEFT] = eb_dotag(&new->node.branches, EB_LEAF); |
412 | 0 | new->node.leaf_p = eb_dotag(root, EB_LEFT); |
413 | 0 | new->node.node_p = NULL; /* node part unused */ |
414 | 0 | return new; |
415 | 0 | } |
416 | | |
417 | | /* The tree descent is fairly easy : |
418 | | * - first, check if we have reached a leaf node |
419 | | * - second, check if we have gone too far |
420 | | * - third, reiterate |
421 | | * Everywhere, we use <new> for the node node we are inserting, <root> |
422 | | * for the node we attach it to, and <old> for the node we are |
423 | | * displacing below <new>. <troot> will always point to the future node |
424 | | * (tagged with its type). <side> carries the side the node <new> is |
425 | | * attached to below its parent, which is also where previous node |
426 | | * was attached. <newkey> carries a high bit shift of the key being |
427 | | * inserted in order to have negative keys stored before positive |
428 | | * ones. |
429 | | */ |
430 | 0 | newkey = new->key ^ (1ULL << 63); |
431 | |
|
432 | 0 | while (1) { |
433 | 0 | if (unlikely(eb_gettag(troot) == EB_LEAF)) { |
434 | 0 | eb_troot_t *new_left, *new_rght; |
435 | 0 | eb_troot_t *new_leaf, *old_leaf; |
436 | |
|
437 | 0 | old = container_of(eb_untag(troot, EB_LEAF), |
438 | 0 | struct eb64_node, node.branches); |
439 | |
|
440 | 0 | new_left = eb_dotag(&new->node.branches, EB_LEFT); |
441 | 0 | new_rght = eb_dotag(&new->node.branches, EB_RGHT); |
442 | 0 | new_leaf = eb_dotag(&new->node.branches, EB_LEAF); |
443 | 0 | old_leaf = eb_dotag(&old->node.branches, EB_LEAF); |
444 | |
|
445 | 0 | new->node.node_p = old->node.leaf_p; |
446 | | |
447 | | /* Right here, we have 3 possibilities : |
448 | | - the tree does not contain the key, and we have |
449 | | new->key < old->key. We insert new above old, on |
450 | | the left ; |
451 | | |
452 | | - the tree does not contain the key, and we have |
453 | | new->key > old->key. We insert new above old, on |
454 | | the right ; |
455 | | |
456 | | - the tree does contain the key, which implies it |
457 | | is alone. We add the new key next to it as a |
458 | | first duplicate. |
459 | | |
460 | | The last two cases can easily be partially merged. |
461 | | */ |
462 | | |
463 | 0 | if ((s64)new->key < (s64)old->key) { |
464 | 0 | new->node.leaf_p = new_left; |
465 | 0 | old->node.leaf_p = new_rght; |
466 | 0 | new->node.branches.b[EB_LEFT] = new_leaf; |
467 | 0 | new->node.branches.b[EB_RGHT] = old_leaf; |
468 | 0 | } else { |
469 | | /* we may refuse to duplicate this key if the tree is |
470 | | * tagged as containing only unique keys. |
471 | | */ |
472 | 0 | if ((new->key == old->key) && eb_gettag(root_right)) |
473 | 0 | return old; |
474 | | |
475 | | /* new->key >= old->key, new goes the right */ |
476 | 0 | old->node.leaf_p = new_left; |
477 | 0 | new->node.leaf_p = new_rght; |
478 | 0 | new->node.branches.b[EB_LEFT] = old_leaf; |
479 | 0 | new->node.branches.b[EB_RGHT] = new_leaf; |
480 | |
|
481 | 0 | if (new->key == old->key) { |
482 | 0 | new->node.bit = -1; |
483 | 0 | root->b[side] = eb_dotag(&new->node.branches, EB_NODE); |
484 | 0 | return new; |
485 | 0 | } |
486 | 0 | } |
487 | 0 | break; |
488 | 0 | } |
489 | | |
490 | | /* OK we're walking down this link */ |
491 | 0 | old = container_of(eb_untag(troot, EB_NODE), |
492 | 0 | struct eb64_node, node.branches); |
493 | 0 | old_node_bit = old->node.bit; |
494 | | |
495 | | /* Stop going down when we don't have common bits anymore. We |
496 | | * also stop in front of a duplicates tree because it means we |
497 | | * have to insert above. |
498 | | */ |
499 | |
|
500 | 0 | if ((old_node_bit < 0) || /* we're above a duplicate tree, stop here */ |
501 | 0 | (((new->key ^ old->key) >> old_node_bit) >= EB_NODE_BRANCHES)) { |
502 | | /* The tree did not contain the key, so we insert <new> before the node |
503 | | * <old>, and set ->bit to designate the lowest bit position in <new> |
504 | | * which applies to ->branches.b[]. |
505 | | */ |
506 | 0 | eb_troot_t *new_left, *new_rght; |
507 | 0 | eb_troot_t *new_leaf, *old_node; |
508 | |
|
509 | 0 | new_left = eb_dotag(&new->node.branches, EB_LEFT); |
510 | 0 | new_rght = eb_dotag(&new->node.branches, EB_RGHT); |
511 | 0 | new_leaf = eb_dotag(&new->node.branches, EB_LEAF); |
512 | 0 | old_node = eb_dotag(&old->node.branches, EB_NODE); |
513 | |
|
514 | 0 | new->node.node_p = old->node.node_p; |
515 | |
|
516 | 0 | if ((s64)new->key < (s64)old->key) { |
517 | 0 | new->node.leaf_p = new_left; |
518 | 0 | old->node.node_p = new_rght; |
519 | 0 | new->node.branches.b[EB_LEFT] = new_leaf; |
520 | 0 | new->node.branches.b[EB_RGHT] = old_node; |
521 | 0 | } |
522 | 0 | else if ((s64)new->key > (s64)old->key) { |
523 | 0 | old->node.node_p = new_left; |
524 | 0 | new->node.leaf_p = new_rght; |
525 | 0 | new->node.branches.b[EB_LEFT] = old_node; |
526 | 0 | new->node.branches.b[EB_RGHT] = new_leaf; |
527 | 0 | } |
528 | 0 | else { |
529 | 0 | struct eb_node *ret; |
530 | 0 | ret = eb_insert_dup(&old->node, &new->node); |
531 | 0 | return container_of(ret, struct eb64_node, node); |
532 | 0 | } |
533 | 0 | break; |
534 | 0 | } |
535 | | |
536 | | /* walk down */ |
537 | 0 | root = &old->node.branches; |
538 | |
|
539 | 0 | if (sizeof(long) >= 8) { |
540 | 0 | side = newkey >> old_node_bit; |
541 | 0 | } else { |
542 | | /* note: provides the best code on low-register count archs |
543 | | * such as i386. |
544 | | */ |
545 | 0 | side = newkey; |
546 | 0 | side >>= old_node_bit; |
547 | 0 | if (old_node_bit >= 32) { |
548 | 0 | side = newkey >> 32; |
549 | 0 | side >>= old_node_bit & 0x1F; |
550 | 0 | } |
551 | 0 | } |
552 | 0 | side &= EB_NODE_BRANCH_MASK; |
553 | 0 | troot = root->b[side]; |
554 | 0 | } |
555 | | |
556 | | /* Ok, now we are inserting <new> between <root> and <old>. <old>'s |
557 | | * parent is already set to <new>, and the <root>'s branch is still in |
558 | | * <side>. Update the root's leaf till we have it. Note that we can also |
559 | | * find the side by checking the side of new->node.node_p. |
560 | | */ |
561 | | |
562 | | /* We need the common higher bits between new->key and old->key. |
563 | | * What differences are there between new->key and the node here ? |
564 | | * NOTE that bit(new) is always < bit(root) because highest |
565 | | * bit of new->key and old->key are identical here (otherwise they |
566 | | * would sit on different branches). |
567 | | */ |
568 | | // note that if EB_NODE_BITS > 1, we should check that it's still >= 0 |
569 | 0 | new->node.bit = fls64(new->key ^ old->key) - EB_NODE_BITS; |
570 | 0 | root->b[side] = eb_dotag(&new->node.branches, EB_NODE); |
571 | |
|
572 | 0 | return new; |
573 | 0 | } Unexecuted instantiation: cfgparse.c:__eb64i_insert Unexecuted instantiation: connection.c:__eb64i_insert Unexecuted instantiation: eb64tree.c:__eb64i_insert Unexecuted instantiation: ebistree.c:__eb64i_insert Unexecuted instantiation: filters.c:__eb64i_insert Unexecuted instantiation: flt_http_comp.c:__eb64i_insert Unexecuted instantiation: haproxy.c:__eb64i_insert Unexecuted instantiation: http_ana.c:__eb64i_insert Unexecuted instantiation: http_ext.c:__eb64i_insert Unexecuted instantiation: http_htx.c:__eb64i_insert Unexecuted instantiation: peers.c:__eb64i_insert Unexecuted instantiation: proxy.c:__eb64i_insert Unexecuted instantiation: resolvers.c:__eb64i_insert Unexecuted instantiation: server.c:__eb64i_insert Unexecuted instantiation: sock.c:__eb64i_insert Unexecuted instantiation: sock_inet.c:__eb64i_insert Unexecuted instantiation: stats.c:__eb64i_insert Unexecuted instantiation: stick_table.c:__eb64i_insert Unexecuted instantiation: stream.c:__eb64i_insert Unexecuted instantiation: tcpcheck.c:__eb64i_insert Unexecuted instantiation: tools.c:__eb64i_insert Unexecuted instantiation: backend.c:__eb64i_insert Unexecuted instantiation: cache.c:__eb64i_insert Unexecuted instantiation: cfgparse-listen.c:__eb64i_insert Unexecuted instantiation: check.c:__eb64i_insert Unexecuted instantiation: dict.c:__eb64i_insert Unexecuted instantiation: ebimtree.c:__eb64i_insert Unexecuted instantiation: fcgi-app.c:__eb64i_insert Unexecuted instantiation: http_fetch.c:__eb64i_insert Unexecuted instantiation: pattern.c:__eb64i_insert Unexecuted instantiation: h1_htx.c:__eb64i_insert Unexecuted instantiation: lru.c:__eb64i_insert |
574 | | |
575 | | #endif /* _EB64_TREE_H */ |