Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F47075485
rb_toy.c
dougm (Doug Moore)
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
dougm
Aug 22 2022, 7:13 AM
2022-08-22 07:13:59 (UTC+0)
Size
7 KB
Referenced Files
None
Subscribers
None
rb_toy.c
View Options
#include
<stdio.h>
#include
<stdlib.h>
#include
<stdbool.h>
#include
<string.h>
#include
<time.h>
struct
map_entry
;
#ifdef TEST_AUGMENTATION
#define RB_AUGMENT(entry) augment_entry(entry)
#define RB_AUGMENT_CHECK(entry) augment_entry_check(entry)
#endif
#include
"../../../sys/sys/tree.h"
RB_HEAD
(
entries_tree
,
map_entry
);
RB_PROTOTYPE
(
entries_tree
,
map_entry
,
rb_entry
,
cmp_entries
);
struct
map_entry
{
unsigned
start
;
unsigned
end
;
#ifdef TEST_AUGMENTATION
unsigned
first
;
unsigned
last
;
unsigned
free_down
;
#endif
RB_ENTRY
(
map_entry
)
rb_entry
;
};
#ifdef VERIFY
#include
<assert.h>
static
unsigned
num_nochange_augments
;
#endif
struct
entries_tree
rb_root
=
RB_INITIALIZER
(
root
);
static
int
verbose
=
0
;
static
int
cmp_entries
(
struct
map_entry
*
a
,
struct
map_entry
*
b
)
{
return
(
b
->
end
<
a
->
end
)
-
(
a
->
end
<
b
->
end
);
}
#ifdef TEST_AUGMENTATION
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#ifdef ORIG_AUG
void
augment_entry
(
struct
map_entry
*
entry
)
{
struct
map_entry
*
child
;
unsigned
free_down
;
free_down
=
0
;
if
((
child
=
RB_LEFT
(
entry
,
rb_entry
))
!=
NULL
)
{
free_down
=
MAX
(
free_down
,
child
->
free_down
);
free_down
=
MAX
(
free_down
,
entry
->
start
-
child
->
last
);
entry
->
first
=
child
->
first
;
}
else
entry
->
first
=
entry
->
start
;
if
((
child
=
RB_RIGHT
(
entry
,
rb_entry
))
!=
NULL
)
{
free_down
=
MAX
(
free_down
,
child
->
free_down
);
free_down
=
MAX
(
free_down
,
child
->
first
-
entry
->
end
);
entry
->
last
=
child
->
last
;
}
else
entry
->
last
=
entry
->
end
;
entry
->
free_down
=
free_down
;
}
#else
void
augment_entry
(
struct
map_entry
*
entry
)
{
struct
map_entry
*
left
,
*
right
;
unsigned
end
,
free_down
,
start
;
start
=
entry
->
start
;
end
=
entry
->
end
;
left
=
RB_LEFT
(
entry
,
rb_entry
);
right
=
RB_RIGHT
(
entry
,
rb_entry
);
if
(
left
!=
NULL
)
{
entry
->
first
=
left
->
first
;
free_down
=
start
-
left
->
last
;
if
(
right
!=
NULL
)
{
free_down
=
MAX
(
free_down
,
left
->
free_down
);
free_down
=
MAX
(
free_down
,
right
->
free_down
);
}
}
else
{
entry
->
first
=
start
;
free_down
=
0
;
}
if
(
right
!=
NULL
)
{
free_down
=
MAX
(
free_down
,
right
->
first
-
end
);
end
=
right
->
last
;
}
entry
->
last
=
end
;
entry
->
free_down
=
free_down
;
}
#endif
bool
augment_entry_check
(
struct
map_entry
*
entry
)
{
struct
map_entry
*
child
;
unsigned
bound
,
free_down
;
bool
changed
;
free_down
=
0
;
bound
=
entry
->
start
;
if
((
child
=
RB_LEFT
(
entry
,
rb_entry
))
!=
NULL
)
{
free_down
=
MAX
(
child
->
free_down
,
bound
-
child
->
last
);
bound
=
child
->
first
;
}
changed
=
entry
->
first
!=
bound
;
entry
->
first
=
bound
;
bound
=
entry
->
end
;
if
((
child
=
RB_RIGHT
(
entry
,
rb_entry
))
!=
NULL
)
{
free_down
=
MAX
(
free_down
,
child
->
free_down
);
free_down
=
MAX
(
free_down
,
child
->
first
-
bound
);
bound
=
child
->
last
;
}
changed
=
changed
||
(
entry
->
last
!=
bound
)
||
(
entry
->
free_down
!=
free_down
);
entry
->
last
=
bound
;
entry
->
free_down
=
free_down
;
#ifdef VERIFY
if
(
!
changed
)
++
num_nochange_augments
;
#endif
// if (verbose)
// printf("aug: [%u:%u]%d\n", entry->start, entry->end, changed);
return
(
changed
);
}
#endif
RB_GENERATE
(
entries_tree
,
map_entry
,
rb_entry
,
cmp_entries
);
#ifdef TEST_AUGMENTATION
/* Find the next entry that might abut a big-enough range. */
static
struct
map_entry
*
find_next
(
struct
map_entry
*
curr
,
unsigned
min_free
)
{
struct
map_entry
*
next
;
if
((
next
=
RB_RIGHT
(
curr
,
rb_entry
))
!=
NULL
&&
next
->
free_down
>=
min_free
)
{
/* Find next entry in right subtree. */
do
curr
=
next
;
while
((
next
=
RB_LEFT
(
curr
,
rb_entry
))
!=
NULL
&&
next
->
free_down
>=
min_free
);
}
else
{
/* Find next entry in a left-parent ancestor. */
while
((
next
=
RB_PARENT
(
curr
,
rb_entry
))
!=
NULL
&&
curr
==
RB_RIGHT
(
next
,
rb_entry
))
curr
=
next
;
curr
=
next
;
}
return
(
curr
);
}
static
int
find_space
(
unsigned
size
)
{
struct
map_entry
*
curr
,
*
first
;
struct
map_entry
*
entry
=
calloc
(
1
,
sizeof
(
*
entry
));
if
(
entry
==
NULL
)
return
(
-1
);
/*
* Find the first entry in the lower region that could abut a big-enough
* range.
*/
curr
=
RB_ROOT
(
&
rb_root
);
first
=
NULL
;
while
(
curr
!=
NULL
&&
curr
->
free_down
>=
size
)
{
first
=
curr
;
curr
=
RB_LEFT
(
curr
,
rb_entry
);
}
if
(
first
==
NULL
)
return
(
-1
);
/*
* Walk the big-enough ranges until one satisfies alignment
* requirements, or violates lowaddr address requirement.
*/
for
(
curr
=
first
;
curr
!=
NULL
;
curr
=
find_next
(
curr
,
size
))
{
if
((
first
=
RB_LEFT
(
curr
,
rb_entry
))
!=
NULL
)
{
if
(
curr
->
start
-
first
->
last
>=
size
)
{
entry
->
start
=
first
->
last
;
entry
->
end
=
entry
->
start
+
size
;
RB_INSERT
(
entries_tree
,
&
rb_root
,
entry
);
return
(
0
);
}
}
if
((
first
=
RB_RIGHT
(
curr
,
rb_entry
))
!=
NULL
)
{
if
(
first
->
first
-
curr
->
end
>=
size
)
{
entry
->
start
=
curr
->
end
;
entry
->
end
=
entry
->
start
+
size
;
RB_INSERT
(
entries_tree
,
&
rb_root
,
entry
);
return
(
0
);
}
}
}
free
(
entry
);
return
(
-1
);
}
#endif
static
int
dump_tree
(
struct
map_entry
*
element
,
int
depth
)
{
int
lh
,
rh
;
if
(
element
==
NULL
)
return
0
;
__uintptr_t
bits
=
RB_BITS
(
element
,
rb_entry
);
rh
=
(
bits
&
RB_RED_R
)
?
2
:
1
;
rh
+=
dump_tree
(
RB_RIGHT
(
element
,
rb_entry
),
depth
+
rh
);
if
(
verbose
)
{
printf
(
"%*s[%u:%u]"
,
4
*
depth
,
""
,
element
->
start
,
element
->
end
);
#ifdef TEST_AUGMENTATION
printf
(
":%u"
,
element
->
free_down
);
#endif
printf
(
"
\n
"
);
}
lh
=
(
bits
&
RB_RED_R
)
?
2
:
1
;
lh
+=
dump_tree
(
RB_LEFT
(
element
,
rb_entry
),
depth
+
lh
);
#ifdef VERIFY
assert
(
lh
==
rh
);
assert
(
lh
!=
2
||
RB_LEFT
(
element
,
rb_entry
)
!=
NULL
||
RB_RIGHT
(
element
,
rb_entry
)
!=
NULL
);
#ifdef TEST_AUGMENTATION
rh
=
augment_entry_check
(
element
);
assert
(
!
rh
);
#endif
#endif
return
(
lh
);
}
int
main
()
{
struct
timespec
tp1
,
tp2
;
struct
map_entry
*
element
;
const
unsigned
maxval
=
65536
;
struct
map_entry
nodes
[
65536
];
for
(
int
i
=
0
;
i
<
maxval
;
++
i
)
{
nodes
[
i
].
start
=
0
;
nodes
[
i
].
end
=
i
;
}
for
(
int
i
=
0
;
i
<
maxval
;
++
i
)
{
int
r
=
i
+
random
()
%
(
maxval
-
i
);
unsigned
x
=
nodes
[
r
].
end
;
nodes
[
r
].
end
=
nodes
[
i
].
end
;
nodes
[
i
].
end
=
x
;
}
#ifdef REM_ONLY
struct
map_entry
backup
[
65536
];
struct
map_entry
*
back_root
;
for
(
int
i
=
0
;
i
<
maxval
;
++
i
)
RB_INSERT
(
entries_tree
,
&
rb_root
,
&
nodes
[
i
]);
memcpy
(
backup
,
nodes
,
sizeof
(
nodes
));
back_root
=
RB_ROOT
(
&
rb_root
);
#endif
clock_gettime
(
CLOCK_REALTIME_PRECISE
,
&
tp1
);
#ifdef INSERT_FIRST_FREE
element
=
malloc
(
sizeof
(
*
element
));
element
->
start
=
0
;
element
->
end
=
0
;
RB_INSERT
(
entries_tree
,
&
rb_root
,
element
);
element
=
malloc
(
sizeof
(
*
element
));
element
->
start
=
maxval
+
1
;
element
->
end
=
maxval
+
1
;
RB_INSERT
(
entries_tree
,
&
rb_root
,
element
);
#endif
#ifdef PLAIN
for
(
int
i
=
0
;
i
<
maxval
/
2
;
++
i
)
RB_INSERT
(
entries_tree
,
&
rb_root
,
&
nodes
[
i
]);
for
(
int
i
=
0
;
i
<
4095
*
maxval
;
++
i
)
{
int
j
=
i
+
maxval
/
2
;
RB_INSERT
(
entries_tree
,
&
rb_root
,
&
nodes
[
j
%
maxval
]);
RB_REMOVE
(
entries_tree
,
&
rb_root
,
&
nodes
[
i
%
maxval
]);
}
for
(
int
i
=
0
;
i
<
maxval
/
2
;
++
i
)
RB_REMOVE
(
entries_tree
,
&
rb_root
,
&
nodes
[
i
]);
#endif
#ifdef INS_ONLY
for
(
int
j
=
0
;
j
<
4096
;
++
j
)
{
for
(
int
i
=
0
;
i
<
maxval
;
++
i
)
{
int
k
=
(
i
+
j
)
%
maxval
;
RB_INSERT
(
entries_tree
,
&
rb_root
,
&
nodes
[
k
]);
}
RB_INIT
(
&
rb_root
);
}
#endif
#ifdef REM_ONLY
for
(
int
j
=
0
;
j
<
8192
;
++
j
)
{
for
(
int
i
=
0
;
i
<
maxval
;
++
i
)
{
int
k
=
(
i
+
j
)
%
maxval
;
RB_REMOVE
(
entries_tree
,
&
rb_root
,
&
nodes
[
k
]);
}
memcpy
(
nodes
,
backup
,
sizeof
(
nodes
));
RB_ROOT
(
&
rb_root
)
=
back_root
;
}
#endif
#ifdef TEST_AUGMENTATION
#ifdef VERIFY
num_nochange_augments
=
0
;
#endif
#endif
#ifdef INSERT_FIRST_FREE
find_space
(
1
);
#else
#endif
#ifdef VERIFY
assert
(
num_nochange_augments
<=
1
);
dump_tree
(
RB_ROOT
(
&
rb_root
),
0
);
#else
if
(
verbose
)
dump_tree
(
RB_ROOT
(
&
rb_root
),
0
);
#endif
clock_gettime
(
CLOCK_REALTIME_PRECISE
,
&
tp2
);
int
borrow
=
tp2
.
tv_nsec
<
tp1
.
tv_nsec
;
printf
(
"%ld.%09ld
\n
"
,
tp2
.
tv_sec
-
tp1
.
tv_sec
-
borrow
,
tp2
.
tv_nsec
-
tp1
.
tv_nsec
+
borrow
*
1000000000
);
return
(
0
);
}
File Metadata
Details
Attached
Mime Type
text/x-c
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5081302
Default Alt Text
rb_toy.c (7 KB)
Attached To
Mode
D36288: rb_tree: optimize removal
Attached
Detach File
Event Timeline
Log In to Comment