source: rtems/cpukit/libcsupport/src/malloc.c @ ac7d5ef0

4.104.114.84.95
Last change on this file since ac7d5ef0 was ac7d5ef0, checked in by Joel Sherrill <joel.sherrill@…>, on May 11, 1995 at 5:39:37 PM

Initial revision

  • Property mode set to 100644
File size: 5.4 KB
Line 
1/*
2 *  RTEMS Malloc Family Implementation
3 *
4 *
5 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
6 *  On-Line Applications Research Corporation (OAR).
7 *  All rights assigned to U.S. Government, 1994.
8 *
9 *  This material may be reproduced by or for the U.S. Government pursuant
10 *  to the copyright license under the clause at DFARS 252.227-7013.  This
11 *  notice must appear in all copies of this file and its derivatives.
12 *
13 *  $Id$
14 */
15
16#include <rtems.h>
17#ifdef RTEMS_LIBC
18#include <memory.h>
19#endif
20#include "libcsupport.h"
21#ifdef RTEMS_NEWLIB
22#include <sys/reent.h>
23#endif
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <sys/types.h>
28#include <assert.h>
29#include <errno.h>
30#include <string.h>
31
32/*
33 *  XXX: Do we really need to duplicate these? It appears that they
34 *       only cause typing problems.
35 */
36
37#if 0
38void *malloc(size_t);
39void *calloc(size_t, size_t);
40void *realloc(void *, size_t);
41void free(void *);
42void *sbrk(size_t);
43#endif
44
45rtems_id RTEMS_Malloc_Heap;
46size_t RTEMS_Malloc_Sbrk_amount;
47
48void RTEMS_Malloc_Initialize(
49  void   *start,
50  size_t  length,
51  size_t  sbrk_amount
52)
53{
54  rtems_status_code   status;
55  void               *starting_address;
56  rtems_unsigned32    u32_address;
57
58  /*
59   * If the starting address is 0 then we are to attempt to
60   * get length worth of memory using sbrk. Make sure we
61   * align the address that we get back.
62   */
63
64  starting_address = start;
65
66  if (!starting_address) {
67    u32_address = (unsigned int)sbrk(length);
68
69    if (u32_address == -1) {
70      rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
71      /* DOES NOT RETURN!!! */
72    }
73
74    if (u32_address & (CPU_ALIGNMENT-1)) {
75      u32_address = (u32_address + CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1);
76      /* XXX: if we do any alignment .. then length should be shortened */
77    }
78
79    starting_address = (void *)u32_address;
80  }
81
82  /*
83   *  Unfortunately we cannot use assert if this fails because if this
84   *  has failed we do not have a heap and if we do not have a heap
85   *  STDIO cannot work because there will be no buffers.
86   */
87
88  status = rtems_region_create(
89    rtems_build_name( 'H', 'E', 'A', 'P' ),
90    starting_address,
91    length,
92    8,                     /* XXX : use CPU dependent RTEMS constant */
93    RTEMS_DEFAULT_ATTRIBUTES,
94    &RTEMS_Malloc_Heap
95  );
96  if ( status != RTEMS_SUCCESSFUL )
97    rtems_fatal_error_occurred( status );
98}
99
100void *malloc(
101  size_t  size
102)
103{
104  void              *return_this;
105  void              *starting_address;
106  rtems_unsigned32   the_size;
107  rtems_unsigned32   sbrk_amount;
108  rtems_status_code  status;
109
110  if ( !size )
111    return (void *) 0;
112
113  /*
114   * Try to give a segment in the current region if there is not
115   * enough space then try to grow the region using rtems_region_extend().
116   * If this fails then return a NULL pointer.
117   */
118
119  status = rtems_region_get_segment(
120    RTEMS_Malloc_Heap,
121    size,
122    RTEMS_NO_WAIT,
123    RTEMS_NO_TIMEOUT,
124    &return_this
125  );
126
127  if ( status != RTEMS_SUCCESSFUL ) {
128    /*
129     *  Round to the "requested sbrk amount" so hopefully we won't have
130     *  to grow again for a while.  This effectively does sbrk() calls
131     *  in "page" amounts.
132     */
133
134    sbrk_amount = RTEMS_Malloc_Sbrk_amount;
135
136    if ( sbrk_amount == 0 )
137      return (void *) 0;
138
139    the_size = ((size + sbrk_amount) / sbrk_amount * sbrk_amount);
140
141    if (((rtems_unsigned32)starting_address = sbrk(the_size)) == -1)
142      return (void *) 0;
143
144    /*
145    fprintf(stderr, "Extended the C heap starting at 0x%x for %d bytes\n",
146        (unsigned32)starting_address, the_size);
147     */
148
149    status = rtems_region_extend(
150      RTEMS_Malloc_Heap,
151      starting_address,
152      the_size
153    );
154    if ( status != RTEMS_SUCCESSFUL ) {
155      sbrk(-the_size);
156      return(FALSE);
157      errno = ENOMEM;
158      return (void *) 0;
159    }
160    status = rtems_region_get_segment(
161      RTEMS_Malloc_Heap,
162       size,
163       RTEMS_NO_WAIT,
164       RTEMS_NO_TIMEOUT,
165       &return_this
166    );
167    if ( status != RTEMS_SUCCESSFUL ) {
168      errno = ENOMEM;
169      return (void *) 0;
170    }
171  }
172
173  return return_this;
174}
175
176void *calloc(
177  size_t nelem,
178  size_t elsize
179)
180{
181  register char *cptr;
182  int length;
183
184  length = nelem * elsize;
185  cptr = malloc( length );
186  if ( cptr )
187    memset( cptr, '\0', length );
188
189  return cptr;
190}
191
192void *realloc(
193  void *ptr,
194  size_t size
195)
196{
197  rtems_unsigned32  old_size;
198  rtems_status_code status;
199  char *new_area;
200
201  if ( !ptr )
202    return malloc( size );
203
204  if ( !size ) {
205    free( ptr );
206    return (void *) 0;
207  }
208
209  status = rtems_region_get_segment_size( RTEMS_Malloc_Heap, ptr, &old_size );
210  if ( status != RTEMS_SUCCESSFUL ) {
211    errno = EINVAL;
212    return (void *) 0;
213  }
214
215  new_area = malloc( size );
216  if ( !new_area ) {
217    free( ptr );
218    return (void *) 0;
219  }
220
221  memcpy( new_area, ptr, (size < old_size) ? size : old_size );
222  free( ptr );
223
224  return new_area;
225
226}
227
228void free(
229  void *ptr
230)
231{
232  rtems_status_code status;
233
234  if ( !ptr )
235    return;
236
237  status = rtems_region_return_segment( RTEMS_Malloc_Heap, ptr );
238  if ( status != RTEMS_SUCCESSFUL ) {
239    errno = EINVAL;
240    assert( 0 );
241  }
242}
243
244/*
245 *  "Reentrant" versions of the above routines implemented above.
246 */
247
248#ifdef RTEMS_NEWLIB
249void *malloc_r(
250  struct _reent *ignored,
251  size_t  size
252)
253{
254  return malloc( size );
255}
256
257void *calloc_r(
258  size_t nelem,
259  size_t elsize
260)
261{
262  return calloc( nelem, elsize );
263}
264
265void *realloc_r(
266  void *ptr,
267  size_t size
268)
269{
270  return realloc_r( ptr, size );
271}
272
273void free_r(
274  void *ptr
275)
276{
277  free( ptr );
278}
279#endif
280
Note: See TracBrowser for help on using the repository browser.