Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/tools/testing/memblock/tests/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 10 kB image not shown  

Quelle  alloc_helpers_api.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
#include "alloc_helpers_api.h"

/*
 * A simple test that tries to allocate a memory region above a specified,
 * aligned address:
 *
 *             +
 *  |          +-----------+         |
 *  |          |    rgn    |         |
 *  +----------+-----------+---------+
 *             ^
 *             |
 *             Aligned min_addr
 *
 * Expect to allocate a cleared region at the minimal memory address.
 */

static int alloc_from_simple_generic_check(void)
{
 struct memblock_region *rgn = &memblock.reserved.regions[0];
 void *allocated_ptr = NULL;
 phys_addr_t size = SZ_16;
 phys_addr_t min_addr;

 PREFIX_PUSH();
 setup_memblock();

 min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES;

 allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);

 ASSERT_NE(allocated_ptr, NULL);
 ASSERT_MEM_EQ(allocated_ptr, 0, size);

 ASSERT_EQ(rgn->size, size);
 ASSERT_EQ(rgn->base, min_addr);

 ASSERT_EQ(memblock.reserved.cnt, 1);
 ASSERT_EQ(memblock.reserved.total_size, size);

 test_pass_pop();

 return 0;
}

/*
 * A test that tries to allocate a memory region above a certain address.
 * The minimal address here is not aligned:
 *
 *         +      +
 *  |      +      +---------+            |
 *  |      |      |   rgn   |            |
 *  +------+------+---------+------------+
 *         ^      ^------.
 *         |             |
 *       min_addr        Aligned address
 *                       boundary
 *
 * Expect to allocate a cleared region at the closest aligned memory address.
 */

static int alloc_from_misaligned_generic_check(void)
{
 struct memblock_region *rgn = &memblock.reserved.regions[0];
 void *allocated_ptr = NULL;
 phys_addr_t size = SZ_32;
 phys_addr_t min_addr;

 PREFIX_PUSH();
 setup_memblock();

 /* A misaligned address */
 min_addr = memblock_end_of_DRAM() - (SMP_CACHE_BYTES * 2 - 1);

 allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);

 ASSERT_NE(allocated_ptr, NULL);
 ASSERT_MEM_EQ(allocated_ptr, 0, size);

 ASSERT_EQ(rgn->size, size);
 ASSERT_EQ(rgn->base, memblock_end_of_DRAM() - SMP_CACHE_BYTES);

 ASSERT_EQ(memblock.reserved.cnt, 1);
 ASSERT_EQ(memblock.reserved.total_size, size);

 test_pass_pop();

 return 0;
}

/*
 * A test that tries to allocate a memory region above an address that is too
 * close to the end of the memory:
 *
 *              +        +
 *  |           +--------+---+      |
 *  |           |   rgn  +   |      |
 *  +-----------+--------+---+------+
 *              ^        ^
 *              |        |
 *              |        min_addr
 *              |
 *              Aligned address
 *              boundary
 *
 * Expect to prioritize granting memory over satisfying the minimal address
 * requirement.
 */

static int alloc_from_top_down_high_addr_check(void)
{
 struct memblock_region *rgn = &memblock.reserved.regions[0];
 void *allocated_ptr = NULL;
 phys_addr_t size = SZ_32;
 phys_addr_t min_addr;

 PREFIX_PUSH();
 setup_memblock();

 /* The address is too close to the end of the memory */
 min_addr = memblock_end_of_DRAM() - SZ_16;

 allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);

 ASSERT_NE(allocated_ptr, NULL);
 ASSERT_EQ(rgn->size, size);
 ASSERT_EQ(rgn->base, memblock_end_of_DRAM() - SMP_CACHE_BYTES);

 ASSERT_EQ(memblock.reserved.cnt, 1);
 ASSERT_EQ(memblock.reserved.total_size, size);

 test_pass_pop();

 return 0;
}

/*
 * A test that tries to allocate a memory region when there is no space
 * available above the minimal address above a certain address:
 *
 *                     +
 *  |        +---------+-------------|
 *  |        |   rgn   |             |
 *  +--------+---------+-------------+
 *                     ^
 *                     |
 *                     min_addr
 *
 * Expect to prioritize granting memory over satisfying the minimal address
 * requirement and to allocate next to the previously reserved region. The
 * regions get merged into one.
 */

