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

4.115
Last change on this file since 6f27ba8 was 6f27ba8, checked in by Joel Sherrill <joel.sherrill@…>, on 05/05/11 at 16:45:47

2011-05-05 Joel Sherrill <joel.sherrill@…>

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