File indexing completed on 2025-05-11 08:24:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031
0032 #include "tmacros.h"
0033
0034 #include <rtems.h>
0035 #include <rtems/rbheap.h>
0036 #include <rtems/malloc.h>
0037 #include <rtems/score/rbtreeimpl.h>
0038
0039 const char rtems_test_name[] = "RBHEAP 1";
0040
0041
0042 static rtems_task Init(rtems_task_argument argument);
0043
0044 #define TEST_PAGE_SIZE 1024
0045
0046 #define TEST_PAGE_COUNT 8
0047
0048 static char area [TEST_PAGE_SIZE * TEST_PAGE_COUNT + TEST_PAGE_SIZE - 1];
0049
0050 static rtems_rbheap_chunk chunks [TEST_PAGE_COUNT];
0051
0052 static void extend_descriptors(rtems_rbheap_control *control)
0053 {
0054 rtems_chain_control *chain =
0055 rtems_rbheap_get_spare_descriptor_chain(control);
0056
0057 rtems_rbheap_set_extend_descriptors(
0058 control,
0059 rtems_rbheap_extend_descriptors_never
0060 );
0061
0062 rtems_chain_initialize(
0063 chain,
0064 chunks,
0065 TEST_PAGE_COUNT,
0066 sizeof(chunks [0])
0067 );
0068 }
0069
0070 static uintptr_t idx(const rtems_rbheap_chunk *chunk)
0071 {
0072 uintptr_t base = (uintptr_t) area;
0073 uintptr_t excess = base % TEST_PAGE_SIZE;
0074
0075 if (excess > 0) {
0076 base += TEST_PAGE_SIZE - excess;
0077 }
0078
0079 return (chunk->begin - base) / TEST_PAGE_SIZE;
0080 }
0081
0082 typedef struct {
0083 uintptr_t index;
0084 bool free;
0085 } chunk_descriptor;
0086
0087 typedef struct {
0088 const chunk_descriptor *chunk_current;
0089 const chunk_descriptor *chunk_end;
0090 } chunk_visitor_context;
0091
0092 static bool chunk_visitor(
0093 const RBTree_Node *node,
0094 void *visitor_arg
0095 )
0096 {
0097 rtems_rbheap_chunk *chunk = rtems_rbheap_chunk_of_node(node);
0098 chunk_visitor_context *context = visitor_arg;
0099 const chunk_descriptor *current = context->chunk_current;
0100
0101 rtems_test_assert(current != context->chunk_end);
0102
0103 rtems_test_assert(idx(chunk) == current->index);
0104 rtems_test_assert(rtems_rbheap_is_chunk_free(chunk) == current->free);
0105
0106 context->chunk_current = current + 1;
0107
0108 return false;
0109 }
0110
0111 static void test_init_begin_greater_than_end(void)
0112 {
0113 rtems_status_code sc = RTEMS_SUCCESSFUL;
0114 rtems_rbheap_control control;
0115
0116 sc = rtems_rbheap_initialize(
0117 &control,
0118 (void *) TEST_PAGE_SIZE,
0119 (uintptr_t) -TEST_PAGE_SIZE,
0120 TEST_PAGE_SIZE,
0121 extend_descriptors,
0122 NULL
0123 );
0124 rtems_test_assert(sc == RTEMS_INVALID_ADDRESS);
0125 }
0126
0127 static void test_init_begin_greater_than_aligned_begin(void)
0128 {
0129 rtems_status_code sc = RTEMS_SUCCESSFUL;
0130 rtems_rbheap_control control;
0131
0132 sc = rtems_rbheap_initialize(
0133 &control,
0134 (void *) -(TEST_PAGE_SIZE / 2),
0135 TEST_PAGE_SIZE,
0136 TEST_PAGE_SIZE,
0137 extend_descriptors,
0138 NULL
0139 );
0140 rtems_test_assert(sc == RTEMS_INVALID_ADDRESS);
0141 }
0142
0143 static void test_init_aligned_begin_greater_than_aligned_end(void)
0144 {
0145 rtems_status_code sc = RTEMS_SUCCESSFUL;
0146 rtems_rbheap_control control;
0147
0148 sc = rtems_rbheap_initialize(
0149 &control,
0150 (void *) TEST_PAGE_SIZE,
0151 TEST_PAGE_SIZE / 2,
0152 TEST_PAGE_SIZE,
0153 extend_descriptors,
0154 NULL
0155 );
0156 rtems_test_assert(sc == RTEMS_INVALID_ADDRESS);
0157 }
0158
0159 static void test_init_empty_descriptors(void)
0160 {
0161 rtems_status_code sc = RTEMS_SUCCESSFUL;
0162 rtems_rbheap_control control;
0163
0164 sc = rtems_rbheap_initialize(
0165 &control,
0166 (void *) TEST_PAGE_SIZE,
0167 TEST_PAGE_SIZE,
0168 TEST_PAGE_SIZE,
0169 rtems_rbheap_extend_descriptors_never,
0170 NULL
0171 );
0172 rtems_test_assert(sc == RTEMS_NO_MEMORY);
0173 }
0174
0175 static void test_chunk_tree(
0176 const rtems_rbheap_control *control,
0177 const chunk_descriptor *chunk_begin,
0178 size_t chunk_count
0179 )
0180 {
0181 chunk_visitor_context context = {
0182 .chunk_current = chunk_begin,
0183 .chunk_end = chunk_begin + chunk_count
0184 };
0185
0186 rtems_test_assert(
0187 rtems_chain_node_count_unprotected(&control->spare_descriptor_chain)
0188 == TEST_PAGE_COUNT - chunk_count
0189 );
0190
0191 _RBTree_Iterate(
0192 &control->chunk_tree,
0193 chunk_visitor,
0194 &context
0195 );
0196 }
0197
0198 #define TEST_PAGE_TREE(control, chunks) \
0199 test_chunk_tree( \
0200 control, \
0201 chunks, \
0202 RTEMS_ARRAY_SIZE(chunks) \
0203 )
0204
0205 static void test_init_successful(rtems_rbheap_control *control)
0206 {
0207 static const chunk_descriptor chunks [] = {
0208 { 0, true }
0209 };
0210
0211 rtems_status_code sc = RTEMS_SUCCESSFUL;
0212
0213 sc = rtems_rbheap_initialize(
0214 control,
0215 area,
0216 sizeof(area),
0217 TEST_PAGE_SIZE,
0218 extend_descriptors,
0219 NULL
0220 );
0221 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0222
0223 TEST_PAGE_TREE(control, chunks);
0224 }
0225
0226 static void test_alloc_and_free_one(void)
0227 {
0228 static const chunk_descriptor chunks_0 [] = {
0229 { 0, true },
0230 { TEST_PAGE_COUNT - 1, false }
0231 };
0232 static const chunk_descriptor chunks_1 [] = {
0233 { 0, true }
0234 };
0235
0236 rtems_status_code sc = RTEMS_SUCCESSFUL;
0237 rtems_rbheap_control control;
0238 void *ptr = NULL;
0239
0240 test_init_successful(&control);
0241
0242 ptr = rtems_rbheap_allocate(&control, TEST_PAGE_SIZE);
0243 rtems_test_assert(ptr != NULL);
0244
0245 TEST_PAGE_TREE(&control, chunks_0);
0246
0247 sc = rtems_rbheap_free(&control, ptr);
0248 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0249
0250 TEST_PAGE_TREE(&control, chunks_1);
0251 }
0252
0253 static void test_alloc_zero(void)
0254 {
0255 static const chunk_descriptor chunks [] = {
0256 { 0, true }
0257 };
0258
0259 rtems_rbheap_control control;
0260 void *ptr = NULL;
0261
0262 test_init_successful(&control);
0263
0264 ptr = rtems_rbheap_allocate(&control, 0);
0265 rtems_test_assert(ptr == NULL);
0266
0267 TEST_PAGE_TREE(&control, chunks);
0268 }
0269
0270 static void test_alloc_huge_chunk(void)
0271 {
0272 static const chunk_descriptor chunks [] = {
0273 { 0, true }
0274 };
0275
0276 rtems_rbheap_control control;
0277 void *ptr = NULL;
0278
0279 test_init_successful(&control);
0280
0281 ptr = rtems_rbheap_allocate(&control, (TEST_PAGE_COUNT + 1) * TEST_PAGE_SIZE);
0282 rtems_test_assert(ptr == NULL);
0283
0284 TEST_PAGE_TREE(&control, chunks);
0285 }
0286
0287 static void test_alloc_one_chunk(void)
0288 {
0289 static const chunk_descriptor chunks_0 [] = {
0290 { 0, false }
0291 };
0292 static const chunk_descriptor chunks_1 [] = {
0293 { 0, true },
0294 };
0295
0296 rtems_status_code sc = RTEMS_SUCCESSFUL;
0297 rtems_rbheap_control control;
0298 void *ptr = NULL;
0299
0300 test_init_successful(&control);
0301
0302 ptr = rtems_rbheap_allocate(&control, TEST_PAGE_COUNT * TEST_PAGE_SIZE);
0303 rtems_test_assert(ptr != NULL);
0304
0305 TEST_PAGE_TREE(&control, chunks_0);
0306
0307 sc = rtems_rbheap_free(&control, ptr);
0308 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0309
0310 TEST_PAGE_TREE(&control, chunks_1);
0311 }
0312
0313 static void test_alloc_many_chunks(void)
0314 {
0315 static const chunk_descriptor chunks_0 [] = {
0316 { 0, false },
0317 { 1, false },
0318 { 2, false },
0319 { 3, false },
0320 { 4, false },
0321 { 5, false },
0322 { 6, false },
0323 { 7, false }
0324 };
0325 static const chunk_descriptor chunks_1 [] = {
0326 { 0, true }
0327 };
0328
0329 rtems_status_code sc = RTEMS_SUCCESSFUL;
0330 rtems_rbheap_control control;
0331 void *ptr [TEST_PAGE_COUNT];
0332 void *null = NULL;
0333 int i = 0;
0334
0335 test_init_successful(&control);
0336
0337 for (i = 0; i < TEST_PAGE_COUNT; ++i) {
0338 ptr [i] = rtems_rbheap_allocate(&control, TEST_PAGE_SIZE);
0339 rtems_test_assert(ptr [i] != NULL);
0340 }
0341
0342 TEST_PAGE_TREE(&control, chunks_0);
0343
0344 null = rtems_rbheap_allocate(&control, TEST_PAGE_SIZE);
0345 rtems_test_assert(null == NULL);
0346
0347 TEST_PAGE_TREE(&control, chunks_0);
0348
0349 for (i = 0; i < TEST_PAGE_COUNT; ++i) {
0350 sc = rtems_rbheap_free(&control, ptr [i]);
0351 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0352 }
0353
0354 TEST_PAGE_TREE(&control, chunks_1);
0355 }
0356
0357 static void test_alloc_misaligned(void)
0358 {
0359 rtems_rbheap_control control;
0360 void *p;
0361
0362 test_init_successful(&control);
0363
0364 p = rtems_rbheap_allocate(&control, TEST_PAGE_SIZE - 1);
0365 rtems_test_assert(p != NULL);
0366 }
0367
0368 static void test_alloc_with_malloc_extend(void)
0369 {
0370 rtems_status_code sc;
0371 rtems_rbheap_control control;
0372 void *p;
0373 void *opaque;
0374
0375 sc = rtems_rbheap_initialize(
0376 &control,
0377 area,
0378 sizeof(area),
0379 TEST_PAGE_SIZE,
0380 rtems_rbheap_extend_descriptors_with_malloc,
0381 NULL
0382 );
0383 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0384
0385 opaque = rtems_heap_greedy_allocate(NULL, 0);
0386
0387 p = rtems_rbheap_allocate(&control, TEST_PAGE_SIZE);
0388 rtems_test_assert(p == NULL);
0389
0390 rtems_heap_greedy_free(opaque);
0391
0392 p = rtems_rbheap_allocate(&control, TEST_PAGE_SIZE);
0393 rtems_test_assert(p != NULL);
0394 }
0395
0396 static void test_free_null(void)
0397 {
0398 rtems_status_code sc = RTEMS_SUCCESSFUL;
0399 rtems_rbheap_control control;
0400
0401 test_init_successful(&control);
0402
0403 sc = rtems_rbheap_free(&control, NULL);
0404 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0405 }
0406
0407 static void test_free_invalid(void)
0408 {
0409 rtems_status_code sc = RTEMS_SUCCESSFUL;
0410 rtems_rbheap_control control;
0411
0412 test_init_successful(&control);
0413
0414 sc = rtems_rbheap_free(&control, (void *) 1);
0415 rtems_test_assert(sc == RTEMS_INVALID_ID);
0416 }
0417
0418 static void test_free_double(void)
0419 {
0420 rtems_status_code sc = RTEMS_SUCCESSFUL;
0421 rtems_rbheap_control control;
0422 void *ptr = NULL;
0423
0424 test_init_successful(&control);
0425
0426 ptr = rtems_rbheap_allocate(&control, TEST_PAGE_COUNT * TEST_PAGE_SIZE);
0427 rtems_test_assert(ptr != NULL);
0428
0429 sc = rtems_rbheap_free(&control, ptr);
0430 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0431
0432 sc = rtems_rbheap_free(&control, ptr);
0433 rtems_test_assert(sc == RTEMS_INCORRECT_STATE);
0434 }
0435
0436 enum {
0437 LOW,
0438 LEFT,
0439 MIDDLE,
0440 RIGHT,
0441 HIGH
0442 };
0443
0444 static void test_free_merge_left_or_right(bool left)
0445 {
0446 static const chunk_descriptor chunks_0 [] = {
0447 { 0, true },
0448 { 3, false },
0449 { 4, false },
0450 { 5, false },
0451 { 6, false },
0452 { 7, false }
0453 };
0454 static const chunk_descriptor chunks_1_left [] = {
0455 { 0, true },
0456 { 3, false },
0457 { 4, true },
0458 { 5, false },
0459 { 6, false },
0460 { 7, false }
0461 };
0462 static const chunk_descriptor chunks_1_right [] = {
0463 { 0, true },
0464 { 3, false },
0465 { 4, false },
0466 { 5, false },
0467 { 6, true },
0468 { 7, false }
0469 };
0470 static const chunk_descriptor chunks_2_left [] = {
0471 { 0, true },
0472 { 3, false },
0473 { 4, true },
0474 { 6, false },
0475 { 7, false }
0476 };
0477 static const chunk_descriptor chunks_2_right [] = {
0478 { 0, true },
0479 { 3, false },
0480 { 4, false },
0481 { 5, true },
0482 { 7, false }
0483 };
0484
0485 rtems_status_code sc = RTEMS_SUCCESSFUL;
0486 rtems_rbheap_control control;
0487 void *ptr [HIGH + 1];
0488 int dir = left ? LEFT : RIGHT;
0489 int i = 0;
0490
0491 test_init_successful(&control);
0492
0493 for (i = sizeof(ptr) / sizeof(ptr [0]) - 1; i >= 0; --i) {
0494 ptr [i] = rtems_rbheap_allocate(&control, TEST_PAGE_SIZE);
0495 rtems_test_assert(ptr [i] != NULL);
0496 }
0497
0498 TEST_PAGE_TREE(&control, chunks_0);
0499
0500 sc = rtems_rbheap_free(&control, ptr [dir]);
0501 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0502
0503 if (left) {
0504 TEST_PAGE_TREE(&control, chunks_1_left);
0505 } else {
0506 TEST_PAGE_TREE(&control, chunks_1_right);
0507 }
0508
0509 sc = rtems_rbheap_free(&control, ptr [MIDDLE]);
0510 rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0511
0512 if (left) {
0513 TEST_PAGE_TREE(&control, chunks_2_left);
0514 } else {
0515 TEST_PAGE_TREE(&control, chunks_2_right);
0516 }
0517 }
0518
0519 static void Init(rtems_task_argument arg)
0520 {
0521 TEST_BEGIN();
0522
0523 test_init_begin_greater_than_end();
0524 test_init_begin_greater_than_aligned_begin();
0525 test_init_aligned_begin_greater_than_aligned_end();
0526 test_init_empty_descriptors();
0527 test_alloc_and_free_one();
0528 test_alloc_zero();
0529 test_alloc_huge_chunk();
0530 test_alloc_one_chunk();
0531 test_alloc_many_chunks();
0532 test_alloc_misaligned();
0533 test_alloc_with_malloc_extend();
0534 test_free_null();
0535 test_free_invalid();
0536 test_free_double();
0537 test_free_merge_left_or_right(true);
0538 test_free_merge_left_or_right(false);
0539
0540 TEST_END();
0541
0542 rtems_test_exit(0);
0543 }
0544
0545 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0546 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0547
0548 #define CONFIGURE_MAXIMUM_TASKS 1
0549
0550 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0551
0552 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0553
0554 #define CONFIGURE_INIT
0555
0556 #include <rtems/confdefs.h>