3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
11 static void *ngx_radix_alloc(ngx_radix_tree_t
*tree
);
15 ngx_radix_tree_create(ngx_pool_t
*pool
, ngx_int_t preallocate
)
17 uint32_t key
, mask
, inc
;
18 ngx_radix_tree_t
*tree
;
20 if (!(tree
= ngx_palloc(pool
, sizeof(ngx_radix_tree_t
)))) {
29 if (!(tree
->root
= ngx_radix_alloc(tree
))) {
33 tree
->root
->right
= NULL
;
34 tree
->root
->left
= NULL
;
35 tree
->root
->parent
= NULL
;
36 tree
->root
->value
= NGX_RADIX_NO_VALUE
;
38 if (preallocate
== 0) {
43 * We preallocate the first nodes: 0, 1, 00, 01, 10, 11, 000, 001, etc.,
44 * to increase the TLB hits even if for the first lookup iterations.
45 * On the 32-bit platforms the 7 preallocated bits takes continuous 4K,
46 * 8 - 8K, 9 - 16K, etc. On the 64-bit platforms the 6 preallocated bits
47 * takes continuous 4K, 7 - 8K, 8 - 16K, etc. There is no sense to
48 * to preallocate more than one page, because further preallocation
49 * distribute the only bit per page. Instead, the random insertion
50 * may distribute several bits per page.
52 * Thus, by default we preallocate maximum
53 * 6 bits on amd64 (64-bit platform and 4K pages)
54 * 7 bits on i386 (32-bit platform and 4K pages)
55 * 7 bits on sparc64 in 64-bit mode (8K pages)
56 * 8 bits on sparc64 in 32-bit mode (8K pages)
59 if (preallocate
== -1) {
60 switch (ngx_pagesize
/ sizeof(ngx_radix_tree_t
)) {
72 /* sparc64 in 32-bit mode */
81 while (preallocate
--) {
88 if (ngx_radix32tree_insert(tree
, key
, mask
, NGX_RADIX_NO_VALUE
)
106 ngx_radix32tree_insert(ngx_radix_tree_t
*tree
, uint32_t key
, uint32_t mask
,
110 ngx_radix_node_t
*node
, *next
;
134 if (node
->value
!= NGX_RADIX_NO_VALUE
) {
143 if (!(next
= ngx_radix_alloc(tree
))) {
150 next
->value
= NGX_RADIX_NO_VALUE
;
170 ngx_radix32tree_delete(ngx_radix_tree_t
*tree
, uint32_t key
, uint32_t mask
)
173 ngx_radix_node_t
*node
;
178 while (node
&& (bit
& mask
)) {
193 if (node
->right
|| node
->left
) {
194 if (node
->value
!= NGX_RADIX_NO_VALUE
) {
195 node
->value
= NGX_RADIX_NO_VALUE
;
203 if (node
->parent
->right
== node
) {
204 node
->parent
->right
= NULL
;
206 node
->parent
->left
= NULL
;
209 node
->right
= tree
->free
;
216 || node
->value
!= NGX_RADIX_NO_VALUE
217 || node
->parent
== NULL
)
228 ngx_radix32tree_find(ngx_radix_tree_t
*tree
, uint32_t key
)
232 ngx_radix_node_t
*node
;
235 value
= NGX_RADIX_NO_VALUE
;
239 if (node
->value
!= NGX_RADIX_NO_VALUE
) {
258 ngx_radix_alloc(ngx_radix_tree_t
*tree
)
263 p
= (char *) tree
->free
;
264 tree
->free
= tree
->free
->right
;
268 if (tree
->size
< sizeof(ngx_radix_node_t
)) {
269 if (!(tree
->start
= ngx_palloc(tree
->pool
, ngx_pagesize
))) {
273 tree
->size
= ngx_pagesize
;
277 tree
->start
+= sizeof(ngx_radix_node_t
);
278 tree
->size
-= sizeof(ngx_radix_node_t
);