summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport/src/malloc_sbrk_helpers.c
blob: bbc6faf5196054cb0e2d7a7d5442a338d741f851 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 *  RTEMS Malloc -- SBRK Support Plugin
 *
 *  COPYRIGHT (c) 1989-2007.
 *  On-Line Applications Research Corporation (OAR).
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.com/license/LICENSE.
 *
 *  $Id$
 */

#if HAVE_CONFIG_H
#include "config.h"
#endif

#include <rtems.h>
#include <rtems/malloc.h>
#include "malloc_p.h"

#include <errno.h>

size_t  RTEMS_Malloc_Sbrk_amount;

void *malloc_sbrk_initialize(
  void  *starting_address,
  size_t length
)
{
  uintptr_t     old_address;
  uintptr_t     uaddress;

  RTEMS_Malloc_Sbrk_amount = length;

  /*
   * If the starting address is 0 then we are to attempt to
   * get length worth of memory using sbrk. Make sure we
   * align the address that we get back.
   */

  if (!starting_address) {
    uaddress = (uintptr_t)sbrk(length);

    if (uaddress == (uintptr_t) -1) {
      rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
      /* DOES NOT RETURN!!! */
    }

    if (uaddress & (CPU_HEAP_ALIGNMENT-1)) {
      old_address = uaddress;
      uaddress = (uaddress + CPU_HEAP_ALIGNMENT) & ~(CPU_HEAP_ALIGNMENT-1);

      /*
       * adjust the length by whatever we aligned by
       */
      length -= uaddress - old_address;
    }

    starting_address = (void *)uaddress;
  }
  return starting_address;
}

void *malloc_sbrk_extend_and_allocate(
  size_t size
)
{
  uint32_t  sbrk_amount;
  void     *starting_address;
  uint32_t  the_size;
  void     *return_this;

  /*
   *  Round to the "requested sbrk amount" so hopefully we won't have
   *  to grow again for a while.  This effectively does sbrk() calls
   *  in "page" amounts.
   */

  sbrk_amount = RTEMS_Malloc_Sbrk_amount;

  if ( sbrk_amount == 0 )
    return (void *) 0;

  the_size = ((size + sbrk_amount) / sbrk_amount * sbrk_amount);

  starting_address = (void *) sbrk(the_size);
  if ( starting_address == (void*) -1 )
    return (void *) 0;

  if ( !_Protected_heap_Extend(
          &RTEMS_Malloc_Heap, starting_address, the_size) ) {
    sbrk(-the_size);
    errno = ENOMEM;
    return (void *) 0;
  }

  MSBUMP(space_available, the_size);

  return_this = _Protected_heap_Allocate( &RTEMS_Malloc_Heap, size );
  return return_this;
}


rtems_malloc_sbrk_functions_t rtems_malloc_sbrk_helpers_table = {
  malloc_sbrk_initialize,
  malloc_sbrk_extend_and_allocate
};