Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:33

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /* 
0004  *  COPYRIGHT (c) 1989-2011, 2014.
0005  *  On-Line Applications Research Corporation (OAR).
0006  *
0007  *  Copyright (C) 2009, 2016 embedded brains GmbH & Co. KG
0008  *
0009  * Redistribution and use in source and binary forms, with or without
0010  * modification, are permitted provided that the following conditions
0011  * are met:
0012  * 1. Redistributions of source code must retain the above copyright
0013  *    notice, this list of conditions and the following disclaimer.
0014  * 2. Redistributions in binary form must reproduce the above copyright
0015  *    notice, this list of conditions and the following disclaimer in the
0016  *    documentation and/or other materials provided with the distribution.
0017  *
0018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0028  * POSSIBILITY OF SUCH DAMAGE.
0029  */
0030 
0031 #ifdef HAVE_CONFIG_H
0032 #include "config.h"
0033 #endif
0034 
0035 #define CONFIGURE_INIT
0036 #include "system.h"
0037 
0038 #include <stdlib.h>
0039 #include <string.h>
0040 #include <inttypes.h>
0041 #include <errno.h>
0042 #include <rtems/score/protectedheap.h>
0043 #include <rtems/malloc.h>
0044 #include <rtems/sysinit.h>
0045 
0046 const char rtems_test_name[] = "MALLOCTEST";
0047 
0048 /*
0049  *  A simple test of realloc
0050  */
0051 static void test_realloc(void)
0052 {
0053   void *p1, *p2, *p3, *p4;
0054   size_t i;
0055   int sc;
0056   bool malloc_walk_ok;
0057 
0058   /* Test growing reallocation "in place" */
0059   p1 = malloc(1);
0060   for (i=2 ; i<2048 ; i++) {
0061     p2 = realloc(p1, i);
0062     if (p2 != p1)
0063 /*
0064  * This was added to address the following warning.
0065  * warning: pointer 'p1' may be used after 'realloc'
0066  */
0067 #pragma GCC diagnostic push
0068 #pragma GCC diagnostic ignored "-Wuse-after-free"
0069       printf( "realloc - failed grow in place: "
0070               "%p != realloc(%p,%zu)\n", p1, p2, i);
0071 #pragma GCC diagnostic pop
0072     p1 = p2;
0073   }
0074   free(p1);
0075 
0076   /* Test shrinking reallocation "in place" */
0077   p1 = malloc(2048);
0078   for (i=2047 ; i>=1; i--)  {
0079     p2 = realloc(p1, i);
0080     if (p2 != p1)
0081 /*
0082  * This was added to address the following warning.
0083  * warning: pointer 'p1' may be used after 'realloc'
0084  */
0085 #pragma GCC diagnostic push
0086 #pragma GCC diagnostic ignored "-Wuse-after-free"
0087        printf( "realloc - failed shrink in place: "
0088               "%p != realloc(%p,%zu)\n", p1, p2, i);
0089 #pragma GCC diagnostic pop
0090     p1 = p2;
0091   }
0092   free(p1);
0093 
0094   /* Test realloc that should fail "in place", i.e.,
0095    * fallback to free()-- malloc()
0096    */
0097   p1 = malloc(32);
0098   p2 = malloc(32);
0099   p3 = realloc(p1, 64);
0100   if (p3 == p1 || p3 == NULL)
0101 /*
0102  * This was added to address the following warning.
0103  * warning: pointer may be used after 'realloc'
0104  */
0105 #pragma GCC diagnostic push
0106 #pragma GCC diagnostic ignored "-Wuse-after-free"
0107      printf(
0108       "realloc - failed non-in place: realloc(%p,%d) = %p\n", p1, 64, p3);
0109 #pragma GCC diagnostic pop
0110   free(p3);
0111   free(p2);
0112 
0113   /*
0114    *  Yet another case
0115    */
0116   p1 = malloc(8);
0117   p2 = malloc(8);
0118   free(p1);
0119   sc = posix_memalign(&p1, 16, 32);
0120   if (!sc)
0121     free(p1);
0122 
0123   /*
0124    *  Allocate with default alignment coverage
0125    */
0126   sc = rtems_memalign( &p4, 0, 8 );
0127   if ( !sc && p4 )
0128     free( p4 );
0129 
0130   /*
0131    * Walk the C Program Heap
0132    */
0133   puts( "malloc_walk - normal path" );
0134   malloc_walk_ok = malloc_walk( 1234, false );
0135   rtems_test_assert( malloc_walk_ok );
0136 
0137   puts( "malloc_walk - in critical section path" );
0138   _Thread_Dispatch_disable();
0139   malloc_walk_ok = malloc_walk( 1234, false );
0140   rtems_test_assert( malloc_walk_ok );
0141   _Thread_Dispatch_enable( _Per_CPU_Get() );
0142 
0143   /*
0144    *  Realloc with a bad pointer to force a point
0145    */
0146 /*
0147  * This was added to address the following warning.
0148  * warning: 'realloc' called on unallocated object
0149  */
0150 #pragma GCC diagnostic push
0151 #pragma GCC diagnostic ignored "-Wfree-nonheap-object"
0152    p4 = realloc( test_realloc, 32 );
0153 #pragma GCC diagnostic pop
0154 
0155   p4 = _realloc_r( NULL, NULL, 1 );
0156 }
0157 
0158 #define TEST_HEAP_SIZE 2048
0159 
0160 uint8_t TestHeapMemory[TEST_HEAP_SIZE];
0161 
0162 Heap_Control TestHeap;
0163 
0164 static void test_heap_default_init(void)
0165 {
0166   memset( &TestHeapMemory, 0x7f, TEST_HEAP_SIZE );
0167   _Heap_Initialize( &TestHeap, TestHeapMemory, TEST_HEAP_SIZE, 0 );
0168 }
0169 
0170 static void test_free( void *addr )
0171 {
0172   uint32_t failed_allocs;
0173 
0174   rtems_test_assert( _Heap_Free( &TestHeap, addr ) );
0175 
0176   failed_allocs = TestHeap.stats.failed_allocs;
0177   _Heap_Protection_free_all_delayed_blocks( &TestHeap );
0178   rtems_test_assert( failed_allocs == TestHeap.stats.failed_allocs );
0179 }
0180 
0181 static void test_heap_cases_1(void)
0182 {
0183   void     *p1, *p2, *p3;
0184   uintptr_t  u1, u2;
0185   Heap_Resize_status rsc;
0186 
0187   /*
0188    * Another odd case.  What we are trying to do from Sergei
0189    *
0190    * 32-bit CPU when CPU_ALIGNMENT = 4 (most targets have 8) with the
0191    * code like this:
0192    */
0193   test_heap_default_init();
0194   p1 = _Heap_Allocate( &TestHeap, 12 );
0195   p2 = _Heap_Allocate( &TestHeap, 32 );
0196   p3 = _Heap_Allocate( &TestHeap, 32 );
0197   test_free( p2 );
0198   p2 = _Heap_Allocate_aligned( &TestHeap, 8, 28 );
0199   test_free( p1 );
0200   test_free( p2 );
0201   test_free( p3 );
0202 
0203   /*
0204    *  Odd case in resizing a block.  Again test case outline per Sergei
0205    */
0206   test_heap_default_init();
0207   p1 = _Heap_Allocate( &TestHeap, 32 );
0208   p2 = _Heap_Allocate( &TestHeap, 8 );
0209   p3 = _Heap_Allocate( &TestHeap, 32 );
0210   test_free( p2 );
0211   rsc = _Heap_Resize_block( &TestHeap, p1, 41, &u1, &u2 );
0212   /* XXX what should we expect */
0213   test_free( p3 );
0214   test_free( p1 );
0215 
0216   /*
0217    *  To tackle a special case of resizing a block in order to cover the
0218    *  code in heapresizeblock.c
0219    *
0220    *  Re-initialise the heap, so that the blocks created from now on
0221    *  are contiguous.
0222    */
0223   test_heap_default_init();
0224   puts( "Heap Initialized" );
0225   p1 = _Heap_Allocate( &TestHeap, 400 );
0226   rtems_test_assert( p1 != NULL );
0227   p2 = _Heap_Allocate( &TestHeap, 496 );
0228   rtems_test_assert( p2 != NULL );
0229   rsc = _Heap_Resize_block( &TestHeap, p1, 256, &u1, &u2 );
0230   rtems_test_assert( rsc == HEAP_RESIZE_SUCCESSFUL );
0231   test_free( p1 );
0232   test_free( p2 );
0233 }
0234 
0235 #define TEST_DEFAULT_PAGE_SIZE 128
0236 
0237 static void test_heap_init(uintptr_t page_size )
0238 {
0239   uintptr_t rv = 0;
0240 
0241   memset( &TestHeapMemory, 0x7f, TEST_HEAP_SIZE );
0242 
0243   rv = _Heap_Initialize( &TestHeap, TestHeapMemory, TEST_HEAP_SIZE, page_size );
0244   rtems_test_assert( rv > 0 );
0245 }
0246 
0247 static void test_check_alloc(
0248   void *alloc_begin_ptr,
0249   void *expected_alloc_begin_ptr,
0250   uintptr_t alloc_size,
0251   uintptr_t alignment,
0252   uintptr_t boundary
0253 )
0254 {
0255   uintptr_t const min_block_size = TestHeap.min_block_size;
0256   uintptr_t const page_size = TestHeap.page_size;
0257 
0258   rtems_test_assert( alloc_begin_ptr == expected_alloc_begin_ptr );
0259 
0260   if( expected_alloc_begin_ptr != NULL ) {
0261     uintptr_t const alloc_begin = (uintptr_t ) alloc_begin_ptr;
0262     uintptr_t const alloc_end = alloc_begin + alloc_size;
0263 
0264     uintptr_t const alloc_area_begin = _Heap_Align_down( alloc_begin, page_size );
0265     uintptr_t const alloc_area_offset = alloc_begin - alloc_area_begin;
0266 #if UNUSED
0267     uintptr_t const alloc_area_size = alloc_area_offset + alloc_size;
0268 #endif
0269     Heap_Block *block = _Heap_Block_of_alloc_area( alloc_area_begin, page_size );
0270     uintptr_t const block_begin = (uintptr_t ) block;
0271     uintptr_t const block_size = _Heap_Block_size( block );
0272     uintptr_t const block_end = block_begin + block_size;
0273 
0274     rtems_test_assert( block_size >= min_block_size );
0275     rtems_test_assert( block_begin < block_end );
0276     rtems_test_assert(
0277       _Heap_Is_aligned( block_begin + HEAP_BLOCK_HEADER_SIZE, page_size )
0278     );
0279     rtems_test_assert(
0280       _Heap_Is_aligned( block_size, page_size )
0281     );
0282 
0283     rtems_test_assert( alloc_end <= block_end + HEAP_ALLOC_BONUS );
0284     rtems_test_assert( alloc_area_begin > block_begin );
0285     rtems_test_assert( alloc_area_offset < page_size );
0286 
0287     rtems_test_assert( _Heap_Is_aligned( alloc_area_begin, page_size ) );
0288     if ( alignment == 0 ) {
0289       rtems_test_assert( alloc_begin == alloc_area_begin );
0290     } else {
0291       rtems_test_assert( _Heap_Is_aligned( alloc_begin, alignment ) );
0292     }
0293 
0294     if ( boundary != 0 ) {
0295       uintptr_t boundary_line = _Heap_Align_down( alloc_end, boundary );
0296 
0297       rtems_test_assert( alloc_size <= boundary );
0298       rtems_test_assert(
0299         boundary_line <= alloc_begin
0300           || alloc_end <= boundary_line
0301       );
0302     }
0303   }
0304 
0305   rtems_test_assert(
0306     page_size < CPU_ALIGNMENT
0307       || _Heap_Walk( &TestHeap, 0, false )
0308   );
0309 }
0310 
0311 static void test_check_alloc_simple(
0312   void *alloc_begin_ptr,
0313   uintptr_t alloc_size,
0314   uintptr_t alignment,
0315   uintptr_t boundary
0316 )
0317 {
0318   test_check_alloc(
0319     alloc_begin_ptr,
0320     alloc_begin_ptr,
0321     alloc_size,
0322     alignment,
0323     boundary
0324   );
0325 }
0326 
0327 static void *test_alloc(
0328   uintptr_t alloc_size,
0329   uintptr_t alignment,
0330   uintptr_t boundary,
0331   void *expected_alloc_begin_ptr
0332 )
0333 {
0334   void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
0335     &TestHeap,
0336     alloc_size,
0337     alignment,
0338     boundary
0339   );
0340 
0341   test_check_alloc(
0342     alloc_begin_ptr,
0343     expected_alloc_begin_ptr,
0344     alloc_size,
0345     alignment,
0346     boundary
0347   );
0348 
0349   return alloc_begin_ptr;
0350 }
0351 
0352 static void *test_alloc_simple(
0353   uintptr_t alloc_size,
0354   uintptr_t alignment,
0355   uintptr_t boundary
0356 )
0357 {
0358   void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
0359     &TestHeap,
0360     alloc_size,
0361     alignment,
0362     boundary
0363   );
0364 
0365   test_check_alloc_simple(
0366     alloc_begin_ptr,
0367     alloc_size,
0368     alignment,
0369     boundary
0370   );
0371 
0372   rtems_test_assert( alloc_begin_ptr != NULL );
0373 
0374   return alloc_begin_ptr;
0375 }
0376 
0377 static void *test_init_and_alloc(
0378   uintptr_t alloc_size,
0379   uintptr_t alignment,
0380   uintptr_t boundary,
0381   void *expected_alloc_begin_ptr
0382 )
0383 {
0384   test_heap_init( TEST_DEFAULT_PAGE_SIZE );
0385 
0386   return test_alloc(
0387     alloc_size,
0388     alignment,
0389     boundary,
0390     expected_alloc_begin_ptr
0391   );
0392 }
0393 
0394 static void *test_init_and_alloc_simple(
0395   uintptr_t alloc_size,
0396   uintptr_t alignment,
0397   uintptr_t boundary
0398 )
0399 {
0400   test_heap_init( TEST_DEFAULT_PAGE_SIZE );
0401 
0402   return test_alloc_simple(
0403     alloc_size,
0404     alignment,
0405     boundary
0406   );
0407 }
0408 
0409 static uintptr_t test_page_size(void)
0410 {
0411   return TestHeap.page_size;
0412 }
0413 
0414 static void test_heap_do_initialize(
0415   uintptr_t area_size,
0416   uintptr_t page_size,
0417   uintptr_t success_expected
0418 )
0419 {
0420   uintptr_t rv =
0421     _Heap_Initialize( &TestHeap, TestHeapMemory, area_size, page_size );
0422 
0423   if ( success_expected ) {
0424     rtems_test_assert( rv > 0 && _Heap_Walk( &TestHeap, 0, false ) );
0425   } else {
0426     rtems_test_assert( rv == 0 );
0427   }
0428 }
0429 
0430 static void test_heap_initialize(void)
0431 {
0432   puts( "run tests for _Heap_Initialize()" );
0433 
0434   test_heap_do_initialize( TEST_HEAP_SIZE, 0, true );
0435 
0436   test_heap_do_initialize( TEST_HEAP_SIZE, TEST_DEFAULT_PAGE_SIZE, true );
0437 
0438   test_heap_do_initialize( 0, 0, false );
0439 
0440   test_heap_do_initialize( (uintptr_t) -1, 0, false );
0441 
0442   test_heap_do_initialize( TEST_HEAP_SIZE, (uintptr_t) -1, false );
0443 
0444   test_heap_do_initialize(
0445     TEST_HEAP_SIZE,
0446     (uintptr_t) (-2 * CPU_ALIGNMENT),
0447     false
0448   );
0449 }
0450 
0451 static void test_heap_allocate(void)
0452 {
0453   void *p1 = NULL;
0454   void *p2 = NULL;
0455   void *p3 = NULL;
0456   uintptr_t alloc_size = 0;
0457   uintptr_t alignment = 0;
0458   uintptr_t boundary = 0;
0459   uintptr_t page_size = 0;
0460   uintptr_t first_page_begin = 0;
0461   uintptr_t previous_last_block_begin = 0;
0462   uintptr_t previous_last_page_begin = 0;
0463 
0464   uintptr_t last_block_begin = 0;
0465   uintptr_t last_alloc_begin = 0;
0466 
0467   test_heap_init( TEST_DEFAULT_PAGE_SIZE );
0468 
0469   last_block_begin = (uintptr_t) TestHeap.last_block;
0470   last_alloc_begin = _Heap_Alloc_area_of_block( TestHeap.last_block );
0471 
0472   puts( "run tests for _Heap_Allocate_aligned_with_boundary()");
0473 
0474   puts( "\tcheck if NULL will be returned if size causes integer overflow" );
0475 
0476   alloc_size = (uintptr_t ) -1;
0477   alignment = 0;
0478   boundary = 0;
0479   test_init_and_alloc( alloc_size, alignment, boundary, NULL );
0480 
0481   puts( "\ttry to allocate more space than the one which fits in the boundary" );
0482 
0483   alloc_size = 2;
0484   alignment = 0;
0485   boundary = alloc_size - 1;
0486   test_init_and_alloc( alloc_size, alignment, boundary, NULL );
0487 
0488   puts( "\tcheck if alignment will be set to page size if only a boundary is given" );
0489 
0490   alloc_size = 1;
0491   boundary = 1;
0492 
0493   alignment = 0;
0494   p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
0495 
0496   alignment = test_page_size();
0497   test_init_and_alloc( alloc_size, alignment, boundary, p1 );
0498 
0499   puts( "\tcreate a block which is bigger then the first free space" );
0500 
0501   alignment = 0;
0502   boundary = 0;
0503 
0504   alloc_size = test_page_size();
0505   p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
0506   p2 = test_alloc_simple( alloc_size, alignment, boundary );
0507   rtems_test_assert( p2 );
0508 
0509   test_free( p1 );
0510 
0511   alloc_size = 2 * alloc_size;
0512   p3 = test_alloc_simple( alloc_size, alignment, boundary );
0513   rtems_test_assert( p1 != p3 );
0514 
0515   puts( "\tset boundary before allocation begin" );
0516 
0517   alloc_size = 1;
0518   alignment = 0;
0519   boundary = last_alloc_begin - test_page_size();
0520   p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
0521   rtems_test_assert( (uintptr_t ) p1 >= boundary );
0522 
0523   puts( "\tset boundary between allocation begin and end" );
0524   alloc_size = test_page_size();
0525   alignment = 0;
0526   boundary = last_alloc_begin - alloc_size / 2;
0527   p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
0528   rtems_test_assert( (uintptr_t ) p1 + alloc_size <= boundary );
0529 
0530   puts( "\tset boundary after allocation end" );
0531   alloc_size = 1;
0532   alignment = 0;
0533   boundary = last_alloc_begin;
0534   p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
0535   rtems_test_assert( (uintptr_t ) p1 + alloc_size < boundary );
0536 
0537   puts( "\tset boundary on allocation end" );
0538   alloc_size = TEST_DEFAULT_PAGE_SIZE - HEAP_BLOCK_HEADER_SIZE;
0539   alignment = 0;
0540   boundary = last_block_begin;
0541   p1 = (void *) (last_alloc_begin - TEST_DEFAULT_PAGE_SIZE);
0542   test_init_and_alloc( alloc_size, alignment, boundary, p1);
0543 
0544   puts( "\talign the allocation to different positions in the block header" );
0545 
0546   page_size = sizeof(uintptr_t);
0547   alloc_size = 1;
0548   boundary = 0;
0549 
0550   test_heap_init( page_size );
0551 
0552   /* Force the page size to a small enough value */
0553   TestHeap.page_size = page_size;
0554 
0555   alignment = first_page_begin - sizeof(uintptr_t);
0556   p1 = test_alloc( alloc_size, alignment, boundary, NULL );
0557 
0558   first_page_begin = ((uintptr_t) TestHeap.first_block ) + HEAP_BLOCK_HEADER_SIZE;
0559   alignment = first_page_begin + sizeof(uintptr_t);
0560   p1 = test_alloc( alloc_size, alignment, boundary, NULL );
0561 
0562   first_page_begin = ((uintptr_t) TestHeap.first_block )
0563       + HEAP_BLOCK_HEADER_SIZE;
0564   alignment = first_page_begin;
0565   p1 = test_alloc_simple( alloc_size, alignment, boundary );
0566 
0567   puts( "\tallocate last block with different boundarys" );
0568   page_size = TEST_DEFAULT_PAGE_SIZE;
0569   test_heap_init( page_size );
0570   previous_last_block_begin = ((uintptr_t) TestHeap.last_block )
0571       - TestHeap.min_block_size;
0572   previous_last_page_begin = previous_last_block_begin
0573       + HEAP_BLOCK_HEADER_SIZE;
0574   alloc_size = TestHeap.page_size - HEAP_BLOCK_HEADER_SIZE;
0575   alignment = sizeof(uintptr_t);
0576   boundary = 0;
0577   p1 = test_alloc( alloc_size, alignment, boundary, (void *) (previous_last_page_begin + sizeof(uintptr_t)));
0578 
0579   test_heap_init( page_size );
0580   boundary = ((uintptr_t) TestHeap.last_block );
0581   p1 = test_alloc( alloc_size, alignment, boundary, (void *) previous_last_page_begin );
0582 
0583   puts( "\tbreak the boundaries and aligns more than one time" );
0584 
0585   page_size = CPU_ALIGNMENT * 20;
0586   alloc_size = page_size / 4;
0587   alignment = page_size / 5;
0588   boundary = page_size / 4;
0589   test_heap_init( page_size );
0590   p1 = (void *) (_Heap_Alloc_area_of_block( TestHeap.last_block ) - page_size );
0591   test_alloc( alloc_size, alignment, boundary, p1);
0592 
0593   puts( "\tdifferent combinations, so that there is no valid block at the end" );
0594 
0595   page_size = sizeof(uintptr_t);
0596 
0597   test_heap_init( 0 );
0598 
0599   /* Force the page size to a small enough value */
0600   TestHeap.page_size = page_size;
0601 
0602   alloc_size = 1;
0603   alignment = (uintptr_t) TestHeap.last_block;
0604   boundary = 0;
0605   p1 = test_alloc( alloc_size, alignment, boundary, NULL );
0606 
0607   boundary = (uintptr_t) TestHeap.last_block;
0608   p1 = test_alloc( alloc_size, alignment, boundary, NULL );
0609 
0610   alloc_size = 0;
0611   p1 = test_alloc( alloc_size, alignment, boundary, NULL );
0612 
0613   alloc_size = 1;
0614   alignment = sizeof(uintptr_t);
0615   boundary = 0;
0616   p1 = test_alloc_simple( alloc_size, alignment, boundary );
0617 
0618   puts( "\ttry to create a block, which is not possible because of the alignment and boundary" );
0619 
0620   alloc_size = 2;
0621   boundary = _Heap_Alloc_area_of_block( TestHeap.first_block )
0622       + _Heap_Block_size( TestHeap.first_block ) / 2;
0623   alignment = boundary - 1;
0624   p1 = test_init_and_alloc( alloc_size, alignment, boundary, NULL );
0625 
0626   alloc_size = 2;
0627   alignment = _Heap_Alloc_area_of_block( TestHeap.first_block );
0628   boundary = alignment + 1;
0629   p1 = test_init_and_alloc( alloc_size, alignment, boundary, NULL );
0630 }
0631 
0632 static void test_heap_free(void)
0633 {
0634   Heap_Control *heap = &TestHeap;
0635   void *p;
0636   Heap_Block *block;
0637   bool ok;
0638 
0639   _Heap_Initialize( heap, &TestHeapMemory[0], sizeof(TestHeapMemory), 0 );
0640 
0641   p = _Heap_Allocate( heap, 1 );
0642   rtems_test_assert( p != NULL );
0643 
0644   block = _Heap_Block_of_alloc_area( (uintptr_t) p, heap->page_size );
0645 
0646   /*
0647    * This will kick the next block outside of the heap area and the next
0648    * _Heap_Free() will detect this.
0649    */
0650   block->size_and_flag += sizeof(TestHeapMemory);
0651 
0652   ok = _Heap_Free( heap, p );
0653   rtems_test_assert( !ok );
0654 }
0655 
0656 static void *test_create_used_block( void )
0657 {
0658   uintptr_t const alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE;
0659   uintptr_t const alignment = 0;
0660   uintptr_t const boundary = 0;
0661 
0662   return test_alloc_simple( alloc_size, alignment, boundary );
0663 }
0664 
0665 static void test_block_alloc(
0666   int free_variant,
0667   int alloc_variant,
0668   uintptr_t alloc_begin,
0669   uintptr_t alloc_size
0670 )
0671 {
0672   void *p1 = NULL;
0673   void *p2 = NULL;
0674   void *p3 = NULL;
0675 
0676   uintptr_t size_fresh_heap = 0;
0677   uintptr_t pages_per_default_block = 0;
0678   uint32_t exp_free_pages = 0;
0679   uint32_t exp_free_blocks = 0;
0680   uint32_t exp_used_blocks = 0;
0681 
0682   test_heap_init( TEST_DEFAULT_PAGE_SIZE );
0683 
0684   size_fresh_heap = _Heap_Get_size( &TestHeap );
0685   exp_free_pages = size_fresh_heap / TestHeap.page_size;
0686 
0687   p1 = test_create_used_block();
0688   p2 = test_create_used_block();
0689   p3 = test_create_used_block();
0690 
0691   pages_per_default_block = _Heap_Block_size(
0692     _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size )
0693   ) / TestHeap.page_size;
0694 
0695   if (free_variant == 1) {
0696     test_free( p1 );
0697   } else if (free_variant == 2) {
0698     test_free( p3 );
0699   } else if (free_variant == 3) {
0700     test_free( p2 );
0701     test_free( p3 );
0702   }
0703 
0704   _Heap_Block_allocate(
0705     &TestHeap,
0706     _Heap_Block_of_alloc_area( (uintptr_t) p2, test_page_size()),
0707     alloc_begin,
0708     alloc_size
0709   );
0710 
0711   test_check_alloc_simple( (void *) alloc_begin, alloc_size, 0, 0 );
0712 
0713   /* check statistics */
0714   switch( free_variant ) {
0715     case 1:
0716       exp_free_pages = exp_free_pages - 2 * pages_per_default_block;
0717       exp_used_blocks = 2;
0718 
0719       switch( alloc_variant ) {
0720     case 1:
0721       /* allocate block full space */
0722       exp_free_blocks = 2;
0723       break;
0724     case 2:
0725       /* allocate block in the middle */
0726       exp_free_pages = exp_free_pages + pages_per_default_block - 1;
0727       exp_free_blocks = 3;
0728       break;
0729     case 3:
0730       /* allocate block at the end */
0731       exp_free_pages = exp_free_pages + pages_per_default_block - 2;
0732       exp_free_blocks = 2;
0733       break;
0734     default:
0735       /* allocate block at the beginning */
0736       exp_free_pages = exp_free_pages + pages_per_default_block - 1;
0737       exp_free_blocks = 3;
0738       break;
0739       }
0740       break;
0741     case 2:
0742       exp_free_pages = exp_free_pages - 2 * pages_per_default_block;
0743       exp_used_blocks = 2;
0744 
0745       switch( alloc_variant ) {
0746     case 1:
0747       /* allocate block full space */
0748       exp_free_blocks = 1;
0749       break;
0750     case 2:
0751       /* allocate block in the middle */
0752       exp_free_pages = exp_free_pages + pages_per_default_block - 1;
0753       exp_free_blocks = 2;
0754       break;
0755     case 3:
0756       /* allocate block at the end */
0757       exp_free_pages = exp_free_pages + pages_per_default_block - 1;
0758       exp_free_blocks = 2;
0759       break;
0760     default:
0761       /* allocate block at the beginning */
0762       exp_free_pages = exp_free_pages + pages_per_default_block - 1;
0763       exp_free_blocks = 1;
0764       break;
0765       }
0766       break;
0767     case 3:
0768       exp_free_pages = exp_free_pages - pages_per_default_block;
0769       exp_used_blocks = 2;
0770 
0771       switch( alloc_variant ) {
0772     case 1:
0773       /* allocate block full space */
0774       exp_free_pages = exp_free_pages - pages_per_default_block;
0775       exp_free_blocks = 1;
0776       break;
0777     case 2:
0778       /* allocate block in the middle */
0779       exp_free_pages = exp_free_pages - 1;
0780       exp_free_blocks = 2;
0781       break;
0782     case 3:
0783       /* allocate block at the end */
0784       exp_free_pages = exp_free_pages - 2;
0785       exp_free_blocks = 2;
0786       break;
0787     default:
0788       /* allocate block at the beginning */
0789       exp_free_pages = exp_free_pages - 1;
0790       exp_free_blocks = 1;
0791       break;
0792       }
0793       break;
0794     default:
0795       exp_free_pages = exp_free_pages - 3 * pages_per_default_block;
0796       exp_used_blocks = 3;
0797 
0798       switch( alloc_variant ) {
0799     case 1:
0800       /* allocate block full space */
0801       exp_free_blocks = 1;
0802       break;
0803     case 2:
0804       /* allocate block in the middle */
0805       exp_free_blocks = 3;
0806       exp_free_pages = exp_free_pages + pages_per_default_block - 1;
0807       break;
0808     case 3:
0809       /* allocate block at the end */
0810       exp_free_blocks = 2;
0811       exp_free_pages = exp_free_pages + pages_per_default_block - 1;
0812       break;
0813     default:
0814       /* allocate block at the beginning */
0815       exp_free_blocks = 2;
0816       exp_free_pages = exp_free_pages + pages_per_default_block - 1;
0817       }
0818   }
0819 
0820   rtems_test_assert( TestHeap.stats.free_size == exp_free_pages * TestHeap.page_size );
0821   rtems_test_assert( TestHeap.stats.free_blocks == exp_free_blocks );
0822   rtems_test_assert( TestHeap.stats.used_blocks == exp_used_blocks );
0823 }
0824 
0825 static void test_heap_do_block_allocate( int variant, void *p2 )
0826 {
0827   Heap_Block *const block =
0828     _Heap_Block_of_alloc_area( (uintptr_t) p2, test_page_size());
0829   uintptr_t const alloc_box_begin = _Heap_Alloc_area_of_block( block );
0830   uintptr_t const alloc_box_size = _Heap_Block_size( block );
0831   uintptr_t const alloc_box_end = alloc_box_begin + alloc_box_size;
0832   uintptr_t alloc_begin = 0;
0833   uintptr_t alloc_size = 0;
0834 
0835   puts( "\tallocate block at the beginning");
0836   alloc_begin = alloc_box_begin;
0837   alloc_size = 0;
0838   test_block_alloc( variant, 0, alloc_begin, alloc_size );
0839 
0840   puts( "\tallocate block full space");
0841   alloc_begin = alloc_box_begin;
0842   alloc_size = alloc_box_size + HEAP_ALLOC_BONUS
0843     - HEAP_BLOCK_HEADER_SIZE;
0844   test_block_alloc( variant, 1, alloc_begin, alloc_size );
0845 
0846   puts( "\tallocate block in the middle");
0847   alloc_begin = alloc_box_begin + TEST_DEFAULT_PAGE_SIZE;
0848   alloc_size = 0;
0849   test_block_alloc( variant, 2, alloc_begin, alloc_size );
0850 
0851   puts( "\tallocate block at the end");
0852   alloc_begin = alloc_box_end - TEST_DEFAULT_PAGE_SIZE;
0853   alloc_size = TEST_DEFAULT_PAGE_SIZE + HEAP_ALLOC_BONUS
0854     - HEAP_BLOCK_HEADER_SIZE;
0855   test_block_alloc( variant, 3, alloc_begin, alloc_size );
0856 }
0857 
0858 static void test_heap_block_allocate( void )
0859 {
0860   void *p2 = NULL;
0861 
0862   puts( "run tests for _Heap_Block_allocate()" );
0863 
0864   test_heap_init( TEST_DEFAULT_PAGE_SIZE );
0865 
0866   test_create_used_block();
0867   p2 = test_create_used_block();
0868 
0869   test_heap_do_block_allocate( 0, p2 );
0870   test_heap_do_block_allocate( 1, p2 );
0871   test_heap_do_block_allocate( 2, p2 );
0872   test_heap_do_block_allocate( 3, p2 );
0873 }
0874 
0875 static void *test_alloc_one_page(void)
0876 {
0877   void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
0878     &TestHeap,
0879     1,
0880     0,
0881     0
0882   );
0883 
0884   test_check_alloc_simple(
0885     alloc_begin_ptr,
0886     1,
0887     0,
0888     0
0889   );
0890 
0891   rtems_test_assert( alloc_begin_ptr != NULL );
0892 
0893   return alloc_begin_ptr;
0894 }
0895 
0896 static void *test_alloc_two_pages(void)
0897 {
0898   void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
0899     &TestHeap,
0900     3 * TestHeap.page_size / 2,
0901     0,
0902     0
0903   );
0904 
0905   test_check_alloc_simple(
0906     alloc_begin_ptr,
0907     3 * TestHeap.page_size / 2,
0908     0,
0909     0
0910   );
0911 
0912   rtems_test_assert( alloc_begin_ptr != NULL );
0913 
0914   return alloc_begin_ptr;
0915 }
0916 
0917 static void test_simple_resize_block(
0918   void *alloc_pointer,
0919   uintptr_t new_alloc_size,
0920   Heap_Resize_status expected_status
0921 )
0922 {
0923   uintptr_t old_size = 0;
0924   uintptr_t new_size = 0;
0925 
0926   Heap_Resize_status status = _Heap_Resize_block(
0927     &TestHeap,
0928     alloc_pointer,
0929     new_alloc_size,
0930     &old_size,
0931     &new_size
0932   );
0933 
0934   rtems_test_assert( status == expected_status );
0935 }
0936 
0937 static void test_heap_resize_block(void)
0938 {
0939   void *p1, *p2, *p3;
0940   uintptr_t new_alloc_size = 0;
0941   Heap_Block *block = NULL;
0942 
0943   puts( "run tests for _Heap_Resize_Block()" );
0944 
0945   puts( "\tgive a block outside the heap to the function" );
0946   test_heap_init( TEST_DEFAULT_PAGE_SIZE );
0947   p1 = TestHeap.first_block - TEST_DEFAULT_PAGE_SIZE;
0948   new_alloc_size = 1;
0949   test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_FATAL_ERROR );
0950 
0951   puts( "\tincrease size");
0952 
0953   puts( "\t\tlet the next block be used alredy and try to get a size bigger than the actual block" );
0954   test_heap_init( TEST_DEFAULT_PAGE_SIZE );
0955   p1 = test_alloc_one_page();
0956   rtems_test_assert( p1 );
0957 
0958   p2 = test_alloc_one_page();
0959   rtems_test_assert( p2 );
0960 
0961   new_alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE / 2;
0962   test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_UNSATISFIED );
0963 
0964   puts( "\t\tnext block not used and try to set the new allocation size between the page-alignments" );
0965   test_heap_init( TEST_DEFAULT_PAGE_SIZE );
0966   p1 = test_alloc_one_page();
0967   new_alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE / 2;
0968   test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
0969 
0970   puts( "\t\tlet the block after the next be used and try to allocate more then one pagesize more" );
0971   test_heap_init( TEST_DEFAULT_PAGE_SIZE );
0972   p1 = test_alloc_one_page();
0973   rtems_test_assert( p1 );
0974 
0975   p2 = test_alloc_one_page();
0976   rtems_test_assert( p2 );
0977 
0978   p3 = test_alloc_one_page();
0979   rtems_test_assert( p3 );
0980 
0981   test_free( p2 );
0982   new_alloc_size = 5 * TEST_DEFAULT_PAGE_SIZE / 2;
0983   test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_UNSATISFIED );
0984 
0985   puts( "\ttry to resize to the same size" );
0986   test_heap_init( TEST_DEFAULT_PAGE_SIZE );
0987   p1 = test_alloc_one_page();
0988   block = _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size );
0989   new_alloc_size = _Heap_Block_size( block );
0990   test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
0991 
0992   puts( "\tdecrease size");
0993 
0994   puts( "\t\tdecrease a block with two pages to one page" );
0995   test_heap_init( TEST_DEFAULT_PAGE_SIZE );
0996   p1 = test_alloc_two_pages();
0997   new_alloc_size = 1;
0998   test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
0999 
1000   puts( "\t\tresize the block to the size 0" );
1001   test_heap_init( TEST_DEFAULT_PAGE_SIZE );
1002   p1 = test_alloc_one_page();
1003   new_alloc_size = 0;
1004   test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
1005 }
1006 
1007 static void test_heap_assert(bool ret, bool expected)
1008 {
1009   rtems_test_assert( ret == expected );
1010   rtems_test_assert( _Heap_Walk( &TestHeap, 0, false ) );
1011 }
1012 
1013 static void test_heap_extend(void)
1014 {
1015   bool ret = false;
1016   Heap_Control *heap = &TestHeap;
1017   uint8_t *area_begin = TestHeapMemory;
1018   uint8_t *sub_area_begin;
1019   uint8_t *sub_area_end;
1020 
1021   _Heap_Initialize( heap, area_begin + 768, 256, 0 );
1022   sub_area_begin = (uint8_t *) heap->first_block;
1023   sub_area_end = (uint8_t *) heap->first_block->prev_size;
1024 
1025   puts( "heap extend - link below" );
1026   ret = _Protected_heap_Extend( heap, area_begin + 0, 256 );
1027   test_heap_assert( ret, true );
1028 
1029   puts( "heap extend - merge below overlap" );
1030   ret = _Protected_heap_Extend( heap, sub_area_begin - 128, 256 );
1031   test_heap_assert( ret, false );
1032 
1033   puts( "heap extend - merge below" );
1034   ret = _Protected_heap_Extend( heap, sub_area_begin - 256, 256 );
1035   test_heap_assert( ret, true );
1036 
1037   puts( "heap extend - merge above overlap" );
1038   ret = _Protected_heap_Extend( heap, sub_area_end - 128, 256 );
1039   test_heap_assert( ret, false );
1040 
1041   puts( "heap extend - merge above" );
1042   ret = _Protected_heap_Extend( heap, sub_area_end, 256 );
1043   test_heap_assert( ret, true );
1044 
1045   puts( "heap extend - link above" );
1046   ret = _Protected_heap_Extend( heap, area_begin + 1536, 256 );
1047   test_heap_assert( ret, true );
1048 
1049   puts( "heap extend - area too small" );
1050   ret = _Protected_heap_Extend( heap, area_begin + 2048, 0 );
1051   test_heap_assert( ret, false );
1052 
1053   puts( "heap extend - invalid area" );
1054   ret = _Protected_heap_Extend( heap, (void *) -1, 2 );
1055   test_heap_assert( ret, false );
1056 
1057   area_begin = (uint8_t *) (((uintptr_t) area_begin) | 1);
1058 
1059   _Heap_Initialize( heap, area_begin + 768, 256, 0 );
1060 
1061   puts( "heap extend - merge below with align up" );
1062   ret = _Protected_heap_Extend( heap, area_begin + 512, 256 );
1063   test_heap_assert( ret, true );
1064 }
1065 
1066 static void test_heap_extend_allocation_order(void)
1067 {
1068   Heap_Control *heap = &TestHeap;
1069   uintptr_t size = 256;
1070   uintptr_t gap = 256;
1071   uint8_t *init_area_begin = TestHeapMemory;
1072   uint8_t *extend_area_begin = init_area_begin + size + gap;
1073   bool ret;
1074   uint8_t *p;
1075 
1076   _Heap_Initialize( heap, init_area_begin, size, 0 );
1077 
1078   ret = _Protected_heap_Extend( heap, extend_area_begin, size );
1079   test_heap_assert( ret, true );
1080 
1081   p = _Heap_Allocate( heap, 1 );
1082   rtems_test_assert( (uintptr_t) (p - init_area_begin) < size );
1083 }
1084 
1085 static void test_heap_extend_allocation_order_with_empty_heap(void)
1086 {
1087   Heap_Control *heap = &TestHeap;
1088   uintptr_t size = 256;
1089   uintptr_t gap = 256;
1090   uint8_t *init_area_begin = TestHeapMemory;
1091   uint8_t *extend_area_begin = init_area_begin + size + gap;
1092   bool ret;
1093   uint8_t *p;
1094 
1095   _Heap_Initialize( heap, init_area_begin, size, 0 );
1096 
1097   _Heap_Greedy_allocate( heap, NULL, 0 );
1098 
1099   ret = _Protected_heap_Extend( heap, extend_area_begin, size );
1100   test_heap_assert( ret, true );
1101 
1102   p = _Heap_Allocate( heap, 1 );
1103   rtems_test_assert( (uintptr_t) (p - extend_area_begin) < size );
1104 }
1105 
1106 static void test_heap_no_extend(void)
1107 {
1108   uintptr_t extended_space = _Heap_No_extend( NULL, 0, 0, 0 );
1109   rtems_test_assert( extended_space == 0 );
1110 }
1111 
1112 static void free_all_delayed_blocks( void )
1113 {
1114   rtems_resource_snapshot unused;
1115 
1116   rtems_resource_snapshot_take( &unused );
1117 }
1118 
1119 static void do_free( void *p )
1120 {
1121   free( p );
1122   free_all_delayed_blocks();
1123 }
1124 
1125 static void test_heap_info(void)
1126 {
1127   size_t                  s1, s2;
1128   void                   *p1;
1129   int                     sc;
1130   Heap_Information_block  the_info;
1131 
1132   free_all_delayed_blocks();
1133 
1134   s1 = malloc_free_space();
1135   p1 = malloc( 512 );
1136   s2 = malloc_free_space();
1137   puts( "malloc_free_space - check malloc space drops after malloc" );
1138   rtems_test_assert( s1 );
1139   rtems_test_assert( s2 );
1140   rtems_test_assert( s2 <= s1 );
1141   do_free( p1 );
1142 
1143   puts( "malloc_free_space - verify free space returns to previous value" );
1144   s2 = malloc_free_space();
1145   rtems_test_assert( s1 == s2 );
1146 
1147   puts( "malloc_info - called with NULL\n" );
1148   sc = malloc_info( NULL );
1149   rtems_test_assert( sc == -1 );
1150 
1151   puts( "malloc_info - check free space drops after malloc" );
1152   sc = malloc_info( &the_info );
1153   rtems_test_assert( sc == 0 );
1154   s1 = the_info.Free.largest;
1155 
1156   p1 = malloc( 512 );
1157 
1158   sc = malloc_info( &the_info );
1159   rtems_test_assert( sc == 0 );
1160   s2 = the_info.Free.largest;
1161 
1162   rtems_test_assert( s1 );
1163   rtems_test_assert( s2 );
1164   rtems_test_assert( s2 <= s1 );
1165   do_free( p1 );
1166 
1167   puts( "malloc_info - verify free space returns to previous value" );
1168   sc = malloc_info( &the_info );
1169   rtems_test_assert( sc == 0 );
1170   rtems_test_assert( s1 == the_info.Free.largest );
1171 }
1172 
1173 static void test_protected_heap_info(void)
1174 {
1175   Heap_Control           heap;
1176   Heap_Information_block info;
1177   bool                   rc;
1178 
1179   puts( "_Protected_heap_Get_information - NULL heap" );
1180   rc = _Protected_heap_Get_information( NULL, &info );
1181   rtems_test_assert( rc == false );
1182 
1183   puts( "_Protected_heap_Get_information - NULL info" );
1184   rc = _Protected_heap_Get_information( &heap, NULL );
1185   rtems_test_assert( rc == false );
1186 }
1187 
1188 static void test_rtems_heap_allocate_aligned_with_boundary(void)
1189 {
1190   void *p = NULL;
1191 
1192   p = rtems_heap_allocate_aligned_with_boundary(1, 1, 1);
1193   rtems_test_assert( p != NULL );
1194   free(p);
1195 
1196   _Thread_Dispatch_disable();
1197   p = rtems_heap_allocate_aligned_with_boundary(1, 1, 1);
1198   _Thread_Dispatch_enable( _Per_CPU_Get() );
1199   rtems_test_assert( p == NULL );
1200 }
1201 
1202 static void test_rtems_malloc(void)
1203 {
1204   void *p;
1205 
1206   p = rtems_malloc(0);
1207   rtems_test_assert(p == NULL);
1208 
1209   errno = 0;
1210   p = rtems_malloc(SIZE_MAX / 2);
1211   rtems_test_assert(p == NULL);
1212   rtems_test_assert(errno == 0);
1213 
1214   p = rtems_malloc(1);
1215   rtems_test_assert(p != NULL);
1216 
1217   RTEMS_OBFUSCATE_VARIABLE(p);
1218   free(p);
1219 }
1220 
1221 static void test_rtems_calloc(void)
1222 {
1223   void *p;
1224   int *i;
1225 
1226   p = rtems_calloc(0, 0);
1227   rtems_test_assert(p == NULL);
1228 
1229   p = rtems_calloc(0, 1);
1230   rtems_test_assert(p == NULL);
1231 
1232   p = rtems_calloc(1, 0);
1233   rtems_test_assert(p == NULL);
1234 
1235   errno = 0;
1236   p = rtems_calloc(1, SIZE_MAX / 2);
1237   rtems_test_assert(p == NULL);
1238   rtems_test_assert(errno == 0);
1239 
1240   errno = 0;
1241   p = rtems_calloc(SIZE_MAX / 2, 1);
1242   rtems_test_assert(p == NULL);
1243   rtems_test_assert(errno == 0);
1244 
1245 #pragma GCC diagnostic push
1246 #pragma GCC diagnostic ignored "-Walloc-size-larger-than=N"
1247   errno = 0;
1248   p = rtems_calloc(SIZE_MAX, SIZE_MAX);
1249   rtems_test_assert(p == NULL);
1250   rtems_test_assert(errno == 0);
1251 #pragma GCC diagnostic pop
1252 
1253   i = rtems_calloc(1, sizeof(*i));
1254   rtems_test_assert(i != NULL);
1255   rtems_test_assert(*i == 0);
1256 
1257 
1258   RTEMS_OBFUSCATE_VARIABLE(p);
1259   free(i);
1260 }
1261 
1262 static void test_heap_size_with_overhead(void)
1263 {
1264   uintptr_t s;
1265 
1266   puts( "_Heap_Size_with_overhead" );
1267 
1268   s = _Heap_Size_with_overhead(0, 0, 0);
1269   rtems_test_assert(s == HEAP_BLOCK_HEADER_SIZE + CPU_ALIGNMENT - 1);
1270 
1271   s = _Heap_Size_with_overhead(CPU_ALIGNMENT, 0, 0);
1272   rtems_test_assert(s == HEAP_BLOCK_HEADER_SIZE + CPU_ALIGNMENT - 1);
1273 
1274   s = _Heap_Size_with_overhead(CPU_ALIGNMENT, 0, 2 * CPU_ALIGNMENT);
1275   rtems_test_assert(s == HEAP_BLOCK_HEADER_SIZE + 2 * CPU_ALIGNMENT - 1);
1276 
1277   s = _Heap_Size_with_overhead(CPU_ALIGNMENT, 123, 0);
1278   rtems_test_assert(s == HEAP_BLOCK_HEADER_SIZE + CPU_ALIGNMENT - 1 + 123);
1279 }
1280 
1281 /*
1282  *  A simple test of posix_memalign
1283  */
1284 static void test_posix_memalign(void)
1285 {
1286   void *p1;
1287   void **p2;
1288   size_t i;
1289   int sc;
1290   int maximumShift;
1291 
1292   /*
1293    * posix_memalign() is declared as never having a NULL first parameter.
1294    * We need to hide the NULL value from the compiler.
1295    */
1296   puts( "posix_memalign - NULL return pointer -- EINVAL" );
1297   p2 = NULL;
1298   RTEMS_OBFUSCATE_VARIABLE( p2 );
1299   sc = posix_memalign( p2, 32, 8 );
1300   fatal_posix_service_status( sc, EINVAL, "posix_memalign NULL pointer" );
1301 
1302   puts( "posix_memalign - alignment of 0 -- EINVAL" );
1303   sc = posix_memalign( &p1, 0, 8 );
1304   fatal_posix_service_status( sc, EINVAL, "posix_memalign alignment of 0" );
1305 
1306   puts( "posix_memalign - alignment  of 2-- EINVAL" );
1307   sc = posix_memalign( &p1, 2, 8 );
1308   fatal_posix_service_status( sc, EINVAL, "posix_memalign alignment of 2" );
1309 
1310   maximumShift = (sizeof(size_t) * CHAR_BIT) - 1;
1311   for ( i=sizeof(void *) ; i<maximumShift ; i++ ) {
1312     size_t alignment = 1;
1313 
1314     alignment <<= i;
1315 
1316     p1 = NULL; /* Initialize p1 to aovid used uninitialized */
1317 
1318     printf( "posix_memalign - alignment of %zu -- OK\n", alignment);
1319     sc = posix_memalign( &p1, alignment, 8 );
1320     if ( sc == ENOMEM ) {
1321       printf( "posix_memalign - ran out of memory trying %zu\n", alignment );
1322       break;
1323     }
1324     posix_service_failed( sc, "posix_memalign alignment OK" );
1325 
1326     free( p1 );
1327   }
1328   for ( ; i<maximumShift ; i++ ) {
1329     size_t alignment = 1 << i;
1330     printf( "posix_memalign - alignment of %zd -- SKIPPED\n", alignment);
1331   }
1332 
1333 }
1334 
1335 static void test_greedy_allocate(void)
1336 {
1337   Heap_Control *heap = &TestHeap;
1338   uintptr_t block_size = 1;
1339   void *p;
1340 
1341   _Heap_Initialize( heap, &TestHeapMemory[0], sizeof(TestHeapMemory), 0 );
1342 
1343   _Heap_Greedy_allocate( heap, &block_size, 1 );
1344 
1345   p = _Heap_Allocate( heap, 1 );
1346   rtems_test_assert( p != NULL );
1347 
1348   p = _Heap_Allocate( heap, 1 );
1349   rtems_test_assert( p == NULL );
1350 
1351   /* The internal allocation fails */
1352   _Heap_Greedy_allocate( heap, &block_size, 1 );
1353 
1354   p = _Heap_Allocate( heap, 1 );
1355   rtems_test_assert( p == NULL );
1356 }
1357 
1358 static void test_alloc_zero_size(void)
1359 {
1360   size_t size;
1361   void *p;
1362   int eno;
1363 
1364   size = 0;
1365   errno = -1;
1366 
1367   RTEMS_OBFUSCATE_VARIABLE( size );
1368   p = malloc( size );
1369   rtems_test_assert( p == NULL );
1370   rtems_test_assert( errno == -1 );
1371 
1372   RTEMS_OBFUSCATE_VARIABLE( size );
1373   p = calloc( size, 1 );
1374   rtems_test_assert( p == NULL );
1375   rtems_test_assert( errno == -1 );
1376 
1377   RTEMS_OBFUSCATE_VARIABLE( size );
1378   p = rtems_malloc( size );
1379   rtems_test_assert( p == NULL );
1380   rtems_test_assert( errno == -1 );
1381 
1382   RTEMS_OBFUSCATE_VARIABLE( size );
1383   p = rtems_calloc( 1, size );
1384   rtems_test_assert( p == NULL );
1385   rtems_test_assert( errno == -1 );
1386 
1387   RTEMS_OBFUSCATE_VARIABLE( size );
1388   p = (void *)(uintptr_t) 1;
1389   eno = posix_memalign( &p, 32, size );
1390   rtems_test_assert( eno == 0 );
1391   rtems_test_assert( p == NULL );
1392   rtems_test_assert( errno == -1 );
1393 
1394   RTEMS_OBFUSCATE_VARIABLE( size );
1395   p = (void *)(uintptr_t) 1;
1396   eno = rtems_memalign( &p, 32, size );
1397   rtems_test_assert( eno == 0 );
1398   rtems_test_assert( p == NULL );
1399   rtems_test_assert( errno == -1 );
1400 
1401   RTEMS_OBFUSCATE_VARIABLE( size );
1402   p = aligned_alloc( 32, size );
1403   rtems_test_assert( p == NULL );
1404   rtems_test_assert( errno == -1 );
1405 
1406   RTEMS_OBFUSCATE_VARIABLE( size );
1407   p = realloc( NULL, size );
1408   rtems_test_assert( p == NULL );
1409   rtems_test_assert( errno == -1 );
1410 
1411   RTEMS_OBFUSCATE_VARIABLE( size );
1412   p = reallocarray( NULL, 1, size );
1413   rtems_test_assert( p == NULL );
1414   rtems_test_assert( errno == -1 );
1415 }
1416 
1417 rtems_task Init(
1418   rtems_task_argument argument
1419 )
1420 {
1421   void             *p1;
1422   rtems_time_of_day time;
1423   rtems_status_code status;
1424 
1425   TEST_BEGIN();
1426 
1427   build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
1428   status = rtems_clock_set( &time );
1429   directive_failed( status, "rtems_clock_set" );
1430 
1431   /*
1432    * Verify case where block is too large to calloc.
1433    */
1434 #pragma GCC diagnostic push
1435 #pragma GCC diagnostic ignored "-Walloc-size-larger-than=N"
1436   p1 = calloc( 1, SIZE_MAX );
1437   rtems_test_assert( p1 == NULL );
1438 
1439   p1 = calloc( SIZE_MAX, SIZE_MAX );
1440   rtems_test_assert( p1 == NULL );
1441 #pragma GCC diagnostic pop
1442 
1443   test_heap_initialize();
1444   test_heap_block_allocate();
1445   test_heap_allocate();
1446   test_heap_free();
1447   test_heap_resize_block();
1448   test_realloc();
1449   test_heap_cases_1();
1450   test_heap_extend();
1451   test_heap_extend_allocation_order();
1452   test_heap_extend_allocation_order_with_empty_heap();
1453   test_heap_no_extend();
1454   test_heap_info();
1455   test_heap_size_with_overhead();
1456   test_protected_heap_info();
1457   test_rtems_heap_allocate_aligned_with_boundary();
1458   test_rtems_malloc();
1459   test_rtems_calloc();
1460   test_greedy_allocate();
1461   test_alloc_zero_size();
1462 
1463   test_posix_memalign();
1464 
1465   Task_name[ 1 ] = rtems_build_name( 'T', 'A', '1', ' ' );
1466   Task_name[ 2 ] = rtems_build_name( 'T', 'A', '2', ' ' );
1467   Task_name[ 3 ] = rtems_build_name( 'T', 'A', '3', ' ' );
1468   Task_name[ 4 ] = rtems_build_name( 'T', 'A', '4', ' ' );
1469   Task_name[ 5 ] = rtems_build_name( 'T', 'A', '5', ' ' );
1470 
1471   status = rtems_task_create(
1472      Task_name[ 1 ],
1473      1,
1474      TASK_STACK_SIZE,
1475      RTEMS_DEFAULT_MODES,
1476      RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1477      &Task_id[ 1 ]
1478   );
1479   directive_failed( status, "rtems_task_create of TA1" );
1480 
1481   status = rtems_task_create(
1482      Task_name[ 2 ],
1483      1,
1484      TASK_STACK_SIZE,
1485      RTEMS_DEFAULT_MODES,
1486      RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1487      &Task_id[ 2 ]
1488   );
1489   directive_failed( status, "rtems_task_create of TA2" );
1490 
1491   status = rtems_task_create(
1492      Task_name[ 3 ],
1493      1,
1494      TASK_STACK_SIZE,
1495      RTEMS_DEFAULT_MODES,
1496      RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1497      &Task_id[ 3 ]
1498   );
1499   directive_failed( status, "rtems_task_create of TA3" );
1500 
1501   status = rtems_task_create(
1502      Task_name[ 4 ],
1503      1,
1504      TASK_STACK_SIZE,
1505      RTEMS_DEFAULT_MODES,
1506      RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1507      &Task_id[ 4 ]
1508   );
1509   directive_failed( status, "rtems_task_create of TA4" );
1510 
1511   status = rtems_task_create(
1512      Task_name[ 5 ],
1513      1,
1514      TASK_STACK_SIZE,
1515      RTEMS_DEFAULT_MODES,
1516      RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1517      &Task_id[ 5 ]
1518   );
1519   directive_failed( status, "rtems_task_create of TA5" );
1520 
1521   status = rtems_task_start( Task_id[ 1 ], Task_1_through_5, 0 );
1522   directive_failed( status, "rtems_task_start of TA1" );
1523 
1524   status = rtems_task_start( Task_id[ 2 ], Task_1_through_5, 0 );
1525   directive_failed( status, "rtems_task_start of TA2" );
1526 
1527   status = rtems_task_start( Task_id[ 3 ], Task_1_through_5, 0 );
1528   directive_failed( status, "rtems_task_start of TA3" );
1529 
1530   status = rtems_task_start( Task_id[ 4 ], Task_1_through_5, 0 );
1531   directive_failed( status, "rtems_task_start of TA4" );
1532 
1533   status = rtems_task_start( Task_id[ 5 ], Task_1_through_5, 0 );
1534   directive_failed( status, "rtems_task_start of TA5" );
1535 
1536   rtems_task_exit();
1537 }
1538 
1539 static void test_early_malloc( void )
1540 {
1541   void *p;
1542   char *q;
1543   void *r;
1544   void *s;
1545   void *t;
1546 
1547   p = malloc( 1 );
1548   rtems_test_assert( p != NULL );
1549 
1550   free( p );
1551 
1552   q = calloc( 1, 1 );
1553   rtems_test_assert( q != NULL );
1554   rtems_test_assert( p != q );
1555   rtems_test_assert( q[0] == 0 );
1556 
1557   free( q );
1558 
1559 /*
1560  * This was added to address the following warning.
1561  * warning: pointer 'q' used after 'free'
1562  */
1563 #pragma GCC diagnostic push
1564 #pragma GCC diagnostic ignored "-Wuse-after-free"
1565   r = realloc( q, 128 );
1566   rtems_test_assert( r == q );
1567 #pragma GCC diagnostic pop
1568 
1569   s = malloc( 1 );
1570   rtems_test_assert( s != NULL );
1571 
1572   free( s );
1573 
1574   t = realloc( r, 256 );
1575   rtems_test_assert( t != NULL );
1576   rtems_test_assert( t != r );
1577 
1578   free( t );
1579 }
1580 
1581 RTEMS_SYSINIT_ITEM(
1582   test_early_malloc,
1583   RTEMS_SYSINIT_INITIAL_EXTENSIONS,
1584   RTEMS_SYSINIT_ORDER_FIRST
1585 );