static int alloc_from_top_down_no_space_above_check(void)
{
 struct memblock_region *rgn = &memblock.reserved.regions[0];
 void *allocated_ptr = NULL;
 phys_addr_t r1_size = SZ_64;
 phys_addr_t r2_size = SZ_2;
 phys_addr_t total_size = r1_size + r2_size;
 phys_addr_t min_addr;

 PREFIX_PUSH();
 setup_memblock();

 min_addr = memblock_end_of_DRAM() - SMP_CACHE_BYTES * 2;

 /* No space above this address */
 memblock_reserve_kern(min_addr, r2_size);

 allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);

 ASSERT_NE(allocated_ptr, NULL);
 ASSERT_EQ(rgn->base, min_addr - r1_size);
 ASSERT_EQ(rgn->size, total_size);

 ASSERT_EQ(memblock.reserved.cnt, 1);
 ASSERT_EQ(memblock.reserved.total_size, total_size);

 test_pass_pop();

 return 0;
}

/*
 * A test that tries to allocate a memory region with a minimal address below
 * the start address of the available memory. As the allocation is top-down,
 * first reserve a region that will force allocation near the start.
 * Expect successful allocation and merge of both regions.
 */

static int alloc_from_top_down_min_addr_cap_check(void)
{
 struct memblock_region *rgn = &memblock.reserved.regions[0];
 void *allocated_ptr = NULL;
 phys_addr_t r1_size = SZ_64;
 phys_addr_t min_addr;
 phys_addr_t start_addr;

 PREFIX_PUSH();
 setup_memblock();

 start_addr = (phys_addr_t)memblock_start_of_DRAM();
 min_addr = start_addr - SMP_CACHE_BYTES * 3;

 memblock_reserve_kern(start_addr + r1_size, MEM_SIZE - r1_size);

 allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);

 ASSERT_NE(allocated_ptr, NULL);
 ASSERT_EQ(rgn->base, start_addr);
 ASSERT_EQ(rgn->size, MEM_SIZE);

 ASSERT_EQ(memblock.reserved.cnt, 1);
 ASSERT_EQ(memblock.reserved.total_size, MEM_SIZE);

 test_pass_pop();

 return 0;
}

/*
 * A test that tries to allocate a memory region above an address that is too
 * close to the end of the memory:
 *
 *                             +
 *  |-----------+              +     |
 *  |    rgn    |              |     |
 *  +-----------+--------------+-----+
 *  ^                          ^
 *  |                          |
 *  Aligned address            min_addr
 *  boundary
 *
 * Expect to prioritize granting memory over satisfying the minimal address
 * requirement. Allocation happens at beginning of the available memory.
 */

static int alloc_from_bottom_up_high_addr_check(void)
{
 struct memblock_region *rgn = &memblock.reserved.regions[0];
 void *allocated_ptr = NULL;
 phys_addr_t size = SZ_32;
 phys_addr_t min_addr;

 PREFIX_PUSH();
 setup_memblock();

 /* The address is too close to the end of the memory */
 min_addr = memblock_end_of_DRAM() - SZ_8;

 allocated_ptr = memblock_alloc_from(size, SMP_CACHE_BYTES, min_addr);

 ASSERT_NE(allocated_ptr, NULL);
 ASSERT_EQ(rgn->size, size);
 ASSERT_EQ(rgn->base, memblock_start_of_DRAM());

 ASSERT_EQ(memblock.reserved.cnt, 1);
 ASSERT_EQ(memblock.reserved.total_size, size);

 test_pass_pop();

 return 0;
}

/*
 * A test that tries to allocate a memory region when there is no space
 * available above the minimal address above a certain address:
 *
 *                   +
 *  |-----------+    +-------------------|
 *  |    rgn    |    |                   |
 *  +-----------+----+-------------------+
 *                   ^
 *                   |
 *                   min_addr
 *
 * Expect to prioritize granting memory over satisfying the minimal address
 * requirement and to allocate at the beginning of the available memory.
 */

