forked from Imagelibrary/rtems
rbheap: Fix rtems_rbheap_free()
Remove unused descriptor of merged free chunks from the free chain and add them to the spare descriptors. Close #2417.
This commit is contained in:
@@ -7,10 +7,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
* Copyright (c) 2012-2015 embedded brains GmbH. All rights reserved.
|
||||||
*
|
*
|
||||||
* embedded brains GmbH
|
* embedded brains GmbH
|
||||||
* Obere Lagerstr. 30
|
* Dornierstr. 4
|
||||||
* 82178 Puchheim
|
* 82178 Puchheim
|
||||||
* Germany
|
* Germany
|
||||||
* <rtems@embedded-brains.de>
|
* <rtems@embedded-brains.de>
|
||||||
@@ -225,24 +225,17 @@ static rtems_rbheap_chunk *succ(const rtems_rbheap_chunk *chunk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void check_and_merge(
|
static void check_and_merge(
|
||||||
rtems_chain_control *free_chain,
|
rtems_rbheap_control *control,
|
||||||
rtems_rbtree_control *chunk_tree,
|
|
||||||
rtems_rbheap_chunk *a,
|
rtems_rbheap_chunk *a,
|
||||||
rtems_rbheap_chunk *b
|
rtems_rbheap_chunk *b,
|
||||||
|
rtems_rbheap_chunk *c
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (b != NULL_PAGE && rtems_rbheap_is_chunk_free(b)) {
|
if (c != NULL_PAGE && rtems_rbheap_is_chunk_free(c)) {
|
||||||
if (b->begin < a->begin) {
|
|
||||||
rtems_rbheap_chunk *t = a;
|
|
||||||
|
|
||||||
a = b;
|
|
||||||
b = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
a->size += b->size;
|
a->size += b->size;
|
||||||
rtems_chain_extract_unprotected(&b->chain_node);
|
rtems_chain_extract_unprotected(&b->chain_node);
|
||||||
add_to_chain(free_chain, b);
|
rtems_rbheap_add_to_spare_descriptor_chain(control, b);
|
||||||
rtems_rbtree_extract(chunk_tree, &b->tree_node);
|
rtems_rbtree_extract(&control->chunk_tree, &b->tree_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,15 +244,17 @@ rtems_status_code rtems_rbheap_free(rtems_rbheap_control *control, void *ptr)
|
|||||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||||
|
|
||||||
if (ptr != NULL) {
|
if (ptr != NULL) {
|
||||||
rtems_chain_control *free_chain = &control->free_chunk_chain;
|
rtems_rbheap_chunk *chunk = find(&control->chunk_tree, (uintptr_t) ptr);
|
||||||
rtems_rbtree_control *chunk_tree = &control->chunk_tree;
|
|
||||||
rtems_rbheap_chunk *chunk = find(chunk_tree, (uintptr_t) ptr);
|
|
||||||
|
|
||||||
if (chunk != NULL_PAGE) {
|
if (chunk != NULL_PAGE) {
|
||||||
if (!rtems_rbheap_is_chunk_free(chunk)) {
|
if (!rtems_rbheap_is_chunk_free(chunk)) {
|
||||||
check_and_merge(free_chain, chunk_tree, chunk, succ(chunk));
|
rtems_rbheap_chunk *other;
|
||||||
add_to_chain(free_chain, chunk);
|
|
||||||
check_and_merge(free_chain, chunk_tree, chunk, pred(chunk));
|
add_to_chain(&control->free_chunk_chain, chunk);
|
||||||
|
other = succ(chunk);
|
||||||
|
check_and_merge(control, chunk, other, other);
|
||||||
|
other = pred(chunk);
|
||||||
|
check_and_merge(control, other, chunk, other);
|
||||||
} else {
|
} else {
|
||||||
sc = RTEMS_INCORRECT_STATE;
|
sc = RTEMS_INCORRECT_STATE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,6 +170,11 @@ static void test_chunk_tree(
|
|||||||
.chunk_end = chunk_begin + chunk_count
|
.chunk_end = chunk_begin + chunk_count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rtems_test_assert(
|
||||||
|
rtems_chain_node_count_unprotected(&control->spare_descriptor_chain)
|
||||||
|
== PAGE_COUNT - chunk_count
|
||||||
|
);
|
||||||
|
|
||||||
_RBTree_Iterate(
|
_RBTree_Iterate(
|
||||||
&control->chunk_tree,
|
&control->chunk_tree,
|
||||||
chunk_visitor,
|
chunk_visitor,
|
||||||
|
|||||||
Reference in New Issue
Block a user