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

4.115
Last change on this file since ce217f96 was ce217f96, checked in by Sebastian Huber <sebastian.huber@…>, on 03/09/11 at 15:39:58

2011-03-09 Sebastian Huber <sebastian.huber@…>

  • malloctest/init.c: Improve coverage.
  • malloctest/malloctest.scn: Update.
  • Property mode set to 100644
File size: 31.9 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, 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 *  $Id$
24 */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
31#define CONFIGURE_INIT
32#include "system.h"
33
34#include <stdlib.h>
35#include <string.h>
36#include <inttypes.h>
37#include <errno.h>
38#include <rtems/score/protectedheap.h>
39
40/* HACK: Blatant visibility violations */
41extern int malloc_info(Heap_Information_block *the_info);
42extern void malloc_walk(size_t source, size_t printf_enabled);
43
44/*
45 *  A simple test of realloc
46 */
47static void test_realloc(void)
48{
49  void *p1, *p2, *p3, *p4;
50  size_t i;
51  int sc;
52
53  /* Test growing reallocation "in place" */
54  p1 = malloc(1);
55  for (i=2 ; i<2048 ; i++) {
56    p2 = realloc(p1, i);
57    if (p2 != p1)
58      printf( "realloc - failed grow in place: "
59              "%p != realloc(%p,%zu)\n", p1, p2, i);
60    p1 = p2;
61  }
62  free(p1);
63
64  /* Test shrinking reallocation "in place" */
65  p1 = malloc(2048);
66  for (i=2047 ; i>=1; i--)  {
67    p2 = realloc(p1, i);
68    if (p2 != p1)
69      printf( "realloc - failed shrink in place: "
70              "%p != realloc(%p,%zu)\n", p1, p2, i);
71    p1 = p2;
72  }
73  free(p1);
74
75  /* Test realloc that should fail "in place", i.e.,
76   * fallback to free()-- malloc()
77   */
78  p1 = malloc(32);
79  p2 = malloc(32);
80  p3 = realloc(p1, 64);
81  if (p3 == p1 || p3 == NULL)
82    printf(
83      "realloc - failed non-in place: realloc(%p,%d) = %p\n", p1, 64, p3);
84  free(p3);
85  free(p2);
86
87  /*
88   *  Yet another case
89   */
90  p1 = malloc(8);
91  p2 = malloc(8);
92  free(p1);
93  sc = posix_memalign(&p1, 16, 32);
94  if (!sc)
95    free(p1);
96
97  /*
98   *  Allocate with default alignment coverage
99   */
100  sc = rtems_memalign( &p4, 0, 8 );
101  if ( !sc && p4 )
102    free( p4 );
103
104  /*
105   * Walk the C Program Heap
106   */
107  puts( "malloc_walk - normal path" );
108  malloc_walk( 1234, 0 );
109
110  puts( "malloc_walk - in critical section path" );
111  _Thread_Disable_dispatch();
112  malloc_walk( 1234, 0 );
113  _Thread_Enable_dispatch();
114
115  /*
116   *  Realloc with a bad pointer to force a point
117   */
118  p4 = realloc( test_realloc, 32 );
119
120  p4 = _realloc_r( NULL, NULL, 1 );
121}
122
123#define TEST_HEAP_SIZE 2048
124
125uint8_t TestHeapMemory[TEST_HEAP_SIZE];
126
127Heap_Control TestHeap;
128
129static void test_heap_default_init(void)
130{
131  memset( &TestHeapMemory, 0x7f, TEST_HEAP_SIZE );
132  _Heap_Initialize( &TestHeap, TestHeapMemory, TEST_HEAP_SIZE, 0 );
133}
134
135static void test_free( void *addr )
136{
137  rtems_test_assert( _Heap_Free( &TestHeap, addr ) );
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 first_block_begin = 0;
424
425  uintptr_t last_block_begin = 0;
426  uintptr_t last_alloc_begin = 0;
427
428  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
429
430  first_block_begin = (uintptr_t) TestHeap.first_block;
431
432  last_block_begin = (uintptr_t) TestHeap.last_block;
433  last_alloc_begin = _Heap_Alloc_area_of_block( TestHeap.last_block );
434
435  puts( "run tests for _Heap_Allocate_aligned_with_boundary()");
436
437  puts( "\tcheck if NULL will be returned if size causes integer overflow" );
438
439  alloc_size = (uintptr_t ) -1;
440  alignment = 0;
441  boundary = 0;
442  test_init_and_alloc( alloc_size, alignment, boundary, NULL );
443
444  puts( "\ttry to allocate more space than the one which fits in the boundary" );
445
446  alloc_size = 2;
447  alignment = 0;
448  boundary = alloc_size - 1;
449  test_init_and_alloc( alloc_size, alignment, boundary, NULL );
450
451  puts( "\tcheck if alignment will be set to page size if only a boundary is given" );
452
453  alloc_size = 1;
454  boundary = 1;
455
456  alignment = 0;
457  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
458
459  alignment = test_page_size();
460  test_init_and_alloc( alloc_size, alignment, boundary, p1 );
461
462  puts( "\tcreate a block which is bigger then the first free space" );
463
464  alignment = 0;
465  boundary = 0;
466
467  alloc_size = test_page_size();
468  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
469  p2 = test_alloc_simple( alloc_size, alignment, boundary );
470  test_free( p1 );
471
472  alloc_size = 2 * alloc_size;
473  p3 = test_alloc_simple( alloc_size, alignment, boundary );
474  rtems_test_assert( p1 != p3 );
475
476  puts( "\tset boundary before allocation begin" );
477
478  alloc_size = 1;
479  alignment = 0;
480  boundary = last_alloc_begin - test_page_size();
481  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
482  rtems_test_assert( (uintptr_t ) p1 >= boundary );
483
484  puts( "\tset boundary between allocation begin and end" );
485  alloc_size = test_page_size();
486  alignment = 0;
487  boundary = last_alloc_begin - alloc_size / 2;
488  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
489  rtems_test_assert( (uintptr_t ) p1 + alloc_size <= boundary );
490
491  puts( "\tset boundary after allocation end" );
492  alloc_size = 1;
493  alignment = 0;
494  boundary = last_alloc_begin;
495  p1 = test_init_and_alloc_simple( alloc_size, alignment, boundary );
496  rtems_test_assert( (uintptr_t ) p1 + alloc_size < boundary );
497
498  puts( "\tset boundary on allocation end" );
499  alloc_size = TEST_DEFAULT_PAGE_SIZE - HEAP_BLOCK_HEADER_SIZE;
500  alignment = 0;
501  boundary = last_block_begin;
502  p1 = (void *) (last_alloc_begin - TEST_DEFAULT_PAGE_SIZE);
503  test_init_and_alloc( alloc_size, alignment, boundary, p1);
504
505  puts( "\talign the allocation to different positions in the block header" );
506
507  page_size = sizeof(uintptr_t);
508  alloc_size = 1;
509  boundary = 0;
510
511  test_heap_init( page_size );
512
513  /* Force the page size to a small enough value */
514  TestHeap.page_size = page_size;
515
516  alignment = first_page_begin - sizeof(uintptr_t);
517  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
518
519  first_page_begin = ((uintptr_t) TestHeap.first_block ) + HEAP_BLOCK_HEADER_SIZE;
520  alignment = first_page_begin + sizeof(uintptr_t);
521  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
522
523  first_page_begin = ((uintptr_t) TestHeap.first_block )
524          + HEAP_BLOCK_HEADER_SIZE;
525  alignment = first_page_begin;
526  p1 = test_alloc_simple( alloc_size, alignment, boundary );
527
528  puts( "\tallocate last block with different boundarys" );
529  page_size = TEST_DEFAULT_PAGE_SIZE;
530  test_heap_init( page_size );
531  previous_last_block_begin = ((uintptr_t) TestHeap.last_block )
532          - TestHeap.min_block_size;
533  previous_last_page_begin = previous_last_block_begin
534          + HEAP_BLOCK_HEADER_SIZE;
535  alloc_size = TestHeap.page_size - HEAP_BLOCK_HEADER_SIZE;
536  alignment = sizeof(uintptr_t);
537  boundary = 0;
538  p1 = test_alloc( alloc_size, alignment, boundary, (void *) (previous_last_page_begin + sizeof(uintptr_t)));
539
540  test_heap_init( page_size );
541  boundary = ((uintptr_t) TestHeap.last_block );
542  p1 = test_alloc( alloc_size, alignment, boundary, (void *) previous_last_page_begin );
543
544  puts( "\tbreak the boundaries and aligns more than one time" );
545
546  page_size = CPU_ALIGNMENT * 20;
547  alloc_size = page_size / 4;
548  alignment = page_size / 5;
549  boundary = page_size / 4;
550  test_heap_init( page_size );
551  p1 = (void *) (_Heap_Alloc_area_of_block( TestHeap.last_block ) - page_size );
552  test_alloc( alloc_size, alignment, boundary, p1);
553
554  puts( "\tdifferent combinations, so that there is no valid block at the end" );
555
556  page_size = sizeof(uintptr_t);
557
558  test_heap_init( 0 );
559
560  /* Force the page size to a small enough value */
561  TestHeap.page_size = page_size;
562
563  alloc_size = 1;
564  alignment = (uintptr_t) TestHeap.last_block;
565  boundary = 0;
566  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
567
568  boundary = (uintptr_t) TestHeap.last_block;
569  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
570
571  alloc_size = 0;
572  p1 = test_alloc( alloc_size, alignment, boundary, NULL );
573
574  alloc_size = 1;
575  alignment = sizeof(uintptr_t);
576  boundary = 0;
577  p1 = test_alloc_simple( alloc_size, alignment, boundary );
578
579  puts( "\ttry to create a block, which is not possible because of the alignment and boundary" );
580
581  alloc_size = 2;
582  boundary = _Heap_Alloc_area_of_block( TestHeap.first_block )
583          + _Heap_Block_size( TestHeap.first_block ) / 2;
584  alignment = boundary - 1;
585  p1 = test_init_and_alloc( alloc_size, alignment, boundary, NULL );
586
587  alloc_size = 2;
588  alignment = _Heap_Alloc_area_of_block( TestHeap.first_block );
589  boundary = alignment + 1;
590  p1 = test_init_and_alloc( alloc_size, alignment, boundary, NULL );
591}
592
593static void *test_create_used_block( void )
594{
595  uintptr_t const alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE;
596  uintptr_t const alignment = 0;
597  uintptr_t const boundary = 0;
598
599  return test_alloc_simple( alloc_size, alignment, boundary );
600}
601
602static void test_block_alloc(
603  int free_variant,
604  int alloc_variant,
605  uintptr_t alloc_begin,
606  uintptr_t alloc_size
607)
608{
609  void *p1 = NULL;
610  void *p2 = NULL;
611  void *p3 = NULL;
612
613  uintptr_t size_fresh_heap = 0;
614  uintptr_t pages_per_default_block = 0;
615  uint32_t exp_free_pages = 0;
616  uint32_t exp_free_blocks = 0;
617  uint32_t exp_used_blocks = 0;
618
619  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
620
621  size_fresh_heap = _Heap_Get_size( &TestHeap );
622  exp_free_pages = size_fresh_heap / TestHeap.page_size;
623
624  p1 = test_create_used_block();
625  p2 = test_create_used_block();
626  p3 = test_create_used_block();
627
628  pages_per_default_block = _Heap_Block_size(
629    _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size )
630  ) / TestHeap.page_size;
631
632  if (free_variant == 1) {
633    test_free( p1 );
634  } else if (free_variant == 2) {
635    test_free( p3 );
636  } else if (free_variant == 3) {
637    test_free( p2 );
638    test_free( p3 );
639  }
640
641  _Heap_Block_allocate(
642    &TestHeap,
643    _Heap_Block_of_alloc_area( (uintptr_t) p2, test_page_size()),
644    alloc_begin,
645    alloc_size
646  );
647
648  test_check_alloc_simple( (void *) alloc_begin, alloc_size, 0, 0 );
649
650  /* check statistics */
651  switch( free_variant ) {
652    case 1:
653      exp_free_pages = exp_free_pages - 2 * pages_per_default_block;
654      exp_used_blocks = 2;
655
656      switch( alloc_variant ) {
657        case 1:
658          /* allocate block full space */
659          exp_free_blocks = 2;
660          break;
661        case 2:
662          /* allocate block in the middle */
663          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
664          exp_free_blocks = 3;
665          break;
666        case 3:
667          /* allocate block at the end */
668          exp_free_pages = exp_free_pages + pages_per_default_block - 2;
669          exp_free_blocks = 2;
670          break;
671        default:
672          /* allocate block at the beginning */
673          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
674          exp_free_blocks = 3;
675          break;
676      }
677      break;
678    case 2:
679      exp_free_pages = exp_free_pages - 2 * pages_per_default_block;
680      exp_used_blocks = 2;
681
682      switch( alloc_variant ) {
683        case 1:
684          /* allocate block full space */
685          exp_free_blocks = 1;
686          break;
687        case 2:
688          /* allocate block in the middle */
689          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
690          exp_free_blocks = 2;
691          break;
692        case 3:
693          /* allocate block at the end */
694          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
695          exp_free_blocks = 2;
696          break;
697        default:
698          /* allocate block at the beginning */
699          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
700          exp_free_blocks = 1;
701          break;
702      }
703      break;
704    case 3:
705      exp_free_pages = exp_free_pages - pages_per_default_block;
706      exp_used_blocks = 2;
707
708      switch( alloc_variant ) {
709        case 1:
710          /* allocate block full space */
711          exp_free_pages = exp_free_pages - pages_per_default_block;
712          exp_free_blocks = 1;
713          break;
714        case 2:
715          /* allocate block in the middle */
716          exp_free_pages = exp_free_pages - 1;
717          exp_free_blocks = 2;
718          break;
719        case 3:
720          /* allocate block at the end */
721          exp_free_pages = exp_free_pages - 2;
722          exp_free_blocks = 2;
723          break;
724        default:
725          /* allocate block at the beginning */
726          exp_free_pages = exp_free_pages - 1;
727          exp_free_blocks = 1;
728          break;
729      }
730      break;
731    default:
732      exp_free_pages = exp_free_pages - 3 * pages_per_default_block;
733      exp_used_blocks = 3;
734
735      switch( alloc_variant ) {
736        case 1:
737          /* allocate block full space */
738          exp_free_blocks = 1;
739          break;
740        case 2:
741          /* allocate block in the middle */
742          exp_free_blocks = 3;
743          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
744          break;
745        case 3:
746          /* allocate block at the end */
747          exp_free_blocks = 2;
748          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
749          break;
750        default:
751          /* allocate block at the beginning */
752          exp_free_blocks = 2;
753          exp_free_pages = exp_free_pages + pages_per_default_block - 1;
754      }
755  }
756
757  rtems_test_assert( TestHeap.stats.free_size == exp_free_pages * TestHeap.page_size );
758  rtems_test_assert( TestHeap.stats.free_blocks == exp_free_blocks );
759  rtems_test_assert( TestHeap.stats.used_blocks == exp_used_blocks );
760}
761
762static void test_heap_do_block_allocate( int variant, void *p2 )
763{
764  Heap_Block *const block =
765    _Heap_Block_of_alloc_area( (uintptr_t) p2, test_page_size());
766  uintptr_t const alloc_box_begin = _Heap_Alloc_area_of_block( block );
767  uintptr_t const alloc_box_size = _Heap_Block_size( block );
768  uintptr_t const alloc_box_end = alloc_box_begin + alloc_box_size;
769  uintptr_t alloc_begin = 0;
770  uintptr_t alloc_size = 0;
771
772  puts( "\tallocate block at the beginning");
773  alloc_begin = alloc_box_begin;
774  alloc_size = 0;
775  test_block_alloc( variant, 0, alloc_begin, alloc_size );
776
777  puts( "\tallocate block full space");
778  alloc_begin = alloc_box_begin;
779  alloc_size = alloc_box_size + HEAP_ALLOC_BONUS
780    - HEAP_BLOCK_HEADER_SIZE;
781  test_block_alloc( variant, 1, alloc_begin, alloc_size );
782
783  puts( "\tallocate block in the middle");
784  alloc_begin = alloc_box_begin + TEST_DEFAULT_PAGE_SIZE;
785  alloc_size = 0;
786  test_block_alloc( variant, 2, alloc_begin, alloc_size );
787
788  puts( "\tallocate block at the end");
789  alloc_begin = alloc_box_end - TEST_DEFAULT_PAGE_SIZE;
790  alloc_size = TEST_DEFAULT_PAGE_SIZE + HEAP_ALLOC_BONUS
791    - HEAP_BLOCK_HEADER_SIZE;
792  test_block_alloc( variant, 3, alloc_begin, alloc_size );
793}
794
795static void test_heap_block_allocate( void )
796{
797  void *p2 = NULL;
798
799  puts( "run tests for _Heap_Block_allocate()" );
800
801  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
802
803  test_create_used_block();
804  p2 = test_create_used_block();
805
806  test_heap_do_block_allocate( 0, p2 );
807  test_heap_do_block_allocate( 1, p2 );
808  test_heap_do_block_allocate( 2, p2 );
809  test_heap_do_block_allocate( 3, p2 );
810}
811
812static void *test_alloc_one_page(void)
813{
814  void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
815    &TestHeap,
816    1,
817    0,
818    0
819  );
820
821  test_check_alloc_simple(
822    alloc_begin_ptr,
823    1,
824    0,
825    0
826  );
827
828  rtems_test_assert( alloc_begin_ptr != NULL );
829
830  return alloc_begin_ptr;
831}
832
833static void *test_alloc_two_pages(void)
834{
835  void *alloc_begin_ptr = _Heap_Allocate_aligned_with_boundary(
836    &TestHeap,
837    3 * TestHeap.page_size / 2,
838    0,
839    0
840  );
841
842  test_check_alloc_simple(
843    alloc_begin_ptr,
844    3 * TestHeap.page_size / 2,
845    0,
846    0
847  );
848
849  rtems_test_assert( alloc_begin_ptr != NULL );
850
851  return alloc_begin_ptr;
852}
853
854static void test_simple_resize_block(
855  void *alloc_pointer,
856  uintptr_t new_alloc_size,
857  Heap_Resize_status expected_status
858)
859{
860  uintptr_t old_size = 0;
861  uintptr_t new_size = 0;
862
863  Heap_Resize_status status = _Heap_Resize_block(
864    &TestHeap,
865    alloc_pointer,
866    new_alloc_size,
867    &old_size,
868    &new_size
869  );
870
871  rtems_test_assert( status == expected_status );
872}
873
874static void test_heap_resize_block(void)
875{
876  void *p1, *p2, *p3;
877  uintptr_t new_alloc_size = 0;
878  Heap_Block *block = NULL;
879
880  puts( "run tests for _Heap_Resize_Block()" );
881
882  puts( "\tgive a block outside the heap to the function" );
883  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
884  p1 = TestHeap.first_block - TEST_DEFAULT_PAGE_SIZE;
885  new_alloc_size = 1;
886  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_FATAL_ERROR );
887
888  puts( "\tincrease size");
889
890  puts( "\t\tlet the next block be used alredy and try to get a size bigger than the actual block" );
891  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
892  p1 = test_alloc_one_page();
893  p2 = 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_UNSATISFIED );
896
897  puts( "\t\tnext block not used and try to set the new allocation size between the page-alignments" );
898  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
899  p1 = test_alloc_one_page();
900  new_alloc_size = 3 * TEST_DEFAULT_PAGE_SIZE / 2;
901  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
902
903  puts( "\t\tlet the block after the next be used and try to allocate more then one pagesize more" );
904  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
905  p1 = test_alloc_one_page();
906  p2 = test_alloc_one_page();
907  p3 = test_alloc_one_page();
908  _Heap_Free( &TestHeap, p2 );
909  new_alloc_size = 5 * TEST_DEFAULT_PAGE_SIZE / 2;
910  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_UNSATISFIED );
911
912  puts( "\ttry to resize to the same size" );
913  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
914  p1 = test_alloc_one_page();
915  block = _Heap_Block_of_alloc_area( (uintptr_t) p1, TestHeap.page_size );
916  new_alloc_size = _Heap_Block_size( block );
917  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
918
919  puts( "\tdecrease size");
920
921  puts( "\t\tdecrease a block with two pages to one page" );
922  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
923  p1 = test_alloc_two_pages();
924  new_alloc_size = 1;
925  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
926
927  puts( "\t\tresize the block to the size 0" );
928  test_heap_init( TEST_DEFAULT_PAGE_SIZE );
929  p1 = test_alloc_one_page();
930  new_alloc_size = 0;
931  test_simple_resize_block( p1, new_alloc_size, HEAP_RESIZE_SUCCESSFUL );
932}
933
934static void test_heap_assert(bool ret, bool expected)
935{
936  rtems_test_assert( ret == expected );
937  rtems_test_assert( _Heap_Walk( &TestHeap, 0, false ) );
938}
939
940static void test_heap_extend(void)
941{
942  bool ret = false;
943  Heap_Control *heap = &TestHeap;
944  uint8_t *area_begin = TestHeapMemory;
945
946  _Heap_Initialize( heap, area_begin + 768, 256, 0 );
947
948  puts( "heap extend - link below" );
949  ret = _Protected_heap_Extend( heap, area_begin + 0, 256 );
950  test_heap_assert( ret, true );
951
952  puts( "heap extend - merge below" );
953  ret = _Protected_heap_Extend( heap, area_begin + 512, 256 );
954  test_heap_assert( ret, true );
955
956  puts( "heap extend - merge above" );
957  ret = _Protected_heap_Extend( heap, area_begin + 1024, 256 );
958  test_heap_assert( ret, true );
959
960  puts( "heap extend - link above" );
961  ret = _Protected_heap_Extend( heap, area_begin + 1536, 256 );
962  test_heap_assert( ret, true );
963
964  puts( "heap extend - area too small" );
965  ret = _Protected_heap_Extend( heap, area_begin + 2048, 0 );
966  test_heap_assert( ret, false );
967
968  puts( "heap extend - invalid area" );
969  ret = _Protected_heap_Extend( heap, (void *) -1, 2 );
970  test_heap_assert( ret, false );
971
972  area_begin = (uint8_t *) (((uintptr_t) area_begin) | 1);
973
974  _Heap_Initialize( heap, area_begin + 768, 256, 0 );
975
976  puts( "heap extend - merge below with align up" );
977  ret = _Protected_heap_Extend( heap, area_begin + 512, 256 );
978  test_heap_assert( ret, true );
979}
980
981static void test_heap_info(void)
982{
983  size_t                  s1, s2;
984  void                   *p1;
985  int                     sc;
986  Heap_Information_block  the_info;
987
988  s1 = malloc_free_space();
989  p1 = malloc( 512 );
990  s2 = malloc_free_space();
991  puts( "malloc_free_space - check malloc space drops after malloc" );
992  rtems_test_assert( s1 );
993  rtems_test_assert( s2 );
994  rtems_test_assert( s2 <= s1 );
995  free( p1 );
996
997  puts( "malloc_free_space - verify free space returns to previous value" );
998  s2 = malloc_free_space();
999  rtems_test_assert( s1 == s2 );
1000
1001  puts( "malloc_info - called with NULL\n" );
1002  sc = malloc_info( NULL );
1003  rtems_test_assert( sc == -1 );
1004
1005  puts( "malloc_info - check free space drops after malloc" );
1006  sc = malloc_info( &the_info );
1007  rtems_test_assert( sc == 0 );
1008  s1 = the_info.Free.largest;
1009
1010  p1 = malloc( 512 );
1011
1012  sc = malloc_info( &the_info );
1013  rtems_test_assert( sc == 0 );
1014  s2 = the_info.Free.largest;
1015
1016  rtems_test_assert( s1 );
1017  rtems_test_assert( s2 );
1018  rtems_test_assert( s2 <= s1 );
1019  free( p1 );
1020
1021  puts( "malloc_info - verify free space returns to previous value" );
1022  sc = malloc_info( &the_info );
1023  rtems_test_assert( sc == 0 );
1024  rtems_test_assert( s1 == the_info.Free.largest );
1025}
1026
1027static void test_protected_heap_info(void)
1028{
1029  Heap_Control           heap;
1030  Heap_Information_block info;
1031  bool                   rc;
1032
1033  puts( "_Protected_heap_Get_information - NULL heap" );
1034  rc = _Protected_heap_Get_information( NULL, &info );
1035  rtems_test_assert( rc == false );
1036
1037  puts( "_Protected_heap_Get_information - NULL info" );
1038  rc = _Protected_heap_Get_information( &heap, NULL );
1039  rtems_test_assert( rc == false );
1040}
1041
1042static void test_rtems_heap_allocate_aligned_with_boundary(void)
1043{
1044  void *p = NULL;
1045
1046  p = rtems_heap_allocate_aligned_with_boundary(1, 1, 1);
1047  rtems_test_assert( p != NULL );
1048  free(p);
1049
1050  _Thread_Disable_dispatch();
1051  p = rtems_heap_allocate_aligned_with_boundary(1, 1, 1);
1052  _Thread_Enable_dispatch();
1053  rtems_test_assert( p == NULL );
1054}
1055
1056/*
1057 *  A simple test of posix_memalign
1058 */
1059static void test_posix_memalign(void)
1060{
1061  void *p1;
1062  int i;
1063  int sc;
1064  int maximumShift;
1065
1066  puts( "posix_memalign - NULL return pointer -- EINVAL" );
1067  sc = posix_memalign( NULL, 32, 8 );
1068  fatal_posix_service_status( sc, EINVAL, "posix_memalign NULL pointer" );
1069
1070  puts( "posix_memalign - alignment of 0 -- EINVAL" );
1071  sc = posix_memalign( &p1, 0, 8 );
1072  fatal_posix_service_status( sc, EINVAL, "posix_memalign alignment of 0" );
1073
1074  puts( "posix_memalign - alignment  of 2-- EINVAL" );
1075  sc = posix_memalign( &p1, 2, 8 );
1076  fatal_posix_service_status( sc, EINVAL, "posix_memalign alignment of 2" );
1077
1078  maximumShift = (sizeof(size_t) * CHAR_BIT) - 1;
1079  for ( i=sizeof(void *) ; i<maximumShift ; i++ ) {
1080    size_t alignment = 1 << i;
1081    printf( "posix_memalign - alignment of %zd -- OK\n", alignment);
1082    sc = posix_memalign( &p1, alignment, 8 );
1083    if ( sc == ENOMEM ) {
1084      printf( "posix_memalign - ran out of memory trying %zd\n", alignment );
1085      break;
1086    }
1087    posix_service_failed( sc, "posix_memalign alignment OK" );
1088
1089    free( p1 );
1090  }
1091  for ( ; i<maximumShift ; i++ ) {
1092    size_t alignment = 1 << i;
1093    printf( "posix_memalign - alignment of %zd -- SKIPPED\n", alignment);
1094  }
1095
1096}
1097
1098rtems_task Init(
1099  rtems_task_argument argument
1100)
1101{
1102  void             *p1;
1103  rtems_time_of_day time;
1104  rtems_status_code status;
1105
1106  puts( "\n\n*** MALLOC TEST ***" );
1107
1108  build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
1109  status = rtems_clock_set( &time );
1110  directive_failed( status, "rtems_clock_set" );
1111
1112  /*
1113   * Verify case where block is too large to calloc.
1114   */
1115  p1 = calloc( 1, SIZE_MAX );
1116  if (p1) {
1117    printf("ERROR on attempt to calloc SIZE_MAX block expected failure.");
1118    free( p1 );
1119  }
1120
1121  /*
1122   * Verify error case where malloc of size 0.
1123   */
1124  p1 = malloc( 0 );
1125  if (p1) {
1126    printf("ERROR on attempt to malloc size 0 block expected failure.");
1127    free( p1 );
1128  }
1129
1130
1131
1132  test_heap_initialize();
1133  test_heap_block_allocate();
1134  test_heap_allocate();
1135  test_heap_resize_block();
1136  test_realloc();
1137  test_heap_cases_1();
1138  test_heap_extend();
1139  test_heap_info();
1140  test_protected_heap_info();
1141  test_rtems_heap_allocate_aligned_with_boundary();
1142
1143  test_posix_memalign();
1144
1145  Task_name[ 1 ] = rtems_build_name( 'T', 'A', '1', ' ' );
1146  Task_name[ 2 ] = rtems_build_name( 'T', 'A', '2', ' ' );
1147  Task_name[ 3 ] = rtems_build_name( 'T', 'A', '3', ' ' );
1148  Task_name[ 4 ] = rtems_build_name( 'T', 'A', '4', ' ' );
1149  Task_name[ 5 ] = rtems_build_name( 'T', 'A', '5', ' ' );
1150
1151  status = rtems_task_create(
1152     Task_name[ 1 ],
1153     1,
1154     TASK_STACK_SIZE,
1155     RTEMS_DEFAULT_MODES,
1156     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1157     &Task_id[ 1 ]
1158  );
1159  directive_failed( status, "rtems_task_create of TA1" );
1160
1161  status = rtems_task_create(
1162     Task_name[ 2 ],
1163     1,
1164     TASK_STACK_SIZE,
1165     RTEMS_DEFAULT_MODES,
1166     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1167     &Task_id[ 2 ]
1168  );
1169  directive_failed( status, "rtems_task_create of TA2" );
1170
1171  status = rtems_task_create(
1172     Task_name[ 3 ],
1173     1,
1174     TASK_STACK_SIZE,
1175     RTEMS_DEFAULT_MODES,
1176     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1177     &Task_id[ 3 ]
1178  );
1179  directive_failed( status, "rtems_task_create of TA3" );
1180
1181  status = rtems_task_create(
1182     Task_name[ 4 ],
1183     1,
1184     TASK_STACK_SIZE,
1185     RTEMS_DEFAULT_MODES,
1186     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1187     &Task_id[ 4 ]
1188  );
1189  directive_failed( status, "rtems_task_create of TA4" );
1190
1191  status = rtems_task_create(
1192     Task_name[ 5 ],
1193     1,
1194     TASK_STACK_SIZE,
1195     RTEMS_DEFAULT_MODES,
1196     RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT,
1197     &Task_id[ 5 ]
1198  );
1199  directive_failed( status, "rtems_task_create of TA5" );
1200
1201  status = rtems_task_start( Task_id[ 1 ], Task_1_through_5, 0 );
1202  directive_failed( status, "rtems_task_start of TA1" );
1203
1204  status = rtems_task_start( Task_id[ 2 ], Task_1_through_5, 0 );
1205  directive_failed( status, "rtems_task_start of TA2" );
1206
1207  status = rtems_task_start( Task_id[ 3 ], Task_1_through_5, 0 );
1208  directive_failed( status, "rtems_task_start of TA3" );
1209
1210  status = rtems_task_start( Task_id[ 4 ], Task_1_through_5, 0 );
1211  directive_failed( status, "rtems_task_start of TA4" );
1212
1213  status = rtems_task_start( Task_id[ 5 ], Task_1_through_5, 0 );
1214  directive_failed( status, "rtems_task_start of TA5" );
1215
1216  status = rtems_task_delete( RTEMS_SELF );
1217  directive_failed( status, "rtems_task_delete of RTEMS_SELF" );
1218}
Note: See TracBrowser for help on using the repository browser.