source: rtems/testsuites/libtests/malloctest/init.c @ b1274bd9

4.104.115
Last change on this file since b1274bd9 was b1274bd9, checked in by Ralf Corsepius <ralf.corsepius@…>, on Nov 30, 2009 at 3:33:25 AM

Whitespace removal.

  • Property mode set to 100644
File size: 30.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-2009.
15 *  On-Line Applications Research Corporation (OAR).
16 *
17 *  Copyright (c) 2009 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 *  $Id$
24 */
25
26#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
27#define CONFIGURE_INIT
28#include "system.h"
29
30#include <stdlib.h>
31#include <string.h>
32#include <inttypes.h>
33#include <errno.h>
34#include <rtems/score/protectedheap.h>
35
36/* HACK: Blatant visibility violations */
37extern int malloc_info(Heap_Information_block *the_info);
38extern void malloc_walk(size_t source, size_t printf_enabled);
39
40/*
41 *  A simple test of realloc
42 */
43static void test_realloc(void)
44{
45  void *p1, *p2, *p3, *p4;
46  size_t i;
47  int sc;
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( 1234, 0 );
105
106  puts( "malloc_walk - in critical section path" );
107  _Thread_Disable_dispatch();
108  malloc_walk( 1234, 0 );
109  _Thread_Enable_dispatch();
110
111  /*
112   *  Realloc with a bad pointer to force a point
113   */
114  p4 = realloc( test_realloc, 32 );
115}
116
117#define TEST_HEAP_SIZE 2048
118
119uint8_t TestHeapMemory[TEST_HEAP_SIZE];
120
121Heap_Control TestHeap;
122
123static void test_heap_default_init(void)
124{
125  memset( &TestHeapMemory, 0x7f, TEST_HEAP_SIZE );
126  _Heap_Initialize( &TestHeap, TestHeapMemory, TEST_HEAP_SIZE, 0 );
127}
128
129static void test_free( void *addr )
130{
131  rtems_test_assert( _Heap_Free( &TestHeap, addr ) );
132}
133
134static void test_heap_cases_1(void)
135{
136  void     *p1, *p2, *p3;
137  uintptr_t  u1, u2;
138  Heap_Resize_status rsc;
139
140  /*
141   * Another odd case.  What we are trying to do from Sergei
142   *
143   * 32-bit CPU when CPU_ALIGNMENT = 4 (most targets have 8) with the
144   * code like this:
145   */
146  test_heap_default_init();
147  p1 = _Heap_Allocate( &TestHeap, 12 );
148  p2 = _Heap_Allocate( &TestHeap, 32 );
149  p3 = _Heap_Allocate( &TestHeap, 32 );
150  test_free( p2 );
151  p2 = _Heap_Allocate_aligned( &TestHeap, 8, 28 );
152  test_free( p1 );
153  test_free( p2 );
154  test_free( p3 );
155
156  /*
157   *  Odd case in resizing a block.  Again test case outline per Sergei
158   */
159  test_heap_default_init();
160  p1 = _Heap_Allocate( &TestHeap, 32 );
161  p2 = _Heap_Allocate( &TestHeap, 8 );
162  p3 = _Heap_Allocate( &TestHeap, 32 );
163  test_free( p2 );
164  rsc = _Heap_Resize_block( &TestHeap, p1, 41, &u1, &u2 );
165  /* XXX what should we expect */
166  test_free( p3 );
167  test_free( p1 );
168
169  /*
170   *  To tackle a special case of resizing a block in order to cover the
171   *  code in heapresizeblock.c
172   *
173   *  Re-initialise the heap, so that the blocks created from now on
174   *  are contiguous.
175   */
176  test_heap_default_init();
177  puts( "Heap Initialized" );
178  p1 = _Heap_Allocate( &TestHeap, 400 );
179  rtems_test_assert( p1 != NULL );
180  p2 = _Heap_Allocate( &TestHeap, 496 );
181  rtems_test_assert( p2 != NULL );
182  rsc = _Heap_Resize_block( &TestHeap, p1, 256, &u1, &u2 );
183  rtems_test_assert( rsc == HEAP_RESIZE_SUCCESSFUL );
184  test_free( p1 );
185  test_free( p2 );
186}
187
188#define TEST_DEFAULT_PAGE_SIZE 128
189
190static void test_heap_init(uintptr_t page_size )
191{
192  uintptr_t rv = 0;
193
194  memset( &TestHeapMemory, 0x7f, TEST_HEAP_SIZE );
195
196  rv = _Heap_Initialize( &TestHeap, TestHeapMemory, TEST_HEAP_SIZE, page_size );
197  rtems_test_assert( rv > 0 );
198}
199
200static void test_check_alloc(
201  void *alloc_begin_ptr,
202  void *expected_alloc_begin_ptr,
203  uintptr_t alloc_size,
204  uintptr_t alignment,
205  uintptr_t boundary
206)
207{
208  uintptr_t const min_block_size = TestHeap.min_block_size;
209  uintptr_t const page_size = TestHeap.page_size;
210
211  rtems_test_assert( alloc_begin_ptr == expected_alloc_begin_ptr );
212
213  if( expected_alloc_begin_ptr != NULL ) {
214    uintptr_t const alloc_begin = (uintptr_t ) alloc_begin_ptr;
215    uintptr_t const alloc_end = alloc_begin + alloc_size;
216
217    uintptr_t const alloc_area_begin = _Heap_Align_down( alloc_begin, page_size );
218    uintptr_t const alloc_area_offset = alloc_begin - alloc_area_begin;
219#if UNUSED
220    uintptr_t const alloc_area_size = alloc_area_offset + alloc_size;
221#endif
222    Heap_Block *block = _Heap_Block_of_alloc_area( alloc_area_begin, page_size );
223    uintptr_t const block_begin = (uintptr_t ) block;
224    uintptr_t const block_size = _Heap_Block_size( block );
225    uintptr_t const block_end = block_begin + block_size;
226
227    rtems_test_assert( block_size >= min_block_size );
228    rtems_test_assert( block_begin < block_end );
229    rtems_test_assert(
230      _Heap_Is_aligned( block_begin + HEAP_BLOCK_HEADER_SIZE, page_size )
231    );
232    rtems_test_assert(
233      _Heap_Is_aligned( block_size, page_size )
234    );
235
236    rtems_test_assert( alloc_end <= block_end + HEAP_BLOCK_SIZE_OFFSET );
237    rtems_test_assert( alloc_area_begin > block_begin );
238    rtems_test_assert( alloc_area_offset < page_size );
239
240    rtems_test_assert( _Heap_Is_aligned( alloc_area_begin, page_size ) );
241    if ( alignment == 0 ) {
242      rtems_test_assert( alloc_begin == alloc_area_begin );
243    } else {
244      rtems_test_assert( _Heap_Is_aligned( alloc_begin, alignment ) );
245    }
246
247    if ( boundary != 0 ) {
248      uintptr_t boundary_line = _Heap_Align_down( alloc_end, boundary );
249
250      rtems_test_assert( alloc_size <= boundary );
251      rtems_test_assert(
252        boundary_line <= alloc_begin
253          || alloc_end <= boundary_line
254      );
255    }
256  }
257
258  rtems_test_assert(
259    page_size < CPU_ALIGNMENT
260      || _Heap_Walk( &TestHeap, 0, false )
261  );
262}
263
264static void test_check_alloc_simple(
265  void *alloc_begin_ptr,
266  uintptr_t alloc_size,
267  uintptr_t alignment,
268  uintptr_t boundary
269)
270{
271  test_check_alloc(
272    alloc_begin_ptr,
273    alloc_begin_ptr,
274    alloc_size,
275    alignment,
276    boundary
277  );
278}
279
280static void *test_alloc(
281  uintptr_t alloc_size,
282  uintptr_t alignment,
283  uintptr_t boundary,
284  void *expected_alloc_begin_ptr
285)
286{
287  void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
288    &TestHeap,
289    alloc_size,
290    alignment,
291    boundary
292  );
293
294  test_check_alloc(
295    alloc_begin_ptr,
296    expected_alloc_begin_ptr,
297    alloc_size,
298    alignment,
299    boundary
300  );
301
302  return alloc_begin_ptr;
303}
304
305static void *test_alloc_simple(
306  uintptr_t alloc_size,
307  uintptr_t alignment,
308  uintptr_t boundary
309)
310{
311  void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
312    &TestHeap,
313    alloc_size,
314    alignment,
315    boundary
316  );
317
318  test_check_alloc_simple(
319    alloc_begin_ptr,
320    alloc_size,
321    alignment,
322    boundary
323  );
324
325  rtems_test_assert( alloc_begin_ptr != NULL );
326
327  return alloc_begin_ptr;
328}
329
330static void *test_init_and_alloc(
331  uintptr_t alloc_size,
332  uintptr_t alignment,
333  uintptr_t boundary,
334  void *expected_alloc_begin_ptr
335)
336{
337  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
338
339  return test_alloc(
340    alloc_size,
341    alignment,
342    boundary,
343    expected_alloc_begin_ptr
344  );
345}
346
347static void *test_init_and_alloc_simple(
348  uintptr_t alloc_size,
349  uintptr_t alignment,
350  uintptr_t boundary
351)
352{
353  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
354
355  return test_alloc_simple(
356    alloc_size,
357    alignment,
358    boundary
359  );
360}
361
362static uintptr_t test_page_size(void)
363{
364  return TestHeap.page_size;
365}
366
367static void test_heap_do_initialize(
368  uintptr_t area_size,
369  uintptr_t page_size,
370  uintptr_t success_expected
371)
372{
373  uintptr_t rv =
374    _Heap_Initialize( &TestHeap, TestHeapMemory, area_size, page_size );
375
376  if ( success_expected ) {
377    rtems_test_assert( rv > 0 && _Heap_Walk( &TestHeap, 0, false ) );
378  } else {
379    rtems_test_assert( rv == 0 );
380  }
381}
382
383static void test_heap_initialize(void)
384{
385  puts( "run tests for _Heap_Initialize()" );
386
387  test_heap_do_initialize( TEST_HEAP_SIZE, 0, true );
388
389  test_heap_do_initialize( TEST_HEAP_SIZE, TEST_DEFAULT_PAGE_SIZE, true );
390
391  test_heap_do_initialize( 0, 0, false );
392
393  test_heap_do_initialize( (uintptr_t) -1, 0, false );
394
395  test_heap_do_initialize( TEST_HEAP_SIZE, (uintptr_t) -1, false );
396
397  test_heap_do_initialize(
398    TEST_HEAP_SIZE,
399    (uintptr_t) (-2 * CPU_ALIGNMENT),
400    false
401  );
402}
403
404static void test_heap_allocate(void)
405{
406  void *p1 = NULL;
407  void *p2 = NULL;
408  void *p3 = NULL;
409  uintptr_t alloc_size = 0;
410  uintptr_t alignment = 0;
411  uintptr_t boundary = 0;
412  uintptr_t page_size = 0;
413  uintptr_t first_page_begin = 0;
414  uintptr_t previous_last_block_begin = 0;
415  uintptr_t previous_last_page_begin = 0;
416
417  uintptr_t first_block_begin = 0;
418
419  uintptr_t last_block_begin = 0;
420  uintptr_t last_alloc_begin = 0;
421
422  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
423
424  first_block_begin = (uintptr_t) TestHeap.first_block;
425
426  last_block_begin = (uintptr_t) TestHeap.last_block;
427  last_alloc_begin = _Heap_Alloc_area_of_block( TestHeap.last_block );
428
429  puts( "run tests for _Heap_Allocate_aligned_with_boundary()");
430
431  puts( "\tcheck if NULL will be returned if size causes integer overflow" );
432
433  alloc_size = (uintptr_t ) -1;
434  alignment = 0;
435  boundary = 0;
436  test_init_and_alloc( alloc_size, alignment, boundary, NULL );
437
438  puts( "\ttry to allocate more space than the one which fits in the boundary" );
439
440  alloc_size = 2;
441  alignment = 0;
442  boundary = alloc_size - 1;
443  test_init_and_alloc( alloc_size, alignment, boundary, NULL );
444
445  puts( "\tcheck if alignment will be set to page size if only a boundary is given" );
446
447  alloc_size = 1;
448  boundary = 1;
449
450  alignment = 0;
451  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
452
453  alignment = test_page_size();
454  test_init_and_alloc( alloc_size, alignment, boundary, p1 );
455
456  puts( "\tcreate a block which is bigger then the first free space" );
457
458  alignment = 0;
459  boundary = 0;
460
461  alloc_size = test_page_size();
462  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
463  p2 = test_alloc_simple( alloc_size, alignment, boundary );
464  test_free( p1 );
465
466  alloc_size = 2 * alloc_size;
467  p3 = test_alloc_simple( alloc_size, alignment, boundary );
468  rtems_test_assert( p1 != p3 );
469
470  puts( "\tset boundary before allocation begin" );
471
472  alloc_size = 1;
473  alignment = 0;
474  boundary = last_alloc_begin - test_page_size();
475  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
476  rtems_test_assert( (uintptr_t ) p1 >= boundary );
477
478  puts( "\tset boundary between allocation begin and end" );
479  alloc_size = test_page_size();
480  alignment = 0;
481  boundary = last_alloc_begin - alloc_size / 2;
482  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
483  rtems_test_assert( (uintptr_t ) p1 + alloc_size <= boundary );
484
485  puts( "\tset boundary after allocation end" );
486  alloc_size = 1;
487  alignment = 0;
488  boundary = last_alloc_begin;
489  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
490  rtems_test_assert( (uintptr_t ) p1 + alloc_size < boundary );
491
492  puts( "\tset boundary on allocation end" );
493  alloc_size = TEST_DEFAULT_PAGE_SIZE - HEAP_BLOCK_HEADER_SIZE;
494  alignment = 0;
495  boundary = last_block_begin;
496  p1 = (void *) (last_alloc_begin - TEST_DEFAULT_PAGE_SIZE);
497  test_init_and_alloc( alloc_size, alignment, boundary, p1);
498
499  puts( "\talign the allocation to different positions in the block header" );
500
501  page_size = sizeof(uintptr_t);
502  alloc_size = 1;
503  boundary = 0;
504
505  test_heap_init( page_size );
506
507  /* Force the page size to a small enough value */
508  TestHeap.page_size = page_size;
509
510  alignment = first_page_begin - sizeof(uintptr_t);
511  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
512
513  first_page_begin = ((uintptr_t) TestHeap.first_block ) + HEAP_BLOCK_HEADER_SIZE;
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 )
518          + HEAP_BLOCK_HEADER_SIZE;
519  alignment = first_page_begin;
520  p1 = test_alloc_simple( alloc_size, alignment, boundary );
521
522  puts( "\tallocate last block with different boundarys" );
523  page_size = TEST_DEFAULT_PAGE_SIZE;
524  test_heap_init( page_size );
525  previous_last_block_begin = ((uintptr_t) TestHeap.last_block )
526          - TestHeap.min_block_size;
527  previous_last_page_begin = previous_last_block_begin
528          + HEAP_BLOCK_HEADER_SIZE;
529  alloc_size = TestHeap.page_size - HEAP_BLOCK_HEADER_SIZE;
530  alignment = sizeof(uintptr_t);
531  boundary = 0;
532  p1 = test_alloc( alloc_size, alignment, boundary, (void *) (previous_last_page_begin + sizeof(uintptr_t)));
533
534  test_heap_init( page_size );
535  boundary = ((uintptr_t) TestHeap.last_block );
536  p1 = test_alloc( alloc_size, alignment, boundary, (void *) previous_last_page_begin );
537
538  puts( "\tbreak the boundaries and aligns more than one time" );
539
540  page_size = CPU_ALIGNMENT * 20;
541  alloc_size = page_size / 4;
542  alignment = page_size / 5;
543  boundary = page_size / 4;
544  test_heap_init( page_size );
545  p1 = (void *) (_Heap_Alloc_area_of_block( TestHeap.last_block ) - page_size );
546  test_alloc( alloc_size, alignment, boundary, p1);
547
548  puts( "\tdifferent combinations, so that there is no valid block at the end" );
549
550  page_size = sizeof(uintptr_t);
551
552  test_heap_init( 0 );
553
554  /* Force the page size to a small enough value */
555  TestHeap.page_size = page_size;
556
557  alloc_size = 1;
558  alignment = (uintptr_t) TestHeap.last_block;
559  boundary = 0;
560  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
561
562  boundary = (uintptr_t) TestHeap.last_block;
563  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
564
565  alloc_size = 0;
566  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
567
568  alloc_size = 1;
569  alignment = sizeof(uintptr_t);
570  boundary = 0;
571  p1 = test_alloc_simple( alloc_size, alignment, boundary );
572
573  puts( "\ttry to create a block, which is not possible because of the alignment and boundary" );
574
575  alloc_size = 2;
576  boundary = _Heap_Alloc_area_of_block( TestHeap.first_block )
577          + _Heap_Block_size( TestHeap.first_block ) / 2;
578  alignment = boundary - 1;
579  p1 = test_init_and_alloc( alloc_size, alignment, boundary, NULL );
580
581  alloc_size = 2;
582  alignment = _Heap_Alloc_area_of_block( TestHeap.first_block );
583  boundary = alignment + 1;
584  p1 = test_init_and_alloc( alloc_size, alignment, boundary, NULL );
585}
586
587static void *test_create_used_block( void )
588{
589  uintptr_t const alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE;
590  uintptr_t const alignment = 0;
591  uintptr_t const boundary = 0;
592
593  return test_alloc_simple( alloc_size, alignment, boundary );
594}
595
596static void test_block_alloc(
597  int free_variant,
598  int alloc_variant,
599  uintptr_t alloc_begin,
600  uintptr_t alloc_size
601)
602{
603  void *p1 = NULL;
604  void *p2 = NULL;
605  void *p3 = NULL;
606
607  uintptr_t size_fresh_heap = 0;
608  uintptr_t pages_per_default_block = 0;
609  uint32_t exp_free_pages = 0;
610  uint32_t exp_free_blocks = 0;
611  uint32_t exp_used_blocks = 0;
612
613  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
614
615  size_fresh_heap = _Heap_Get_size( &TestHeap );
616  exp_free_pages = size_fresh_heap / TestHeap.page_size;
617
618  p1 = test_create_used_block();
619  p2 = test_create_used_block();
620  p3 = test_create_used_block();
621
622  pages_per_default_block = _Heap_Block_size(
623    _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size )
624  ) / TestHeap.page_size;
625
626  if (free_variant == 1) {
627    test_free( p1 );
628  } else if (free_variant == 2) {
629    test_free( p3 );
630  } else if (free_variant == 3) {
631    test_free( p2 );
632    test_free( p3 );
633  }
634
635  _Heap_Block_allocate(
636    &TestHeap,
637    _Heap_Block_of_alloc_area( (uintptr_t) p2, test_page_size()),
638    alloc_begin,
639    alloc_size
640  );
641
642  test_check_alloc_simple( (void *) alloc_begin, alloc_size, 0, 0 );
643
644  /* check statistics */
645  switch( free_variant ) {
646    case 1:
647      exp_free_pages = exp_free_pages - 2 * pages_per_default_block;
648      exp_used_blocks = 2;
649
650      switch( alloc_variant ) {
651        case 1:
652          /* allocate block full space */
653          exp_free_blocks = 2;
654          break;
655        case 2:
656          /* allocate block in the middle */
657          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
658          exp_free_blocks = 3;
659          break;
660        case 3:
661          /* allocate block at the end */
662          exp_free_pages = exp_free_pages + pages_per_default_block - 2;
663          exp_free_blocks = 2;
664          break;
665        default:
666          /* allocate block at the beginning */
667          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
668          exp_free_blocks = 3;
669          break;
670      }
671      break;
672    case 2:
673      exp_free_pages = exp_free_pages - 2 * pages_per_default_block;
674      exp_used_blocks = 2;
675
676      switch( alloc_variant ) {
677        case 1:
678          /* allocate block full space */
679          exp_free_blocks = 1;
680          break;
681        case 2:
682          /* allocate block in the middle */
683          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
684          exp_free_blocks = 2;
685          break;
686        case 3:
687          /* allocate block at the end */
688          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
689          exp_free_blocks = 2;
690          break;
691        default:
692          /* allocate block at the beginning */
693          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
694          exp_free_blocks = 1;
695          break;
696      }
697      break;
698    case 3:
699      exp_free_pages = exp_free_pages - pages_per_default_block;
700      exp_used_blocks = 2;
701
702      switch( alloc_variant ) {
703        case 1:
704          /* allocate block full space */
705          exp_free_pages = exp_free_pages - pages_per_default_block;
706          exp_free_blocks = 1;
707          break;
708        case 2:
709          /* allocate block in the middle */
710          exp_free_pages = exp_free_pages - 1;
711          exp_free_blocks = 2;
712          break;
713        case 3:
714          /* allocate block at the end */
715          exp_free_pages = exp_free_pages - 2;
716          exp_free_blocks = 2;
717          break;
718        default:
719          /* allocate block at the beginning */
720          exp_free_pages = exp_free_pages - 1;
721          exp_free_blocks = 1;
722          break;
723      }
724      break;
725    default:
726      exp_free_pages = exp_free_pages - 3 * pages_per_default_block;
727      exp_used_blocks = 3;
728
729      switch( alloc_variant ) {
730        case 1:
731          /* allocate block full space */
732          exp_free_blocks = 1;
733          break;
734        case 2:
735          /* allocate block in the middle */
736          exp_free_blocks = 3;
737          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
738          break;
739        case 3:
740          /* allocate block at the end */
741          exp_free_blocks = 2;
742          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
743          break;
744        default:
745          /* allocate block at the beginning */
746          exp_free_blocks = 2;
747          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
748      }
749  }
750
751  rtems_test_assert( TestHeap.stats.free_size == exp_free_pages * TestHeap.page_size );
752  rtems_test_assert( TestHeap.stats.free_blocks == exp_free_blocks );
753  rtems_test_assert( TestHeap.stats.used_blocks == exp_used_blocks );
754}
755
756static void test_heap_do_block_allocate( int variant, void *p2 )
757{
758  Heap_Block *const block =
759    _Heap_Block_of_alloc_area( (uintptr_t) p2, test_page_size());
760  uintptr_t const alloc_box_begin = _Heap_Alloc_area_of_block( block );
761  uintptr_t const alloc_box_size = _Heap_Block_size( block );
762  uintptr_t const alloc_box_end = alloc_box_begin + alloc_box_size;
763  uintptr_t alloc_begin = 0;
764  uintptr_t alloc_size = 0;
765
766  puts( "\tallocate block at the beginning");
767  alloc_begin = alloc_box_begin;
768  alloc_size = 0;
769  test_block_alloc( variant, 0, alloc_begin, alloc_size );
770
771  puts( "\tallocate block full space");
772  alloc_begin = alloc_box_begin;
773  alloc_size = alloc_box_size + HEAP_BLOCK_SIZE_OFFSET
774    - HEAP_BLOCK_HEADER_SIZE;
775  test_block_alloc( variant, 1, alloc_begin, alloc_size );
776
777  puts( "\tallocate block in the middle");
778  alloc_begin = alloc_box_begin + TEST_DEFAULT_PAGE_SIZE;
779  alloc_size = 0;
780  test_block_alloc( variant, 2, alloc_begin, alloc_size );
781
782  puts( "\tallocate block at the end");
783  alloc_begin = alloc_box_end - TEST_DEFAULT_PAGE_SIZE;
784  alloc_size = TEST_DEFAULT_PAGE_SIZE + HEAP_BLOCK_SIZE_OFFSET
785    - HEAP_BLOCK_HEADER_SIZE;
786  test_block_alloc( variant, 3, alloc_begin, alloc_size );
787}
788
789static void test_heap_block_allocate( void )
790{
791  void *p2 = NULL;
792
793  puts( "run tests for _Heap_Block_allocate()" );
794
795  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
796
797  test_create_used_block();
798  p2 = test_create_used_block();
799
800  test_heap_do_block_allocate( 0, p2 );
801  test_heap_do_block_allocate( 1, p2 );
802  test_heap_do_block_allocate( 2, p2 );
803  test_heap_do_block_allocate( 3, p2 );
804}
805
806static void *test_alloc_one_page(void)
807{
808  void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
809    &TestHeap,
810    1,
811    0,
812    0
813  );
814
815  test_check_alloc_simple(
816    alloc_begin_ptr,
817    1,
818    0,
819    0
820  );
821
822  rtems_test_assert( alloc_begin_ptr != NULL );
823
824  return alloc_begin_ptr;
825}
826
827static void *test_alloc_two_pages(void)
828{
829  void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
830    &TestHeap,
831    3 * TestHeap.page_size / 2,
832    0,
833    0
834  );
835
836  test_check_alloc_simple(
837    alloc_begin_ptr,
838    3 * TestHeap.page_size / 2,
839    0,
840    0
841  );
842
843  rtems_test_assert( alloc_begin_ptr != NULL );
844
845  return alloc_begin_ptr;
846}
847
848static void test_simple_resize_block(
849  void *alloc_pointer,
850  uintptr_t new_alloc_size,
851  Heap_Resize_status expected_status
852)
853{
854  uintptr_t old_size = 0;
855  uintptr_t new_size = 0;
856
857  Heap_Resize_status status = _Heap_Resize_block(
858    &TestHeap,
859    alloc_pointer,
860    new_alloc_size,
861    &old_size,
862    &new_size
863  );
864
865  rtems_test_assert( status == expected_status );
866}
867
868static void test_heap_resize_block(void)
869{
870  void *p1, *p2, *p3;
871  uintptr_t new_alloc_size = 0;
872  Heap_Block *block = NULL;
873
874  puts( "run tests for _Heap_Resize_Block()" );
875
876  puts( "\tgive a block outside the heap to the function" );
877  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
878  p1 = TestHeap.first_block - TEST_DEFAULT_PAGE_SIZE;
879  new_alloc_size = 1;
880  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_FATAL_ERROR );
881
882  puts( "\tincrease size");
883
884  puts( "\t\tlet the next block be used alredy and try to get a size bigger than the actual block" );
885  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
886  p1 = test_alloc_one_page();
887  p2 = test_alloc_one_page();
888  new_alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE / 2;
889  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_UNSATISFIED );
890
891  puts( "\t\tnext block not used and try to set the new allocation size between the page-alignments" );
892  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
893  p1 = test_alloc_one_page();
894  new_alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE / 2;
895  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
896
897  puts( "\t\tlet the block after the next be used and try to allocate more then one pagesize more" );
898  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
899  p1 = test_alloc_one_page();
900  p2 = test_alloc_one_page();
901  p3 = test_alloc_one_page();
902  _Heap_Free( &TestHeap, p2 );
903  new_alloc_size = 5 * TEST_DEFAULT_PAGE_SIZE / 2;
904  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_UNSATISFIED );
905
906  puts( "\ttry to resize to the same size" );
907  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
908  p1 = test_alloc_one_page();
909  block = _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size );
910  new_alloc_size = _Heap_Block_size( block );
911  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
912
913  puts( "\tdecrease size");
914
915  puts( "\t\tdecrease a block with two pages to one page" );
916  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
917  p1 = test_alloc_two_pages();
918  new_alloc_size = 1;
919  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
920
921  puts( "\t\tresize the block to the size 0" );
922  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
923  p1 = test_alloc_one_page();
924  new_alloc_size = 0;
925  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
926}
927
928static void test_heap_extend(void)
929{
930  bool      ret;
931
932  /*
933   * Easier to hit extend with a dedicated heap.
934   *
935   */
936  _Heap_Initialize( &TestHeap, TestHeapMemory, 512, 0 );
937
938  puts( "heap extend - bad address" );
939  ret = _Protected_heap_Extend( &TestHeap, TestHeapMemory - 512, 512 );
940  rtems_test_assert( ret == false );
941
942  puts( "heap extend - OK" );
943  ret = _Protected_heap_Extend( &TestHeap, &TestHeapMemory[ 512 ], 512 );
944  rtems_test_assert( ret == true );
945}
946
947static void test_heap_info(void)
948{
949  size_t                  s1, s2;
950  void                   *p1;
951  int                     sc;
952  Heap_Information_block  the_info;
953
954  s1 = malloc_free_space();
955  p1 = malloc( 512 );
956  s2 = malloc_free_space();
957  puts( "malloc_free_space - check malloc space drops after malloc" );
958  rtems_test_assert( s1 );
959  rtems_test_assert( s2 );
960  rtems_test_assert( s2 <= s1 );
961  free( p1 );
962
963  puts( "malloc_free_space - verify free space returns to previous value" );
964  s2 = malloc_free_space();
965  rtems_test_assert( s1 == s2 );
966
967  puts( "malloc_info - called with NULL\n" );
968  sc = malloc_info( NULL );
969  rtems_test_assert( sc == -1 );
970
971  puts( "malloc_info - check free space drops after malloc" );
972  sc = malloc_info( &the_info );
973  rtems_test_assert( sc == 0 );
974  s1 = the_info.Free.largest;
975
976  p1 = malloc( 512 );
977
978  sc = malloc_info( &the_info );
979  rtems_test_assert( sc == 0 );
980  s2 = the_info.Free.largest;
981
982  rtems_test_assert( s1 );
983  rtems_test_assert( s2 );
984  rtems_test_assert( s2 <= s1 );
985  free( p1 );
986
987  puts( "malloc_info - verify free space returns to previous value" );
988  sc = malloc_info( &the_info );
989  rtems_test_assert( sc == 0 );
990  rtems_test_assert( s1 == the_info.Free.largest );
991}
992
993static void test_protected_heap_info(void)
994{
995  Heap_Control           heap;
996  Heap_Information_block info;
997  bool                   rc;
998
999  puts( "_Protected_heap_Get_information - NULL heap" );
1000  rc = _Protected_heap_Get_information( NULL, &info );
1001  rtems_test_assert( rc == false );
1002
1003  puts( "_Protected_heap_Get_information - NULL info" );
1004  rc = _Protected_heap_Get_information( &heap, NULL );
1005  rtems_test_assert( rc == false );
1006}
1007
1008/*
1009 *  A simple test of posix_memalign
1010 */
1011static void test_posix_memalign(void)
1012{
1013  void *p1;
1014  int i;
1015  int sc;
1016  int maximumShift;
1017
1018  puts( "posix_memalign - NULL return pointer -- EINVAL" );
1019  sc = posix_memalign( NULL, 32, 8 );
1020  fatal_posix_service_status( sc, EINVAL, "posix_memalign NULL pointer" );
1021
1022  puts( "posix_memalign - alignment of 0 -- EINVAL" );
1023  sc = posix_memalign( &p1, 0, 8 );
1024  fatal_posix_service_status( sc, EINVAL, "posix_memalign alignment of 0" );
1025
1026  puts( "posix_memalign - alignment  of 2-- EINVAL" );
1027  sc = posix_memalign( &p1, 2, 8 );
1028  fatal_posix_service_status( sc, EINVAL, "posix_memalign alignment of 2" );
1029
1030  if ( sizeof(int) == 4 )
1031    maximumShift = 31;
1032  else if ( sizeof(int) == 2 )
1033    maximumShift = 15;
1034  else {
1035    printf( "Unsupported int size == %zu\n", sizeof(int) );
1036    rtems_test_exit(0);
1037  }
1038  for ( i=2 ; i<maximumShift ; i++ ) {
1039    printf( "posix_memalign - alignment of %" PRId32 " -- OK\n",
1040      (int32_t) 1 << i );
1041    sc = posix_memalign( &p1, 1 << i, 8 );
1042    if ( sc == ENOMEM ) {
1043      printf( "posix_memalign - ran out of memory trying %d\n", 1<<i );
1044      break;
1045    }
1046    posix_service_failed( sc, "posix_memalign alignment OK" );
1047
1048    free( p1 );
1049  }
1050  for ( ; i<maximumShift ; i++ ) {
1051    printf( "posix_memalign - alignment of %" PRId32 " -- SKIPPED\n",
1052      (int32_t) 1 << i );
1053  }
1054
1055}
1056
1057rtems_task Init(
1058  rtems_task_argument argument
1059)
1060{
1061  rtems_time_of_day time;
1062  rtems_status_code status;
1063
1064  puts( "\n\n*** MALLOC TEST ***" );
1065
1066  build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
1067  status = rtems_clock_set( &time );
1068  directive_failed( status, "rtems_clock_set" );
1069
1070  test_heap_initialize();
1071  test_heap_block_allocate();
1072  test_heap_allocate();
1073  test_heap_resize_block();
1074  test_realloc();
1075  test_heap_cases_1();
1076  test_heap_extend();
1077  test_heap_info();
1078  test_protected_heap_info();
1079
1080  test_posix_memalign();
1081
1082  Task_name[ 1 ] = rtems_build_name( 'T', 'A', '1', ' ' );
1083  Task_name[ 2 ] = rtems_build_name( 'T', 'A', '2', ' ' );
1084  Task_name[ 3 ] = rtems_build_name( 'T', 'A', '3', ' ' );
1085  Task_name[ 4 ] = rtems_build_name( 'T', 'A', '4', ' ' );
1086  Task_name[ 5 ] = rtems_build_name( 'T', 'A', '5', ' ' );
1087
1088  status = rtems_task_create(
1089     Task_name[ 1 ],
1090     1,
1091     TASK_STACK_SIZE,
1092     RTEMS_DEFAULT_MODES,
1093     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1094     &Task_id[ 1 ]
1095  );
1096  directive_failed( status, "rtems_task_create of TA1" );
1097
1098  status = rtems_task_create(
1099     Task_name[ 2 ],
1100     1,
1101     TASK_STACK_SIZE,
1102     RTEMS_DEFAULT_MODES,
1103     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1104     &Task_id[ 2 ]
1105  );
1106  directive_failed( status, "rtems_task_create of TA2" );
1107
1108  status = rtems_task_create(
1109     Task_name[ 3 ],
1110     1,
1111     TASK_STACK_SIZE,
1112     RTEMS_DEFAULT_MODES,
1113     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1114     &Task_id[ 3 ]
1115  );
1116  directive_failed( status, "rtems_task_create of TA3" );
1117
1118  status = rtems_task_create(
1119     Task_name[ 4 ],
1120     1,
1121     TASK_STACK_SIZE,
1122     RTEMS_DEFAULT_MODES,
1123     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1124     &Task_id[ 4 ]
1125  );
1126  directive_failed( status, "rtems_task_create of TA4" );
1127
1128  status = rtems_task_create(
1129     Task_name[ 5 ],
1130     1,
1131     TASK_STACK_SIZE,
1132     RTEMS_DEFAULT_MODES,
1133     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1134     &Task_id[ 5 ]
1135  );
1136  directive_failed( status, "rtems_task_create of TA5" );
1137
1138  status = rtems_task_start( Task_id[ 1 ], Task_1_through_5, 0 );
1139  directive_failed( status, "rtems_task_start of TA1" );
1140
1141  status = rtems_task_start( Task_id[ 2 ], Task_1_through_5, 0 );
1142  directive_failed( status, "rtems_task_start of TA2" );
1143
1144  status = rtems_task_start( Task_id[ 3 ], Task_1_through_5, 0 );
1145  directive_failed( status, "rtems_task_start of TA3" );
1146
1147  status = rtems_task_start( Task_id[ 4 ], Task_1_through_5, 0 );
1148  directive_failed( status, "rtems_task_start of TA4" );
1149
1150  status = rtems_task_start( Task_id[ 5 ], Task_1_through_5, 0 );
1151  directive_failed( status, "rtems_task_start of TA5" );
1152
1153  status = rtems_task_delete( RTEMS_SELF );
1154  directive_failed( status, "rtems_task_delete of RTEMS_SELF" );
1155}
Note: See TracBrowser for help on using the repository browser.