source: rtems/testsuites/libtests/malloctest/init.c @ 6b4e448

4.115
Last change on this file since 6b4e448 was b7cf09c3, checked in by Sebastian Huber <sebastian.huber@…>, on 07/23/13 at 19:48:18

libtests/malloctest: Fixes for RTEMS_DEBUG

  • Property mode set to 100644
File size: 35.2 KB
Line 
1/*  Init
2 *
3 *  This routine is the initialization task for this test program.
4 *  It is a user initialization task and has the responsibility for creating
5 *  and starting the tasks that make up the test.  If the time of day
6 *  clock is required for the test, it should also be set to a known
7 *  value by this function.
8 *
9 *  Input parameters:
10 *    argument - task argument
11 *
12 *  Output parameters:  NONE
13 *
14 *  COPYRIGHT (c) 1989-2011.
15 *  On-Line Applications Research Corporation (OAR).
16 *
17 *  Copyright (c) 2009, 2010 embedded brains GmbH.
18 *
19 *  The license and distribution terms for this file may be
20 *  found in the file LICENSE in this distribution or at
21 *  http://www.rtems.com/license/LICENSE.
22 */
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
29#define CONFIGURE_INIT
30#include "system.h"
31
32#include <stdlib.h>
33#include <string.h>
34#include <inttypes.h>
35#include <errno.h>
36#include <rtems/score/protectedheap.h>
37#include <rtems/malloc.h>
38
39/*
40 *  A simple test of realloc
41 */
42static void test_realloc(void)
43{
44  void *p1, *p2, *p3, *p4;
45  size_t i;
46  int sc;
47  bool malloc_walk_ok;
48
49  /* Test growing reallocation "in place" */
50  p1 = malloc(1);
51  for (i=2 ; i<2048 ; i++) {
52    p2 = realloc(p1, i);
53    if (p2 != p1)
54      printf( "realloc - failed grow in place: "
55              "%p != realloc(%p,%zu)\n", p1, p2, i);
56    p1 = p2;
57  }
58  free(p1);
59
60  /* Test shrinking reallocation "in place" */
61  p1 = malloc(2048);
62  for (i=2047 ; i>=1; i--)  {
63    p2 = realloc(p1, i);
64    if (p2 != p1)
65      printf( "realloc - failed shrink in place: "
66              "%p != realloc(%p,%zu)\n", p1, p2, i);
67    p1 = p2;
68  }
69  free(p1);
70
71  /* Test realloc that should fail "in place", i.e.,
72   * fallback to free()-- malloc()
73   */
74  p1 = malloc(32);
75  p2 = malloc(32);
76  p3 = realloc(p1, 64);
77  if (p3 == p1 || p3 == NULL)
78    printf(
79      "realloc - failed non-in place: realloc(%p,%d) = %p\n", p1, 64, p3);
80  free(p3);
81  free(p2);
82
83  /*
84   *  Yet another case
85   */
86  p1 = malloc(8);
87  p2 = malloc(8);
88  free(p1);
89  sc = posix_memalign(&p1, 16, 32);
90  if (!sc)
91    free(p1);
92
93  /*
94   *  Allocate with default alignment coverage
95   */
96  sc = rtems_memalign( &p4, 0, 8 );
97  if ( !sc && p4 )
98    free( p4 );
99
100  /*
101   * Walk the C Program Heap
102   */
103  puts( "malloc_walk - normal path" );
104  malloc_walk_ok = malloc_walk( 1234, false );
105  rtems_test_assert( malloc_walk_ok );
106
107  puts( "malloc_walk - in critical section path" );
108  _Thread_Disable_dispatch();
109  malloc_walk_ok = malloc_walk( 1234, false );
110  rtems_test_assert( malloc_walk_ok );
111  _Thread_Enable_dispatch();
112
113  /*
114   *  Realloc with a bad pointer to force a point
115   */
116  p4 = realloc( test_realloc, 32 );
117
118  p4 = _realloc_r( NULL, NULL, 1 );
119}
120
121#define TEST_HEAP_SIZE 2048
122
123uint8_t TestHeapMemory[TEST_HEAP_SIZE];
124
125Heap_Control TestHeap;
126
127static void test_heap_default_init(void)
128{
129  memset( &TestHeapMemory, 0x7f, TEST_HEAP_SIZE );
130  _Heap_Initialize( &TestHeap, TestHeapMemory, TEST_HEAP_SIZE, 0 );
131}
132
133static void test_free( void *addr )
134{
135  rtems_test_assert( _Heap_Free( &TestHeap, addr ) );
136
137  _Heap_Protection_free_all_delayed_blocks( &TestHeap );
138}
139
140static void test_heap_cases_1(void)
141{
142  void     *p1, *p2, *p3;
143  uintptr_t  u1, u2;
144  Heap_Resize_status rsc;
145
146  /*
147   * Another odd case.  What we are trying to do from Sergei
148   *
149   * 32-bit CPU when CPU_ALIGNMENT = 4 (most targets have 8) with the
150   * code like this:
151   */
152  test_heap_default_init();
153  p1 = _Heap_Allocate( &TestHeap, 12 );
154  p2 = _Heap_Allocate( &TestHeap, 32 );
155  p3 = _Heap_Allocate( &TestHeap, 32 );
156  test_free( p2 );
157  p2 = _Heap_Allocate_aligned( &TestHeap, 8, 28 );
158  test_free( p1 );
159  test_free( p2 );
160  test_free( p3 );
161
162  /*
163   *  Odd case in resizing a block.  Again test case outline per Sergei
164   */
165  test_heap_default_init();
166  p1 = _Heap_Allocate( &TestHeap, 32 );
167  p2 = _Heap_Allocate( &TestHeap, 8 );
168  p3 = _Heap_Allocate( &TestHeap, 32 );
169  test_free( p2 );
170  rsc = _Heap_Resize_block( &TestHeap, p1, 41, &u1, &u2 );
171  /* XXX what should we expect */
172  test_free( p3 );
173  test_free( p1 );
174
175  /*
176   *  To tackle a special case of resizing a block in order to cover the
177   *  code in heapresizeblock.c
178   *
179   *  Re-initialise the heap, so that the blocks created from now on
180   *  are contiguous.
181   */
182  test_heap_default_init();
183  puts( "Heap Initialized" );
184  p1 = _Heap_Allocate( &TestHeap, 400 );
185  rtems_test_assert( p1 != NULL );
186  p2 = _Heap_Allocate( &TestHeap, 496 );
187  rtems_test_assert( p2 != NULL );
188  rsc = _Heap_Resize_block( &TestHeap, p1, 256, &u1, &u2 );
189  rtems_test_assert( rsc == HEAP_RESIZE_SUCCESSFUL );
190  test_free( p1 );
191  test_free( p2 );
192}
193
194#define TEST_DEFAULT_PAGE_SIZE 128
195
196static void test_heap_init(uintptr_t page_size )
197{
198  uintptr_t rv = 0;
199
200  memset( &TestHeapMemory, 0x7f, TEST_HEAP_SIZE );
201
202  rv = _Heap_Initialize( &TestHeap, TestHeapMemory, TEST_HEAP_SIZE, page_size );
203  rtems_test_assert( rv > 0 );
204}
205
206static void test_check_alloc(
207  void *alloc_begin_ptr,
208  void *expected_alloc_begin_ptr,
209  uintptr_t alloc_size,
210  uintptr_t alignment,
211  uintptr_t boundary
212)
213{
214  uintptr_t const min_block_size = TestHeap.min_block_size;
215  uintptr_t const page_size = TestHeap.page_size;
216
217  rtems_test_assert( alloc_begin_ptr == expected_alloc_begin_ptr );
218
219  if( expected_alloc_begin_ptr != NULL ) {
220    uintptr_t const alloc_begin = (uintptr_t ) alloc_begin_ptr;
221    uintptr_t const alloc_end = alloc_begin + alloc_size;
222
223    uintptr_t const alloc_area_begin = _Heap_Align_down( alloc_begin, page_size );
224    uintptr_t const alloc_area_offset = alloc_begin - alloc_area_begin;
225#if UNUSED
226    uintptr_t const alloc_area_size = alloc_area_offset + alloc_size;
227#endif
228    Heap_Block *block = _Heap_Block_of_alloc_area( alloc_area_begin, page_size );
229    uintptr_t const block_begin = (uintptr_t ) block;
230    uintptr_t const block_size = _Heap_Block_size( block );
231    uintptr_t const block_end = block_begin + block_size;
232
233    rtems_test_assert( block_size >= min_block_size );
234    rtems_test_assert( block_begin < block_end );
235    rtems_test_assert(
236      _Heap_Is_aligned( block_begin + HEAP_BLOCK_HEADER_SIZE, page_size )
237    );
238    rtems_test_assert(
239      _Heap_Is_aligned( block_size, page_size )
240    );
241
242    rtems_test_assert( alloc_end <= block_end + HEAP_ALLOC_BONUS );
243    rtems_test_assert( alloc_area_begin > block_begin );
244    rtems_test_assert( alloc_area_offset < page_size );
245
246    rtems_test_assert( _Heap_Is_aligned( alloc_area_begin, page_size ) );
247    if ( alignment == 0 ) {
248      rtems_test_assert( alloc_begin == alloc_area_begin );
249    } else {
250      rtems_test_assert( _Heap_Is_aligned( alloc_begin, alignment ) );
251    }
252
253    if ( boundary != 0 ) {
254      uintptr_t boundary_line = _Heap_Align_down( alloc_end, boundary );
255
256      rtems_test_assert( alloc_size <= boundary );
257      rtems_test_assert(
258        boundary_line <= alloc_begin
259          || alloc_end <= boundary_line
260      );
261    }
262  }
263
264  rtems_test_assert(
265    page_size < CPU_ALIGNMENT
266      || _Heap_Walk( &TestHeap, 0, false )
267  );
268}
269
270static void test_check_alloc_simple(
271  void *alloc_begin_ptr,
272  uintptr_t alloc_size,
273  uintptr_t alignment,
274  uintptr_t boundary
275)
276{
277  test_check_alloc(
278    alloc_begin_ptr,
279    alloc_begin_ptr,
280    alloc_size,
281    alignment,
282    boundary
283  );
284}
285
286static void *test_alloc(
287  uintptr_t alloc_size,
288  uintptr_t alignment,
289  uintptr_t boundary,
290  void *expected_alloc_begin_ptr
291)
292{
293  void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
294    &TestHeap,
295    alloc_size,
296    alignment,
297    boundary
298  );
299
300  test_check_alloc(
301    alloc_begin_ptr,
302    expected_alloc_begin_ptr,
303    alloc_size,
304    alignment,
305    boundary
306  );
307
308  return alloc_begin_ptr;
309}
310
311static void *test_alloc_simple(
312  uintptr_t alloc_size,
313  uintptr_t alignment,
314  uintptr_t boundary
315)
316{
317  void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
318    &TestHeap,
319    alloc_size,
320    alignment,
321    boundary
322  );
323
324  test_check_alloc_simple(
325    alloc_begin_ptr,
326    alloc_size,
327    alignment,
328    boundary
329  );
330
331  rtems_test_assert( alloc_begin_ptr != NULL );
332
333  return alloc_begin_ptr;
334}
335
336static void *test_init_and_alloc(
337  uintptr_t alloc_size,
338  uintptr_t alignment,
339  uintptr_t boundary,
340  void *expected_alloc_begin_ptr
341)
342{
343  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
344
345  return test_alloc(
346    alloc_size,
347    alignment,
348    boundary,
349    expected_alloc_begin_ptr
350  );
351}
352
353static void *test_init_and_alloc_simple(
354  uintptr_t alloc_size,
355  uintptr_t alignment,
356  uintptr_t boundary
357)
358{
359  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
360
361  return test_alloc_simple(
362    alloc_size,
363    alignment,
364    boundary
365  );
366}
367
368static uintptr_t test_page_size(void)
369{
370  return TestHeap.page_size;
371}
372
373static void test_heap_do_initialize(
374  uintptr_t area_size,
375  uintptr_t page_size,
376  uintptr_t success_expected
377)
378{
379  uintptr_t rv =
380    _Heap_Initialize( &TestHeap, TestHeapMemory, area_size, page_size );
381
382  if ( success_expected ) {
383    rtems_test_assert( rv > 0 && _Heap_Walk( &TestHeap, 0, false ) );
384  } else {
385    rtems_test_assert( rv == 0 );
386  }
387}
388
389static void test_heap_initialize(void)
390{
391  puts( "run tests for _Heap_Initialize()" );
392
393  test_heap_do_initialize( TEST_HEAP_SIZE, 0, true );
394
395  test_heap_do_initialize( TEST_HEAP_SIZE, TEST_DEFAULT_PAGE_SIZE, true );
396
397  test_heap_do_initialize( 0, 0, false );
398
399  test_heap_do_initialize( (uintptr_t) -1, 0, false );
400
401  test_heap_do_initialize( TEST_HEAP_SIZE, (uintptr_t) -1, false );
402
403  test_heap_do_initialize(
404    TEST_HEAP_SIZE,
405    (uintptr_t) (-2 * CPU_ALIGNMENT),
406    false
407  );
408}
409
410static void test_heap_allocate(void)
411{
412  void *p1 = NULL;
413  void *p2 = NULL;
414  void *p3 = NULL;
415  uintptr_t alloc_size = 0;
416  uintptr_t alignment = 0;
417  uintptr_t boundary = 0;
418  uintptr_t page_size = 0;
419  uintptr_t first_page_begin = 0;
420  uintptr_t previous_last_block_begin = 0;
421  uintptr_t previous_last_page_begin = 0;
422
423  uintptr_t last_block_begin = 0;
424  uintptr_t last_alloc_begin = 0;
425
426  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
427
428  last_block_begin = (uintptr_t) TestHeap.last_block;
429  last_alloc_begin = _Heap_Alloc_area_of_block( TestHeap.last_block );
430
431  puts( "run tests for _Heap_Allocate_aligned_with_boundary()");
432
433  puts( "\tcheck if NULL will be returned if size causes integer overflow" );
434
435  alloc_size = (uintptr_t ) -1;
436  alignment = 0;
437  boundary = 0;
438  test_init_and_alloc( alloc_size, alignment, boundary, NULL );
439
440  puts( "\ttry to allocate more space than the one which fits in the boundary" );
441
442  alloc_size = 2;
443  alignment = 0;
444  boundary = alloc_size - 1;
445  test_init_and_alloc( alloc_size, alignment, boundary, NULL );
446
447  puts( "\tcheck if alignment will be set to page size if only a boundary is given" );
448
449  alloc_size = 1;
450  boundary = 1;
451
452  alignment = 0;
453  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
454
455  alignment = test_page_size();
456  test_init_and_alloc( alloc_size, alignment, boundary, p1 );
457
458  puts( "\tcreate a block which is bigger then the first free space" );
459
460  alignment = 0;
461  boundary = 0;
462
463  alloc_size = test_page_size();
464  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
465  p2 = test_alloc_simple( alloc_size, alignment, boundary );
466  rtems_test_assert( p2 );
467
468  test_free( p1 );
469
470  alloc_size = 2 * alloc_size;
471  p3 = test_alloc_simple( alloc_size, alignment, boundary );
472  rtems_test_assert( p1 != p3 );
473
474  puts( "\tset boundary before allocation begin" );
475
476  alloc_size = 1;
477  alignment = 0;
478  boundary = last_alloc_begin - test_page_size();
479  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
480  rtems_test_assert( (uintptr_t ) p1 >= boundary );
481
482  puts( "\tset boundary between allocation begin and end" );
483  alloc_size = test_page_size();
484  alignment = 0;
485  boundary = last_alloc_begin - alloc_size / 2;
486  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
487  rtems_test_assert( (uintptr_t ) p1 + alloc_size <= boundary );
488
489  puts( "\tset boundary after allocation end" );
490  alloc_size = 1;
491  alignment = 0;
492  boundary = last_alloc_begin;
493  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
494  rtems_test_assert( (uintptr_t ) p1 + alloc_size < boundary );
495
496  puts( "\tset boundary on allocation end" );
497  alloc_size = TEST_DEFAULT_PAGE_SIZE - HEAP_BLOCK_HEADER_SIZE;
498  alignment = 0;
499  boundary = last_block_begin;
500  p1 = (void *) (last_alloc_begin - TEST_DEFAULT_PAGE_SIZE);
501  test_init_and_alloc( alloc_size, alignment, boundary, p1);
502
503  puts( "\talign the allocation to different positions in the block header" );
504
505  page_size = sizeof(uintptr_t);
506  alloc_size = 1;
507  boundary = 0;
508
509  test_heap_init( page_size );
510
511  /* Force the page size to a small enough value */
512  TestHeap.page_size = page_size;
513
514  alignment = first_page_begin - sizeof(uintptr_t);
515  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
516
517  first_page_begin = ((uintptr_t) TestHeap.first_block ) + HEAP_BLOCK_HEADER_SIZE;
518  alignment = first_page_begin + sizeof(uintptr_t);
519  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
520
521  first_page_begin = ((uintptr_t) TestHeap.first_block )
522          + HEAP_BLOCK_HEADER_SIZE;
523  alignment = first_page_begin;
524  p1 = test_alloc_simple( alloc_size, alignment, boundary );
525
526  puts( "\tallocate last block with different boundarys" );
527  page_size = TEST_DEFAULT_PAGE_SIZE;
528  test_heap_init( page_size );
529  previous_last_block_begin = ((uintptr_t) TestHeap.last_block )
530          - TestHeap.min_block_size;
531  previous_last_page_begin = previous_last_block_begin
532          + HEAP_BLOCK_HEADER_SIZE;
533  alloc_size = TestHeap.page_size - HEAP_BLOCK_HEADER_SIZE;
534  alignment = sizeof(uintptr_t);
535  boundary = 0;
536  p1 = test_alloc( alloc_size, alignment, boundary, (void *) (previous_last_page_begin + sizeof(uintptr_t)));
537
538  test_heap_init( page_size );
539  boundary = ((uintptr_t) TestHeap.last_block );
540  p1 = test_alloc( alloc_size, alignment, boundary, (void *) previous_last_page_begin );
541
542  puts( "\tbreak the boundaries and aligns more than one time" );
543
544  page_size = CPU_ALIGNMENT * 20;
545  alloc_size = page_size / 4;
546  alignment = page_size / 5;
547  boundary = page_size / 4;
548  test_heap_init( page_size );
549  p1 = (void *) (_Heap_Alloc_area_of_block( TestHeap.last_block ) - page_size );
550  test_alloc( alloc_size, alignment, boundary, p1);
551
552  puts( "\tdifferent combinations, so that there is no valid block at the end" );
553
554  page_size = sizeof(uintptr_t);
555
556  test_heap_init( 0 );
557
558  /* Force the page size to a small enough value */
559  TestHeap.page_size = page_size;
560
561  alloc_size = 1;
562  alignment = (uintptr_t) TestHeap.last_block;
563  boundary = 0;
564  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
565
566  boundary = (uintptr_t) TestHeap.last_block;
567  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
568
569  alloc_size = 0;
570  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
571
572  alloc_size = 1;
573  alignment = sizeof(uintptr_t);
574  boundary = 0;
575  p1 = test_alloc_simple( alloc_size, alignment, boundary );
576
577  puts( "\ttry to create a block, which is not possible because of the alignment and boundary" );
578
579  alloc_size = 2;
580  boundary = _Heap_Alloc_area_of_block( TestHeap.first_block )
581          + _Heap_Block_size( TestHeap.first_block ) / 2;
582  alignment = boundary - 1;
583  p1 = test_init_and_alloc( alloc_size, alignment, boundary, NULL );
584
585  alloc_size = 2;
586  alignment = _Heap_Alloc_area_of_block( TestHeap.first_block );
587  boundary = alignment + 1;
588  p1 = test_init_and_alloc( alloc_size, alignment, boundary, NULL );
589}
590
591static void test_heap_free(void)
592{
593  Heap_Control *heap = &TestHeap;
594  void *p;
595  Heap_Block *block;
596  bool ok;
597
598  _Heap_Initialize( heap, &TestHeapMemory[0], sizeof(TestHeapMemory), 0 );
599
600  p = _Heap_Allocate( heap, 1 );
601  rtems_test_assert( p != NULL );
602
603  block = _Heap_Block_of_alloc_area( (uintptr_t) p, heap->page_size );
604
605  /*
606   * This will kick the next block outside of the heap area and the next
607   * _Heap_Free() will detect this.
608   */
609  block->size_and_flag += sizeof(TestHeapMemory);
610
611  ok = _Heap_Free( heap, p );
612  rtems_test_assert( !ok );
613}
614
615static void *test_create_used_block( void )
616{
617  uintptr_t const alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE;
618  uintptr_t const alignment = 0;
619  uintptr_t const boundary = 0;
620
621  return test_alloc_simple( alloc_size, alignment, boundary );
622}
623
624static void test_block_alloc(
625  int free_variant,
626  int alloc_variant,
627  uintptr_t alloc_begin,
628  uintptr_t alloc_size
629)
630{
631  void *p1 = NULL;
632  void *p2 = NULL;
633  void *p3 = NULL;
634
635  uintptr_t size_fresh_heap = 0;
636  uintptr_t pages_per_default_block = 0;
637  uint32_t exp_free_pages = 0;
638  uint32_t exp_free_blocks = 0;
639  uint32_t exp_used_blocks = 0;
640
641  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
642
643  size_fresh_heap = _Heap_Get_size( &TestHeap );
644  exp_free_pages = size_fresh_heap / TestHeap.page_size;
645
646  p1 = test_create_used_block();
647  p2 = test_create_used_block();
648  p3 = test_create_used_block();
649
650  pages_per_default_block = _Heap_Block_size(
651    _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size )
652  ) / TestHeap.page_size;
653
654  if (free_variant == 1) {
655    test_free( p1 );
656  } else if (free_variant == 2) {
657    test_free( p3 );
658  } else if (free_variant == 3) {
659    test_free( p2 );
660    test_free( p3 );
661  }
662
663  _Heap_Block_allocate(
664    &TestHeap,
665    _Heap_Block_of_alloc_area( (uintptr_t) p2, test_page_size()),
666    alloc_begin,
667    alloc_size
668  );
669
670  test_check_alloc_simple( (void *) alloc_begin, alloc_size, 0, 0 );
671
672  /* check statistics */
673  switch( free_variant ) {
674    case 1:
675      exp_free_pages = exp_free_pages - 2 * pages_per_default_block;
676      exp_used_blocks = 2;
677
678      switch( alloc_variant ) {
679        case 1:
680          /* allocate block full space */
681          exp_free_blocks = 2;
682          break;
683        case 2:
684          /* allocate block in the middle */
685          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
686          exp_free_blocks = 3;
687          break;
688        case 3:
689          /* allocate block at the end */
690          exp_free_pages = exp_free_pages + pages_per_default_block - 2;
691          exp_free_blocks = 2;
692          break;
693        default:
694          /* allocate block at the beginning */
695          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
696          exp_free_blocks = 3;
697          break;
698      }
699      break;
700    case 2:
701      exp_free_pages = exp_free_pages - 2 * pages_per_default_block;
702      exp_used_blocks = 2;
703
704      switch( alloc_variant ) {
705        case 1:
706          /* allocate block full space */
707          exp_free_blocks = 1;
708          break;
709        case 2:
710          /* allocate block in the middle */
711          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
712          exp_free_blocks = 2;
713          break;
714        case 3:
715          /* allocate block at the end */
716          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
717          exp_free_blocks = 2;
718          break;
719        default:
720          /* allocate block at the beginning */
721          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
722          exp_free_blocks = 1;
723          break;
724      }
725      break;
726    case 3:
727      exp_free_pages = exp_free_pages - pages_per_default_block;
728      exp_used_blocks = 2;
729
730      switch( alloc_variant ) {
731        case 1:
732          /* allocate block full space */
733          exp_free_pages = exp_free_pages - pages_per_default_block;
734          exp_free_blocks = 1;
735          break;
736        case 2:
737          /* allocate block in the middle */
738          exp_free_pages = exp_free_pages - 1;
739          exp_free_blocks = 2;
740          break;
741        case 3:
742          /* allocate block at the end */
743          exp_free_pages = exp_free_pages - 2;
744          exp_free_blocks = 2;
745          break;
746        default:
747          /* allocate block at the beginning */
748          exp_free_pages = exp_free_pages - 1;
749          exp_free_blocks = 1;
750          break;
751      }
752      break;
753    default:
754      exp_free_pages = exp_free_pages - 3 * pages_per_default_block;
755      exp_used_blocks = 3;
756
757      switch( alloc_variant ) {
758        case 1:
759          /* allocate block full space */
760          exp_free_blocks = 1;
761          break;
762        case 2:
763          /* allocate block in the middle */
764          exp_free_blocks = 3;
765          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
766          break;
767        case 3:
768          /* allocate block at the end */
769          exp_free_blocks = 2;
770          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
771          break;
772        default:
773          /* allocate block at the beginning */
774          exp_free_blocks = 2;
775          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
776      }
777  }
778
779  rtems_test_assert( TestHeap.stats.free_size == exp_free_pages * TestHeap.page_size );
780  rtems_test_assert( TestHeap.stats.free_blocks == exp_free_blocks );
781  rtems_test_assert( TestHeap.stats.used_blocks == exp_used_blocks );
782}
783
784static void test_heap_do_block_allocate( int variant, void *p2 )
785{
786  Heap_Block *const block =
787    _Heap_Block_of_alloc_area( (uintptr_t) p2, test_page_size());
788  uintptr_t const alloc_box_begin = _Heap_Alloc_area_of_block( block );
789  uintptr_t const alloc_box_size = _Heap_Block_size( block );
790  uintptr_t const alloc_box_end = alloc_box_begin + alloc_box_size;
791  uintptr_t alloc_begin = 0;
792  uintptr_t alloc_size = 0;
793
794  puts( "\tallocate block at the beginning");
795  alloc_begin = alloc_box_begin;
796  alloc_size = 0;
797  test_block_alloc( variant, 0, alloc_begin, alloc_size );
798
799  puts( "\tallocate block full space");
800  alloc_begin = alloc_box_begin;
801  alloc_size = alloc_box_size + HEAP_ALLOC_BONUS
802    - HEAP_BLOCK_HEADER_SIZE;
803  test_block_alloc( variant, 1, alloc_begin, alloc_size );
804
805  puts( "\tallocate block in the middle");
806  alloc_begin = alloc_box_begin + TEST_DEFAULT_PAGE_SIZE;
807  alloc_size = 0;
808  test_block_alloc( variant, 2, alloc_begin, alloc_size );
809
810  puts( "\tallocate block at the end");
811  alloc_begin = alloc_box_end - TEST_DEFAULT_PAGE_SIZE;
812  alloc_size = TEST_DEFAULT_PAGE_SIZE + HEAP_ALLOC_BONUS
813    - HEAP_BLOCK_HEADER_SIZE;
814  test_block_alloc( variant, 3, alloc_begin, alloc_size );
815}
816
817static void test_heap_block_allocate( void )
818{
819  void *p2 = NULL;
820
821  puts( "run tests for _Heap_Block_allocate()" );
822
823  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
824
825  test_create_used_block();
826  p2 = test_create_used_block();
827
828  test_heap_do_block_allocate( 0, p2 );
829  test_heap_do_block_allocate( 1, p2 );
830  test_heap_do_block_allocate( 2, p2 );
831  test_heap_do_block_allocate( 3, p2 );
832}
833
834static void *test_alloc_one_page(void)
835{
836  void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
837    &TestHeap,
838    1,
839    0,
840    0
841  );
842
843  test_check_alloc_simple(
844    alloc_begin_ptr,
845    1,
846    0,
847    0
848  );
849
850  rtems_test_assert( alloc_begin_ptr != NULL );
851
852  return alloc_begin_ptr;
853}
854
855static void *test_alloc_two_pages(void)
856{
857  void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
858    &TestHeap,
859    3 * TestHeap.page_size / 2,
860    0,
861    0
862  );
863
864  test_check_alloc_simple(
865    alloc_begin_ptr,
866    3 * TestHeap.page_size / 2,
867    0,
868    0
869  );
870
871  rtems_test_assert( alloc_begin_ptr != NULL );
872
873  return alloc_begin_ptr;
874}
875
876static void test_simple_resize_block(
877  void *alloc_pointer,
878  uintptr_t new_alloc_size,
879  Heap_Resize_status expected_status
880)
881{
882  uintptr_t old_size = 0;
883  uintptr_t new_size = 0;
884
885  Heap_Resize_status status = _Heap_Resize_block(
886    &TestHeap,
887    alloc_pointer,
888    new_alloc_size,
889    &old_size,
890    &new_size
891  );
892
893  rtems_test_assert( status == expected_status );
894}
895
896static void test_heap_resize_block(void)
897{
898  void *p1, *p2, *p3;
899  uintptr_t new_alloc_size = 0;
900  Heap_Block *block = NULL;
901
902  puts( "run tests for _Heap_Resize_Block()" );
903
904  puts( "\tgive a block outside the heap to the function" );
905  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
906  p1 = TestHeap.first_block - TEST_DEFAULT_PAGE_SIZE;
907  new_alloc_size = 1;
908  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_FATAL_ERROR );
909
910  puts( "\tincrease size");
911
912  puts( "\t\tlet the next block be used alredy and try to get a size bigger than the actual block" );
913  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
914  p1 = test_alloc_one_page();
915  rtems_test_assert( p1 );
916
917  p2 = test_alloc_one_page();
918  rtems_test_assert( p2 );
919
920  new_alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE / 2;
921  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_UNSATISFIED );
922
923  puts( "\t\tnext block not used and try to set the new allocation size between the page-alignments" );
924  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
925  p1 = test_alloc_one_page();
926  new_alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE / 2;
927  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
928
929  puts( "\t\tlet the block after the next be used and try to allocate more then one pagesize more" );
930  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
931  p1 = test_alloc_one_page();
932  rtems_test_assert( p1 );
933
934  p2 = test_alloc_one_page();
935  rtems_test_assert( p2 );
936
937  p3 = test_alloc_one_page();
938  rtems_test_assert( p3 );
939
940  test_free( p2 );
941  new_alloc_size = 5 * TEST_DEFAULT_PAGE_SIZE / 2;
942  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_UNSATISFIED );
943
944  puts( "\ttry to resize to the same size" );
945  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
946  p1 = test_alloc_one_page();
947  block = _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size );
948  new_alloc_size = _Heap_Block_size( block );
949  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
950
951  puts( "\tdecrease size");
952
953  puts( "\t\tdecrease a block with two pages to one page" );
954  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
955  p1 = test_alloc_two_pages();
956  new_alloc_size = 1;
957  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
958
959  puts( "\t\tresize the block to the size 0" );
960  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
961  p1 = test_alloc_one_page();
962  new_alloc_size = 0;
963  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
964}
965
966static void test_heap_assert(bool ret, bool expected)
967{
968  rtems_test_assert( ret == expected );
969  rtems_test_assert( _Heap_Walk( &TestHeap, 0, false ) );
970}
971
972static void test_heap_extend(void)
973{
974  bool ret = false;
975  Heap_Control *heap = &TestHeap;
976  uint8_t *area_begin = TestHeapMemory;
977  uint8_t *sub_area_begin;
978  uint8_t *sub_area_end;
979
980  _Heap_Initialize( heap, area_begin + 768, 256, 0 );
981  sub_area_begin = (uint8_t *) heap->first_block;
982  sub_area_end = (uint8_t *) _Heap_Alloc_area_of_block( heap->last_block );
983
984  puts( "heap extend - link below" );
985  ret = _Protected_heap_Extend( heap, area_begin + 0, 256 );
986  test_heap_assert( ret, true );
987
988  puts( "heap extend - merge below overlap" );
989  ret = _Protected_heap_Extend( heap, sub_area_begin - 128, 256 );
990  test_heap_assert( ret, false );
991
992  puts( "heap extend - merge below" );
993  ret = _Protected_heap_Extend( heap, sub_area_begin - 256, 256 );
994  test_heap_assert( ret, true );
995
996  puts( "heap extend - merge above overlap" );
997  ret = _Protected_heap_Extend( heap, sub_area_end - 128, 256 );
998  test_heap_assert( ret, false );
999
1000  puts( "heap extend - merge above" );
1001  ret = _Protected_heap_Extend( heap, sub_area_end, 256 );
1002  test_heap_assert( ret, true );
1003
1004  puts( "heap extend - link above" );
1005  ret = _Protected_heap_Extend( heap, area_begin + 1536, 256 );
1006  test_heap_assert( ret, true );
1007
1008  puts( "heap extend - area too small" );
1009  ret = _Protected_heap_Extend( heap, area_begin + 2048, 0 );
1010  test_heap_assert( ret, false );
1011
1012  puts( "heap extend - invalid area" );
1013  ret = _Protected_heap_Extend( heap, (void *) -1, 2 );
1014  test_heap_assert( ret, false );
1015
1016  area_begin = (uint8_t *) (((uintptr_t) area_begin) | 1);
1017
1018  _Heap_Initialize( heap, area_begin + 768, 256, 0 );
1019
1020  puts( "heap extend - merge below with align up" );
1021  ret = _Protected_heap_Extend( heap, area_begin + 512, 256 );
1022  test_heap_assert( ret, true );
1023}
1024
1025static void test_heap_extend_allocation_order(void)
1026{
1027  Heap_Control *heap = &TestHeap;
1028  uintptr_t size = 256;
1029  uintptr_t gap = 256;
1030  uint8_t *init_area_begin = TestHeapMemory;
1031  uint8_t *extend_area_begin = init_area_begin + size + gap;
1032  bool ret;
1033  uint8_t *p;
1034
1035  _Heap_Initialize( heap, init_area_begin, size, 0 );
1036
1037  ret = _Protected_heap_Extend( heap, extend_area_begin, size );
1038  test_heap_assert( ret, true );
1039
1040  p = _Heap_Allocate( heap, 1 );
1041  rtems_test_assert( (uintptr_t) (p - init_area_begin) < size );
1042}
1043
1044static void test_heap_extend_allocation_order_with_empty_heap(void)
1045{
1046  Heap_Control *heap = &TestHeap;
1047  uintptr_t size = 256;
1048  uintptr_t gap = 256;
1049  uint8_t *init_area_begin = TestHeapMemory;
1050  uint8_t *extend_area_begin = init_area_begin + size + gap;
1051  bool ret;
1052  uint8_t *p;
1053
1054  _Heap_Initialize( heap, init_area_begin, size, 0 );
1055
1056  _Heap_Greedy_allocate( heap, NULL, 0 );
1057
1058  ret = _Protected_heap_Extend( heap, extend_area_begin, size );
1059  test_heap_assert( ret, true );
1060
1061  p = _Heap_Allocate( heap, 1 );
1062  rtems_test_assert( (uintptr_t) (p - extend_area_begin) < size );
1063}
1064
1065static void test_heap_no_extend(void)
1066{
1067  uintptr_t extended_space = _Heap_No_extend( NULL, 0, 0, 0 );
1068  rtems_test_assert( extended_space == 0 );
1069}
1070
1071static void free_all_delayed_blocks( void )
1072{
1073  rtems_resource_snapshot unused;
1074
1075  rtems_resource_snapshot_take( &unused );
1076}
1077
1078static void do_free( void *p )
1079{
1080  free( p );
1081  free_all_delayed_blocks();
1082}
1083
1084static void test_heap_info(void)
1085{
1086  size_t                  s1, s2;
1087  void                   *p1;
1088  int                     sc;
1089  Heap_Information_block  the_info;
1090
1091  free_all_delayed_blocks();
1092
1093  s1 = malloc_free_space();
1094  p1 = malloc( 512 );
1095  s2 = malloc_free_space();
1096  puts( "malloc_free_space - check malloc space drops after malloc" );
1097  rtems_test_assert( s1 );
1098  rtems_test_assert( s2 );
1099  rtems_test_assert( s2 <= s1 );
1100  do_free( p1 );
1101
1102  puts( "malloc_free_space - verify free space returns to previous value" );
1103  s2 = malloc_free_space();
1104  rtems_test_assert( s1 == s2 );
1105
1106  puts( "malloc_info - called with NULL\n" );
1107  sc = malloc_info( NULL );
1108  rtems_test_assert( sc == -1 );
1109
1110  puts( "malloc_info - check free space drops after malloc" );
1111  sc = malloc_info( &the_info );
1112  rtems_test_assert( sc == 0 );
1113  s1 = the_info.Free.largest;
1114
1115  p1 = malloc( 512 );
1116
1117  sc = malloc_info( &the_info );
1118  rtems_test_assert( sc == 0 );
1119  s2 = the_info.Free.largest;
1120
1121  rtems_test_assert( s1 );
1122  rtems_test_assert( s2 );
1123  rtems_test_assert( s2 <= s1 );
1124  do_free( p1 );
1125
1126  puts( "malloc_info - verify free space returns to previous value" );
1127  sc = malloc_info( &the_info );
1128  rtems_test_assert( sc == 0 );
1129  rtems_test_assert( s1 == the_info.Free.largest );
1130}
1131
1132static void test_protected_heap_info(void)
1133{
1134  Heap_Control           heap;
1135  Heap_Information_block info;
1136  bool                   rc;
1137
1138  puts( "_Protected_heap_Get_information - NULL heap" );
1139  rc = _Protected_heap_Get_information( NULL, &info );
1140  rtems_test_assert( rc == false );
1141
1142  puts( "_Protected_heap_Get_information - NULL info" );
1143  rc = _Protected_heap_Get_information( &heap, NULL );
1144  rtems_test_assert( rc == false );
1145}
1146
1147static void test_rtems_heap_allocate_aligned_with_boundary(void)
1148{
1149  void *p = NULL;
1150
1151  p = rtems_heap_allocate_aligned_with_boundary(1, 1, 1);
1152  rtems_test_assert( p != NULL );
1153  free(p);
1154
1155  _Thread_Disable_dispatch();
1156  p = rtems_heap_allocate_aligned_with_boundary(1, 1, 1);
1157  _Thread_Enable_dispatch();
1158  rtems_test_assert( p == NULL );
1159}
1160
1161/*
1162 *  A simple test of posix_memalign
1163 */
1164static void test_posix_memalign(void)
1165{
1166  void *p1;
1167  int i;
1168  int sc;
1169  int maximumShift;
1170
1171  puts( "posix_memalign - NULL return pointer -- EINVAL" );
1172  sc = posix_memalign( NULL, 32, 8 );
1173  fatal_posix_service_status( sc, EINVAL, "posix_memalign NULL pointer" );
1174
1175  puts( "posix_memalign - alignment of 0 -- EINVAL" );
1176  sc = posix_memalign( &p1, 0, 8 );
1177  fatal_posix_service_status( sc, EINVAL, "posix_memalign alignment of 0" );
1178
1179  puts( "posix_memalign - alignment  of 2-- EINVAL" );
1180  sc = posix_memalign( &p1, 2, 8 );
1181  fatal_posix_service_status( sc, EINVAL, "posix_memalign alignment of 2" );
1182
1183  maximumShift = (sizeof(size_t) * CHAR_BIT) - 1;
1184  for ( i=sizeof(void *) ; i<maximumShift ; i++ ) {
1185    size_t alignment = 1 << i;
1186    printf( "posix_memalign - alignment of %zd -- OK\n", alignment);
1187    sc = posix_memalign( &p1, alignment, 8 );
1188    if ( sc == ENOMEM ) {
1189      printf( "posix_memalign - ran out of memory trying %zd\n", alignment );
1190      break;
1191    }
1192    posix_service_failed( sc, "posix_memalign alignment OK" );
1193
1194    free( p1 );
1195  }
1196  for ( ; i<maximumShift ; i++ ) {
1197    size_t alignment = 1 << i;
1198    printf( "posix_memalign - alignment of %zd -- SKIPPED\n", alignment);
1199  }
1200
1201}
1202
1203static void test_greedy_allocate(void)
1204{
1205  Heap_Control *heap = &TestHeap;
1206  uintptr_t block_size = 1;
1207  void *p;
1208
1209  _Heap_Initialize( heap, &TestHeapMemory[0], sizeof(TestHeapMemory), 0 );
1210
1211  _Heap_Greedy_allocate( heap, &block_size, 1 );
1212
1213  p = _Heap_Allocate( heap, 1 );
1214  rtems_test_assert( p != NULL );
1215
1216  p = _Heap_Allocate( heap, 1 );
1217  rtems_test_assert( p == NULL );
1218
1219  /* The internal allocation fails */
1220  _Heap_Greedy_allocate( heap, &block_size, 1 );
1221
1222  p = _Heap_Allocate( heap, 1 );
1223  rtems_test_assert( p == NULL );
1224}
1225
1226rtems_task Init(
1227  rtems_task_argument argument
1228)
1229{
1230  void             *p1;
1231  rtems_time_of_day time;
1232  rtems_status_code status;
1233
1234  puts( "\n\n*** MALLOC TEST ***" );
1235
1236  build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
1237  status = rtems_clock_set( &time );
1238  directive_failed( status, "rtems_clock_set" );
1239
1240  /*
1241   * Verify case where block is too large to calloc.
1242   */
1243  p1 = calloc( 1, SIZE_MAX );
1244  if (p1) {
1245    printf("ERROR on attempt to calloc SIZE_MAX block expected failure.");
1246    free( p1 );
1247  }
1248
1249  /*
1250   * Verify error case where malloc of size 0.
1251   */
1252  p1 = malloc( 0 );
1253  if (p1) {
1254    printf("ERROR on attempt to malloc size 0 block expected failure.");
1255    free( p1 );
1256  }
1257
1258
1259
1260  test_heap_initialize();
1261  test_heap_block_allocate();
1262  test_heap_allocate();
1263  test_heap_free();
1264  test_heap_resize_block();
1265  test_realloc();
1266  test_heap_cases_1();
1267  test_heap_extend();
1268  test_heap_extend_allocation_order();
1269  test_heap_extend_allocation_order_with_empty_heap();
1270  test_heap_no_extend();
1271  test_heap_info();
1272  test_protected_heap_info();
1273  test_rtems_heap_allocate_aligned_with_boundary();
1274  test_greedy_allocate();
1275
1276  test_posix_memalign();
1277
1278  Task_name[ 1 ] = rtems_build_name( 'T', 'A', '1', ' ' );
1279  Task_name[ 2 ] = rtems_build_name( 'T', 'A', '2', ' ' );
1280  Task_name[ 3 ] = rtems_build_name( 'T', 'A', '3', ' ' );
1281  Task_name[ 4 ] = rtems_build_name( 'T', 'A', '4', ' ' );
1282  Task_name[ 5 ] = rtems_build_name( 'T', 'A', '5', ' ' );
1283
1284  status = rtems_task_create(
1285     Task_name[ 1 ],
1286     1,
1287     TASK_STACK_SIZE,
1288     RTEMS_DEFAULT_MODES,
1289     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1290     &Task_id[ 1 ]
1291  );
1292  directive_failed( status, "rtems_task_create of TA1" );
1293
1294  status = rtems_task_create(
1295     Task_name[ 2 ],
1296     1,
1297     TASK_STACK_SIZE,
1298     RTEMS_DEFAULT_MODES,
1299     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1300     &Task_id[ 2 ]
1301  );
1302  directive_failed( status, "rtems_task_create of TA2" );
1303
1304  status = rtems_task_create(
1305     Task_name[ 3 ],
1306     1,
1307     TASK_STACK_SIZE,
1308     RTEMS_DEFAULT_MODES,
1309     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1310     &Task_id[ 3 ]
1311  );
1312  directive_failed( status, "rtems_task_create of TA3" );
1313
1314  status = rtems_task_create(
1315     Task_name[ 4 ],
1316     1,
1317     TASK_STACK_SIZE,
1318     RTEMS_DEFAULT_MODES,
1319     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1320     &Task_id[ 4 ]
1321  );
1322  directive_failed( status, "rtems_task_create of TA4" );
1323
1324  status = rtems_task_create(
1325     Task_name[ 5 ],
1326     1,
1327     TASK_STACK_SIZE,
1328     RTEMS_DEFAULT_MODES,
1329     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1330     &Task_id[ 5 ]
1331  );
1332  directive_failed( status, "rtems_task_create of TA5" );
1333
1334  status = rtems_task_start( Task_id[ 1 ], Task_1_through_5, 0 );
1335  directive_failed( status, "rtems_task_start of TA1" );
1336
1337  status = rtems_task_start( Task_id[ 2 ], Task_1_through_5, 0 );
1338  directive_failed( status, "rtems_task_start of TA2" );
1339
1340  status = rtems_task_start( Task_id[ 3 ], Task_1_through_5, 0 );
1341  directive_failed( status, "rtems_task_start of TA3" );
1342
1343  status = rtems_task_start( Task_id[ 4 ], Task_1_through_5, 0 );
1344  directive_failed( status, "rtems_task_start of TA4" );
1345
1346  status = rtems_task_start( Task_id[ 5 ], Task_1_through_5, 0 );
1347  directive_failed( status, "rtems_task_start of TA5" );
1348
1349  status = rtems_task_delete( RTEMS_SELF );
1350  directive_failed( status, "rtems_task_delete of RTEMS_SELF" );
1351}
Note: See TracBrowser for help on using the repository browser.