/src/haproxy/include/import/eb64tree.h
Line | Count | Source |
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: 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: server.c:eb64_first Unexecuted instantiation: sock.c:eb64_first Unexecuted instantiation: sock_inet.c:eb64_first Unexecuted instantiation: stats-html.c:eb64_first Unexecuted instantiation: stats.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: eb64tree.c:eb64_first Unexecuted instantiation: ebimtree.c:eb64_first Unexecuted instantiation: ebistree.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: proto_tcp.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: 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: server.c:eb64_last Unexecuted instantiation: sock.c:eb64_last Unexecuted instantiation: sock_inet.c:eb64_last Unexecuted instantiation: stats-html.c:eb64_last Unexecuted instantiation: stats.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: eb64tree.c:eb64_last Unexecuted instantiation: ebimtree.c:eb64_last Unexecuted instantiation: ebistree.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: proto_tcp.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: 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: server.c:eb64_next Unexecuted instantiation: sock.c:eb64_next Unexecuted instantiation: sock_inet.c:eb64_next Unexecuted instantiation: stats-html.c:eb64_next Unexecuted instantiation: stats.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: eb64tree.c:eb64_next Unexecuted instantiation: ebimtree.c:eb64_next Unexecuted instantiation: ebistree.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: proto_tcp.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: 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: server.c:eb64_prev Unexecuted instantiation: sock.c:eb64_prev Unexecuted instantiation: sock_inet.c:eb64_prev Unexecuted instantiation: stats-html.c:eb64_prev Unexecuted instantiation: stats.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: eb64tree.c:eb64_prev Unexecuted instantiation: ebimtree.c:eb64_prev Unexecuted instantiation: ebistree.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: proto_tcp.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: 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: server.c:eb64_next_dup Unexecuted instantiation: sock.c:eb64_next_dup Unexecuted instantiation: sock_inet.c:eb64_next_dup Unexecuted instantiation: stats-html.c:eb64_next_dup Unexecuted instantiation: stats.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: eb64tree.c:eb64_next_dup Unexecuted instantiation: ebimtree.c:eb64_next_dup Unexecuted instantiation: ebistree.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: proto_tcp.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: 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: server.c:eb64_prev_dup Unexecuted instantiation: sock.c:eb64_prev_dup Unexecuted instantiation: sock_inet.c:eb64_prev_dup Unexecuted instantiation: stats-html.c:eb64_prev_dup Unexecuted instantiation: stats.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: eb64tree.c:eb64_prev_dup Unexecuted instantiation: ebimtree.c:eb64_prev_dup Unexecuted instantiation: ebistree.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: proto_tcp.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: 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: server.c:eb64_next_unique Unexecuted instantiation: sock.c:eb64_next_unique Unexecuted instantiation: sock_inet.c:eb64_next_unique Unexecuted instantiation: stats-html.c:eb64_next_unique Unexecuted instantiation: stats.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: eb64tree.c:eb64_next_unique Unexecuted instantiation: ebimtree.c:eb64_next_unique Unexecuted instantiation: ebistree.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: proto_tcp.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: 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: server.c:eb64_prev_unique Unexecuted instantiation: sock.c:eb64_prev_unique Unexecuted instantiation: sock_inet.c:eb64_prev_unique Unexecuted instantiation: stats-html.c:eb64_prev_unique Unexecuted instantiation: stats.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: eb64tree.c:eb64_prev_unique Unexecuted instantiation: ebimtree.c:eb64_prev_unique Unexecuted instantiation: ebistree.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: proto_tcp.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: 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: server.c:eb64_delete Unexecuted instantiation: sock.c:eb64_delete Unexecuted instantiation: sock_inet.c:eb64_delete Unexecuted instantiation: stats-html.c:eb64_delete Unexecuted instantiation: stats.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: eb64tree.c:eb64_delete Unexecuted instantiation: ebimtree.c:eb64_delete Unexecuted instantiation: ebistree.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: proto_tcp.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: 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: server.c:__eb64_delete Unexecuted instantiation: sock.c:__eb64_delete Unexecuted instantiation: sock_inet.c:__eb64_delete Unexecuted instantiation: stats-html.c:__eb64_delete Unexecuted instantiation: stats.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: eb64tree.c:__eb64_delete Unexecuted instantiation: ebimtree.c:__eb64_delete Unexecuted instantiation: ebistree.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: proto_tcp.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, z; |
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 (unlikely(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 | eb_prefetch(node->node.branches.b[0], 0); |
141 | 0 | eb_prefetch(node->node.branches.b[1], 0); |
142 | |
|
143 | 0 | y = node->key ^ x; |
144 | 0 | z = 1ULL << (node->node.bit & 63); |
145 | 0 | troot = (x & z) ? node->node.branches.b[1] : node->node.branches.b[0]; |
146 | |
|
147 | 0 | if (!y) { |
148 | | /* Either we found the node which holds the key, or |
149 | | * we have a dup tree. In the later case, we have to |
150 | | * walk it down left to get the first entry. |
151 | | */ |
152 | 0 | if (node->node.bit < 0) { |
153 | 0 | troot = node->node.branches.b[EB_LEFT]; |
154 | 0 | while (eb_gettag(troot) != EB_LEAF) |
155 | 0 | troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; |
156 | 0 | node = container_of(eb_untag(troot, EB_LEAF), |
157 | 0 | struct eb64_node, node.branches); |
158 | 0 | } |
159 | 0 | return node; |
160 | 0 | } |
161 | | |
162 | 0 | if (y & -(z << 1)) |
163 | 0 | return NULL; /* no more common bits */ |
164 | 0 | } |
165 | 0 | } Unexecuted instantiation: cfgparse.c:__eb64_lookup Unexecuted instantiation: connection.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: server.c:__eb64_lookup Unexecuted instantiation: sock.c:__eb64_lookup Unexecuted instantiation: sock_inet.c:__eb64_lookup Unexecuted instantiation: stats-html.c:__eb64_lookup Unexecuted instantiation: stats.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: eb64tree.c:__eb64_lookup Unexecuted instantiation: ebimtree.c:__eb64_lookup Unexecuted instantiation: ebistree.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: proto_tcp.c:__eb64_lookup Unexecuted instantiation: h1_htx.c:__eb64_lookup Unexecuted instantiation: lru.c:__eb64_lookup |
166 | | |
167 | | /* |
168 | | * Find the first occurrence of a signed key in the tree <root>. If none can |
169 | | * be found, return NULL. |
170 | | */ |
171 | | static forceinline struct eb64_node *__eb64i_lookup(struct eb_root *root, s64 x) |
172 | 0 | { |
173 | 0 | struct eb64_node *node; |
174 | 0 | eb_troot_t *troot; |
175 | 0 | u64 key = x ^ (1ULL << 63); |
176 | 0 | u64 y, z; |
177 | |
|
178 | 0 | troot = root->b[EB_LEFT]; |
179 | 0 | if (unlikely(troot == NULL)) |
180 | 0 | return NULL; |
181 | | |
182 | 0 | while (1) { |
183 | 0 | if (unlikely(eb_gettag(troot) == EB_LEAF)) { |
184 | 0 | node = container_of(eb_untag(troot, EB_LEAF), |
185 | 0 | struct eb64_node, node.branches); |
186 | 0 | if (node->key == (u64)x) |
187 | 0 | return node; |
188 | 0 | else |
189 | 0 | return NULL; |
190 | 0 | } |
191 | 0 | node = container_of(eb_untag(troot, EB_NODE), |
192 | 0 | struct eb64_node, node.branches); |
193 | |
|
194 | 0 | eb_prefetch(node->node.branches.b[0], 0); |
195 | 0 | eb_prefetch(node->node.branches.b[1], 0); |
196 | |
|
197 | 0 | y = node->key ^ x; |
198 | 0 | z = 1ULL << (node->node.bit & 63); |
199 | 0 | troot = (key & z) ? node->node.branches.b[1] : node->node.branches.b[0]; |
200 | |
|
201 | 0 | if (!y) { |
202 | | /* Either we found the node which holds the key, or |
203 | | * we have a dup tree. In the later case, we have to |
204 | | * walk it down left to get the first entry. |
205 | | */ |
206 | 0 | if (node->node.bit < 0) { |
207 | 0 | troot = node->node.branches.b[EB_LEFT]; |
208 | 0 | while (eb_gettag(troot) != EB_LEAF) |
209 | 0 | troot = (eb_untag(troot, EB_NODE))->b[EB_LEFT]; |
210 | 0 | node = container_of(eb_untag(troot, EB_LEAF), |
211 | 0 | struct eb64_node, node.branches); |
212 | 0 | } |
213 | 0 | return node; |
214 | 0 | } |
215 | | |
216 | 0 | if (y & -(z << 1)) |
217 | 0 | return NULL; /* no more common bits */ |
218 | 0 | } |
219 | 0 | } Unexecuted instantiation: cfgparse.c:__eb64i_lookup Unexecuted instantiation: connection.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: server.c:__eb64i_lookup Unexecuted instantiation: sock.c:__eb64i_lookup Unexecuted instantiation: sock_inet.c:__eb64i_lookup Unexecuted instantiation: stats-html.c:__eb64i_lookup Unexecuted instantiation: stats.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: eb64tree.c:__eb64i_lookup Unexecuted instantiation: ebimtree.c:__eb64i_lookup Unexecuted instantiation: ebistree.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: proto_tcp.c:__eb64i_lookup Unexecuted instantiation: h1_htx.c:__eb64i_lookup Unexecuted instantiation: lru.c:__eb64i_lookup |
220 | | |
221 | | /* Insert eb64_node <new> into subtree starting at node root <root>. |
222 | | * Only new->key needs be set with the key. The eb64_node is returned. |
223 | | * If root->b[EB_RGHT]==1, the tree may only contain unique keys. |
224 | | */ |
225 | | static forceinline struct eb64_node * |
226 | 0 | __eb64_insert(struct eb_root *root, struct eb64_node *new) { |
227 | 0 | struct eb64_node *old; |
228 | 0 | unsigned int side; |
229 | 0 | eb_troot_t *troot; |
230 | 0 | u64 newkey; /* caching the key saves approximately one cycle */ |
231 | 0 | eb_troot_t *root_right; |
232 | 0 | int old_node_bit; |
233 | |
|
234 | 0 | side = EB_LEFT; |
235 | 0 | troot = root->b[EB_LEFT]; |
236 | 0 | root_right = root->b[EB_RGHT]; |
237 | 0 | if (unlikely(troot == NULL)) { |
238 | | /* Tree is empty, insert the leaf part below the left branch */ |
239 | 0 | root->b[EB_LEFT] = eb_dotag(&new->node.branches, EB_LEAF); |
240 | 0 | new->node.leaf_p = eb_dotag(root, EB_LEFT); |
241 | 0 | new->node.node_p = NULL; /* node part unused */ |
242 | 0 | return new; |
243 | 0 | } |
244 | | |
245 | | /* The tree descent is fairly easy : |
246 | | * - first, check if we have reached a leaf node |
247 | | * - second, check if we have gone too far |
248 | | * - third, reiterate |
249 | | * Everywhere, we use <new> for the node node we are inserting, <root> |
250 | | * for the node we attach it to, and <old> for the node we are |
251 | | * displacing below <new>. <troot> will always point to the future node |
252 | | * (tagged with its type). <side> carries the side the node <new> is |
253 | | * attached to below its parent, which is also where previous node |
254 | | * was attached. <newkey> carries the key being inserted. |
255 | | */ |
256 | 0 | newkey = new->key; |
257 | |
|
258 | 0 | while (1) { |
259 | 0 | if (unlikely(eb_gettag(troot) == EB_LEAF)) { |
260 | 0 | eb_troot_t *new_left, *new_rght; |
261 | 0 | eb_troot_t *new_leaf, *old_leaf; |
262 | |
|
263 | 0 | old = container_of(eb_untag(troot, EB_LEAF), |
264 | 0 | struct eb64_node, node.branches); |
265 | |
|
266 | 0 | new_left = eb_dotag(&new->node.branches, EB_LEFT); |
267 | 0 | new_rght = eb_dotag(&new->node.branches, EB_RGHT); |
268 | 0 | new_leaf = eb_dotag(&new->node.branches, EB_LEAF); |
269 | 0 | old_leaf = eb_dotag(&old->node.branches, EB_LEAF); |
270 | |
|
271 | 0 | new->node.node_p = old->node.leaf_p; |
272 | | |
273 | | /* Right here, we have 3 possibilities : |
274 | | - the tree does not contain the key, and we have |
275 | | new->key < old->key. We insert new above old, on |
276 | | the left ; |
277 | | |
278 | | - the tree does not contain the key, and we have |
279 | | new->key > old->key. We insert new above old, on |
280 | | the right ; |
281 | | |
282 | | - the tree does contain the key, which implies it |
283 | | is alone. We add the new key next to it as a |
284 | | first duplicate. |
285 | | |
286 | | The last two cases can easily be partially merged. |
287 | | */ |
288 | | |
289 | 0 | if (new->key < old->key) { |
290 | 0 | new->node.leaf_p = new_left; |
291 | 0 | old->node.leaf_p = new_rght; |
292 | 0 | new->node.branches.b[EB_LEFT] = new_leaf; |
293 | 0 | new->node.branches.b[EB_RGHT] = old_leaf; |
294 | 0 | } else { |
295 | | /* we may refuse to duplicate this key if the tree is |
296 | | * tagged as containing only unique keys. |
297 | | */ |
298 | 0 | if ((new->key == old->key) && eb_gettag(root_right)) |
299 | 0 | return old; |
300 | | |
301 | | /* new->key >= old->key, new goes the right */ |
302 | 0 | old->node.leaf_p = new_left; |
303 | 0 | new->node.leaf_p = new_rght; |
304 | 0 | new->node.branches.b[EB_LEFT] = old_leaf; |
305 | 0 | new->node.branches.b[EB_RGHT] = new_leaf; |
306 | |
|
307 | 0 | if (new->key == old->key) { |
308 | 0 | new->node.bit = -1; |
309 | 0 | root->b[side] = eb_dotag(&new->node.branches, EB_NODE); |
310 | 0 | return new; |
311 | 0 | } |
312 | 0 | } |
313 | 0 | break; |
314 | 0 | } |
315 | | |
316 | | /* OK we're walking down this link */ |
317 | 0 | old = container_of(eb_untag(troot, EB_NODE), |
318 | 0 | struct eb64_node, node.branches); |
319 | |
|
320 | 0 | eb_prefetch(old->node.branches.b[0], 0); |
321 | 0 | eb_prefetch(old->node.branches.b[1], 0); |
322 | |
|
323 | 0 | old_node_bit = old->node.bit; |
324 | | |
325 | | /* Stop going down when we don't have common bits anymore. We |
326 | | * also stop in front of a duplicates tree because it means we |
327 | | * have to insert above. |
328 | | */ |
329 | |
|
330 | 0 | if ((old_node_bit < 0) || /* we're above a duplicate tree, stop here */ |
331 | 0 | (((new->key ^ old->key) >> old_node_bit) >= EB_NODE_BRANCHES)) { |
332 | | /* The tree did not contain the key, so we insert <new> before the node |
333 | | * <old>, and set ->bit to designate the lowest bit position in <new> |
334 | | * which applies to ->branches.b[]. |
335 | | */ |
336 | 0 | eb_troot_t *new_left, *new_rght; |
337 | 0 | eb_troot_t *new_leaf, *old_node; |
338 | |
|
339 | 0 | new_left = eb_dotag(&new->node.branches, EB_LEFT); |
340 | 0 | new_rght = eb_dotag(&new->node.branches, EB_RGHT); |
341 | 0 | new_leaf = eb_dotag(&new->node.branches, EB_LEAF); |
342 | 0 | old_node = eb_dotag(&old->node.branches, EB_NODE); |
343 | |
|
344 | 0 | new->node.node_p = old->node.node_p; |
345 | |
|
346 | 0 | if (new->key < old->key) { |
347 | 0 | new->node.leaf_p = new_left; |
348 | 0 | old->node.node_p = new_rght; |
349 | 0 | new->node.branches.b[EB_LEFT] = new_leaf; |
350 | 0 | new->node.branches.b[EB_RGHT] = old_node; |
351 | 0 | } |
352 | 0 | else if (new->key > old->key) { |
353 | 0 | old->node.node_p = new_left; |
354 | 0 | new->node.leaf_p = new_rght; |
355 | 0 | new->node.branches.b[EB_LEFT] = old_node; |
356 | 0 | new->node.branches.b[EB_RGHT] = new_leaf; |
357 | 0 | } |
358 | 0 | else { |
359 | 0 | struct eb_node *ret; |
360 | 0 | ret = eb_insert_dup(&old->node, &new->node); |
361 | 0 | return container_of(ret, struct eb64_node, node); |
362 | 0 | } |
363 | 0 | break; |
364 | 0 | } |
365 | | |
366 | | /* walk down */ |
367 | | |
368 | 0 | if (sizeof(long) >= 8) { |
369 | 0 | side = newkey >> old_node_bit; |
370 | 0 | } else { |
371 | | /* note: provides the best code on low-register count archs |
372 | | * such as i386. |
373 | | */ |
374 | 0 | side = newkey; |
375 | 0 | side >>= old_node_bit; |
376 | 0 | if (old_node_bit >= 32) { |
377 | 0 | side = newkey >> 32; |
378 | 0 | side >>= old_node_bit & 0x1F; |
379 | 0 | } |
380 | 0 | } |
381 | 0 | side &= EB_NODE_BRANCH_MASK; |
382 | 0 | troot = side ? old->node.branches.b[1] : old->node.branches.b[0]; |
383 | 0 | root = &old->node.branches; |
384 | 0 | } |
385 | | |
386 | | /* Ok, now we are inserting <new> between <root> and <old>. <old>'s |
387 | | * parent is already set to <new>, and the <root>'s branch is still in |
388 | | * <side>. Update the root's leaf till we have it. Note that we can also |
389 | | * find the side by checking the side of new->node.node_p. |
390 | | */ |
391 | | |
392 | | /* We need the common higher bits between new->key and old->key. |
393 | | * What differences are there between new->key and the node here ? |
394 | | * NOTE that bit(new) is always < bit(root) because highest |
395 | | * bit of new->key and old->key are identical here (otherwise they |
396 | | * would sit on different branches). |
397 | | */ |
398 | | // note that if EB_NODE_BITS > 1, we should check that it's still >= 0 |
399 | 0 | new->node.bit = fls64(new->key ^ old->key) - EB_NODE_BITS; |
400 | 0 | root->b[side] = eb_dotag(&new->node.branches, EB_NODE); |
401 | |
|
402 | 0 | return new; |
403 | 0 | } Unexecuted instantiation: cfgparse.c:__eb64_insert Unexecuted instantiation: connection.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: server.c:__eb64_insert Unexecuted instantiation: sock.c:__eb64_insert Unexecuted instantiation: sock_inet.c:__eb64_insert Unexecuted instantiation: stats-html.c:__eb64_insert Unexecuted instantiation: stats.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: eb64tree.c:__eb64_insert Unexecuted instantiation: ebimtree.c:__eb64_insert Unexecuted instantiation: ebistree.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: proto_tcp.c:__eb64_insert Unexecuted instantiation: h1_htx.c:__eb64_insert Unexecuted instantiation: lru.c:__eb64_insert |
404 | | |
405 | | /* Insert eb64_node <new> into subtree starting at node root <root>, using |
406 | | * signed keys. Only new->key needs be set with the key. The eb64_node |
407 | | * is returned. If root->b[EB_RGHT]==1, the tree may only contain unique keys. |
408 | | */ |
409 | | static forceinline struct eb64_node * |
410 | 0 | __eb64i_insert(struct eb_root *root, struct eb64_node *new) { |
411 | 0 | struct eb64_node *old; |
412 | 0 | unsigned int side; |
413 | 0 | eb_troot_t *troot; |
414 | 0 | u64 newkey; /* caching the key saves approximately one cycle */ |
415 | 0 | eb_troot_t *root_right; |
416 | 0 | int old_node_bit; |
417 | |
|
418 | 0 | side = EB_LEFT; |
419 | 0 | troot = root->b[EB_LEFT]; |
420 | 0 | root_right = root->b[EB_RGHT]; |
421 | 0 | if (unlikely(troot == NULL)) { |
422 | | /* Tree is empty, insert the leaf part below the left branch */ |
423 | 0 | root->b[EB_LEFT] = eb_dotag(&new->node.branches, EB_LEAF); |
424 | 0 | new->node.leaf_p = eb_dotag(root, EB_LEFT); |
425 | 0 | new->node.node_p = NULL; /* node part unused */ |
426 | 0 | return new; |
427 | 0 | } |
428 | | |
429 | | /* The tree descent is fairly easy : |
430 | | * - first, check if we have reached a leaf node |
431 | | * - second, check if we have gone too far |
432 | | * - third, reiterate |
433 | | * Everywhere, we use <new> for the node node we are inserting, <root> |
434 | | * for the node we attach it to, and <old> for the node we are |
435 | | * displacing below <new>. <troot> will always point to the future node |
436 | | * (tagged with its type). <side> carries the side the node <new> is |
437 | | * attached to below its parent, which is also where previous node |
438 | | * was attached. <newkey> carries a high bit shift of the key being |
439 | | * inserted in order to have negative keys stored before positive |
440 | | * ones. |
441 | | */ |
442 | 0 | newkey = new->key ^ (1ULL << 63); |
443 | |
|
444 | 0 | while (1) { |
445 | 0 | if (unlikely(eb_gettag(troot) == EB_LEAF)) { |
446 | 0 | eb_troot_t *new_left, *new_rght; |
447 | 0 | eb_troot_t *new_leaf, *old_leaf; |
448 | |
|
449 | 0 | old = container_of(eb_untag(troot, EB_LEAF), |
450 | 0 | struct eb64_node, node.branches); |
451 | |
|
452 | 0 | new_left = eb_dotag(&new->node.branches, EB_LEFT); |
453 | 0 | new_rght = eb_dotag(&new->node.branches, EB_RGHT); |
454 | 0 | new_leaf = eb_dotag(&new->node.branches, EB_LEAF); |
455 | 0 | old_leaf = eb_dotag(&old->node.branches, EB_LEAF); |
456 | |
|
457 | 0 | new->node.node_p = old->node.leaf_p; |
458 | | |
459 | | /* Right here, we have 3 possibilities : |
460 | | - the tree does not contain the key, and we have |
461 | | new->key < old->key. We insert new above old, on |
462 | | the left ; |
463 | | |
464 | | - the tree does not contain the key, and we have |
465 | | new->key > old->key. We insert new above old, on |
466 | | the right ; |
467 | | |
468 | | - the tree does contain the key, which implies it |
469 | | is alone. We add the new key next to it as a |
470 | | first duplicate. |
471 | | |
472 | | The last two cases can easily be partially merged. |
473 | | */ |
474 | | |
475 | 0 | if ((s64)new->key < (s64)old->key) { |
476 | 0 | new->node.leaf_p = new_left; |
477 | 0 | old->node.leaf_p = new_rght; |
478 | 0 | new->node.branches.b[EB_LEFT] = new_leaf; |
479 | 0 | new->node.branches.b[EB_RGHT] = old_leaf; |
480 | 0 | } else { |
481 | | /* we may refuse to duplicate this key if the tree is |
482 | | * tagged as containing only unique keys. |
483 | | */ |
484 | 0 | if ((new->key == old->key) && eb_gettag(root_right)) |
485 | 0 | return old; |
486 | | |
487 | | /* new->key >= old->key, new goes the right */ |
488 | 0 | old->node.leaf_p = new_left; |
489 | 0 | new->node.leaf_p = new_rght; |
490 | 0 | new->node.branches.b[EB_LEFT] = old_leaf; |
491 | 0 | new->node.branches.b[EB_RGHT] = new_leaf; |
492 | |
|
493 | 0 | if (new->key == old->key) { |
494 | 0 | new->node.bit = -1; |
495 | 0 | root->b[side] = eb_dotag(&new->node.branches, EB_NODE); |
496 | 0 | return new; |
497 | 0 | } |
498 | 0 | } |
499 | 0 | break; |
500 | 0 | } |
501 | | |
502 | | /* OK we're walking down this link */ |
503 | 0 | old = container_of(eb_untag(troot, EB_NODE), |
504 | 0 | struct eb64_node, node.branches); |
505 | |
|
506 | 0 | eb_prefetch(old->node.branches.b[0], 0); |
507 | 0 | eb_prefetch(old->node.branches.b[1], 0); |
508 | |
|
509 | 0 | old_node_bit = old->node.bit; |
510 | | |
511 | | /* Stop going down when we don't have common bits anymore. We |
512 | | * also stop in front of a duplicates tree because it means we |
513 | | * have to insert above. |
514 | | */ |
515 | |
|
516 | 0 | if ((old_node_bit < 0) || /* we're above a duplicate tree, stop here */ |
517 | 0 | (((new->key ^ old->key) >> old_node_bit) >= EB_NODE_BRANCHES)) { |
518 | | /* The tree did not contain the key, so we insert <new> before the node |
519 | | * <old>, and set ->bit to designate the lowest bit position in <new> |
520 | | * which applies to ->branches.b[]. |
521 | | */ |
522 | 0 | eb_troot_t *new_left, *new_rght; |
523 | 0 | eb_troot_t *new_leaf, *old_node; |
524 | |
|
525 | 0 | new_left = eb_dotag(&new->node.branches, EB_LEFT); |
526 | 0 | new_rght = eb_dotag(&new->node.branches, EB_RGHT); |
527 | 0 | new_leaf = eb_dotag(&new->node.branches, EB_LEAF); |
528 | 0 | old_node = eb_dotag(&old->node.branches, EB_NODE); |
529 | |
|
530 | 0 | new->node.node_p = old->node.node_p; |
531 | |
|
532 | 0 | if ((s64)new->key < (s64)old->key) { |
533 | 0 | new->node.leaf_p = new_left; |
534 | 0 | old->node.node_p = new_rght; |
535 | 0 | new->node.branches.b[EB_LEFT] = new_leaf; |
536 | 0 | new->node.branches.b[EB_RGHT] = old_node; |
537 | 0 | } |
538 | 0 | else if ((s64)new->key > (s64)old->key) { |
539 | 0 | old->node.node_p = new_left; |
540 | 0 | new->node.leaf_p = new_rght; |
541 | 0 | new->node.branches.b[EB_LEFT] = old_node; |
542 | 0 | new->node.branches.b[EB_RGHT] = new_leaf; |
543 | 0 | } |
544 | 0 | else { |
545 | 0 | struct eb_node *ret; |
546 | 0 | ret = eb_insert_dup(&old->node, &new->node); |
547 | 0 | return container_of(ret, struct eb64_node, node); |
548 | 0 | } |
549 | 0 | break; |
550 | 0 | } |
551 | | |
552 | | /* walk down */ |
553 | | |
554 | 0 | if (sizeof(long) >= 8) { |
555 | 0 | side = newkey >> old_node_bit; |
556 | 0 | } else { |
557 | | /* note: provides the best code on low-register count archs |
558 | | * such as i386. |
559 | | */ |
560 | 0 | side = newkey; |
561 | 0 | side >>= old_node_bit; |
562 | 0 | if (old_node_bit >= 32) { |
563 | 0 | side = newkey >> 32; |
564 | 0 | side >>= old_node_bit & 0x1F; |
565 | 0 | } |
566 | 0 | } |
567 | 0 | side &= EB_NODE_BRANCH_MASK; |
568 | 0 | troot = side ? old->node.branches.b[1] : old->node.branches.b[0]; |
569 | 0 | root = &old->node.branches; |
570 | 0 | } |
571 | | |
572 | | /* Ok, now we are inserting <new> between <root> and <old>. <old>'s |
573 | | * parent is already set to <new>, and the <root>'s branch is still in |
574 | | * <side>. Update the root's leaf till we have it. Note that we can also |
575 | | * find the side by checking the side of new->node.node_p. |
576 | | */ |
577 | | |
578 | | /* We need the common higher bits between new->key and old->key. |
579 | | * What differences are there between new->key and the node here ? |
580 | | * NOTE that bit(new) is always < bit(root) because highest |
581 | | * bit of new->key and old->key are identical here (otherwise they |
582 | | * would sit on different branches). |
583 | | */ |
584 | | // note that if EB_NODE_BITS > 1, we should check that it's still >= 0 |
585 | 0 | new->node.bit = fls64(new->key ^ old->key) - EB_NODE_BITS; |
586 | 0 | root->b[side] = eb_dotag(&new->node.branches, EB_NODE); |
587 | |
|
588 | 0 | return new; |
589 | 0 | } Unexecuted instantiation: cfgparse.c:__eb64i_insert Unexecuted instantiation: connection.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: server.c:__eb64i_insert Unexecuted instantiation: sock.c:__eb64i_insert Unexecuted instantiation: sock_inet.c:__eb64i_insert Unexecuted instantiation: stats-html.c:__eb64i_insert Unexecuted instantiation: stats.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: eb64tree.c:__eb64i_insert Unexecuted instantiation: ebimtree.c:__eb64i_insert Unexecuted instantiation: ebistree.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: proto_tcp.c:__eb64i_insert Unexecuted instantiation: h1_htx.c:__eb64i_insert Unexecuted instantiation: lru.c:__eb64i_insert |
590 | | |
591 | | #endif /* _EB64_TREE_H */ |