static int alloc_from_bottom_up_no_space_above_check(void)
{
 struct memblock_region *rgn = &memblock.reserved.regions[0];
 void *allocated_ptr = NULL;
 phys_addr_t r1_size = SZ_64;
 phys_addr_t min_addr;
 phys_addr_t r2_size;

 PREFIX_PUSH();
 setup_memblock();

 min_addr = memblock_start_of_DRAM() + SZ_128;
 r2_size = memblock_end_of_DRAM() - min_addr;

 /* No space above this address */
 memblock_reserve(min_addr - SMP_CACHE_BYTES, r2_size);

 allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);

 ASSERT_NE(allocated_ptr, NULL);
 ASSERT_EQ(rgn->base, memblock_start_of_DRAM());
 ASSERT_EQ(rgn->size, r1_size);

 ASSERT_EQ(memblock.reserved.cnt, 2);
 ASSERT_EQ(memblock.reserved.total_size, r1_size + r2_size);

 test_pass_pop();

 return 0;
}

/*
 * A test that tries to allocate a memory region with a minimal address below
 * the start address of the available memory. Expect to allocate a region
 * at the beginning of the available memory.
 */

static int alloc_from_bottom_up_min_addr_cap_check(void)
{
 struct memblock_region *rgn = &memblock.reserved.regions[0];
 void *allocated_ptr = NULL;
 phys_addr_t r1_size = SZ_64;
 phys_addr_t min_addr;
 phys_addr_t start_addr;

 PREFIX_PUSH();
 setup_memblock();

 start_addr = (phys_addr_t)memblock_start_of_DRAM();
 min_addr = start_addr - SMP_CACHE_BYTES * 3;

 allocated_ptr = memblock_alloc_from(r1_size, SMP_CACHE_BYTES, min_addr);

 ASSERT_NE(allocated_ptr, NULL);
 ASSERT_EQ(rgn->base, start_addr);
 ASSERT_EQ(rgn->size, r1_size);

 ASSERT_EQ(memblock.reserved.cnt, 1);
 ASSERT_EQ(memblock.reserved.total_size, r1_size);

 test_pass_pop();

 return 0;
}

/* Test case wrappers */
static int alloc_from_simple_check(void)
{
 test_print("\tRunning %s...\n", __func__);
 run_top_down(alloc_from_simple_generic_check);
 run_bottom_up(alloc_from_simple_generic_check);

 return 0;
}

static int alloc_from_misaligned_check(void)
{
 test_print("\tRunning %s...\n", __func__);
 run_top_down(alloc_from_misaligned_generic_check);
 run_bottom_up(alloc_from_misaligned_generic_check);

 return 0;
}

static int alloc_from_high_addr_check(void)
{
 test_print("\tRunning %s...\n", __func__);
 memblock_set_bottom_up(false);
 alloc_from_top_down_high_addr_check();
 memblock_set_bottom_up(true);
 alloc_from_bottom_up_high_addr_check();

 return 0;
}

static int alloc_from_no_space_above_check(void)
{
 test_print("\tRunning %s...\n", __func__);
 memblock_set_bottom_up(false);
 alloc_from_top_down_no_space_above_check();
 memblock_set_bottom_up(true);
 alloc_from_bottom_up_no_space_above_check();

 return 0;
}

static int alloc_from_min_addr_cap_check(void)
{
 test_print("\tRunning %s...\n", __func__);
 memblock_set_bottom_up(false);
 alloc_from_top_down_min_addr_cap_check();
 memblock_set_bottom_up(true);
 alloc_from_bottom_up_min_addr_cap_check();

 return 0;
}

int memblock_alloc_helpers_checks(void)
{
 const char *func_testing = "memblock_alloc_from";

 prefix_reset();
 prefix_push(func_testing);
 test_print("Running %s tests...\n", func_testing);

 reset_memblock_attributes();
 dummy_physical_memory_init();

 alloc_from_simple_check();
 alloc_from_misaligned_check();
 alloc_from_high_addr_check();
 alloc_from_no_space_above_check();
 alloc_from_min_addr_cap_check();

 dummy_physical_memory_cleanup();

 prefix_pop();

 return 0;
}

Messung V0.5
C=98 H=100 G=98

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.