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

4.115
Last change on this file since 50262970 was 50262970, checked in by Sebastian Huber <sebastian.huber@…>, on 05/16/12 at 10:09:56

libcsupport: Adjust malloc_walk() prototype

The header file <rtems/malloc.h> provides now also the malloc_walk()
prototype.

The malloc_walk() prototype reflects now the _Protected_heap_Walk() API.
The return status helps to print only in case of an error.

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