source: rtems/c/src/lib/libc/malloc.c @ 4cc631db

4.104.114.84.95
Last change on this file since 4cc631db was 4cc631db, checked in by Joel Sherrill <joel.sherrill@…>, on 08/11/95 at 14:33:04

Added functions to access the errno of the native system when using the
newlib C library.

Fixed bug where length did not take into account amount added
for alignment requirements.

  • Property mode set to 100644
File size: 5.6 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    old_address;
57  rtems_unsigned32    u32_address;
58
59  /*
60   * If the starting address is 0 then we are to attempt to
61   * get length worth of memory using sbrk. Make sure we
62   * align the address that we get back.
63   */
64
65  starting_address = start;
66  RTEMS_Malloc_Sbrk_amount = sbrk_amount;
67
68  if (!starting_address) {
69    u32_address = (unsigned int)sbrk(length);
70
71    if (u32_address == -1) {
72      rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
73      /* DOES NOT RETURN!!! */
74    }
75
76    if (u32_address & (CPU_ALIGNMENT-1)) {
77      old_address = u32_address;
78      u32_address = (u32_address + CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1);
79
80      /*
81       *  Adjust the length by whatever we aligned by
82       */
83
84      length -= u32_address - old_address;
85    }
86
87    starting_address = (void *)u32_address;
88  }
89
90  /*
91   *  Unfortunately we cannot use assert if this fails because if this
92   *  has failed we do not have a heap and if we do not have a heap
93   *  STDIO cannot work because there will be no buffers.
94   */
95
96  status = rtems_region_create(
97    rtems_build_name( 'H', 'E', 'A', 'P' ),
98    starting_address,
99    length,
100    8,                     /* XXX : use CPU dependent RTEMS constant */
101    RTEMS_DEFAULT_ATTRIBUTES,
102    &RTEMS_Malloc_Heap
103  );
104  if ( status != RTEMS_SUCCESSFUL )
105    rtems_fatal_error_occurred( status );
106}
107
108void *malloc(
109  size_t  size
110)
111{
112  void              *return_this;
113  void              *starting_address;
114  rtems_unsigned32   the_size;
115  rtems_unsigned32   sbrk_amount;
116  rtems_status_code  status;
117
118  if ( !size )
119    return (void *) 0;
120
121  /*
122   * Try to give a segment in the current region if there is not
123   * enough space then try to grow the region using rtems_region_extend().
124   * If this fails then return a NULL pointer.
125   */
126
127  status = rtems_region_get_segment(
128    RTEMS_Malloc_Heap,
129    size,
130    RTEMS_NO_WAIT,
131    RTEMS_NO_TIMEOUT,
132    &return_this
133  );
134
135  if ( status != RTEMS_SUCCESSFUL ) {
136    /*
137     *  Round to the "requested sbrk amount" so hopefully we won't have
138     *  to grow again for a while.  This effectively does sbrk() calls
139     *  in "page" amounts.
140     */
141
142    sbrk_amount = RTEMS_Malloc_Sbrk_amount;
143
144    if ( sbrk_amount == 0 )
145      return (void *) 0;
146
147    the_size = ((size + sbrk_amount) / sbrk_amount * sbrk_amount);
148
149    if (((rtems_unsigned32)starting_address = sbrk(the_size)) == -1)
150      return (void *) 0;
151
152    /*
153    fprintf(stderr, "Extended the C heap starting at 0x%x for %d bytes\n",
154        (unsigned32)starting_address, the_size);
155     */
156
157    status = rtems_region_extend(
158      RTEMS_Malloc_Heap,
159      starting_address,
160      the_size
161    );
162    if ( status != RTEMS_SUCCESSFUL ) {
163      sbrk(-the_size);
164      return(FALSE);
165      errno = ENOMEM;
166      return (void *) 0;
167    }
168    status = rtems_region_get_segment(
169      RTEMS_Malloc_Heap,
170       size,
171       RTEMS_NO_WAIT,
172       RTEMS_NO_TIMEOUT,
173       &return_this
174    );
175    if ( status != RTEMS_SUCCESSFUL ) {
176      errno = ENOMEM;
177      return (void *) 0;
178    }
179  }
180
181  return return_this;
182}
183
184void *calloc(
185  size_t nelem,
186  size_t elsize
187)
188{
189  register char *cptr;
190  int length;
191
192  length = nelem * elsize;
193  cptr = malloc( length );
194  if ( cptr )
195    memset( cptr, '\0', length );
196
197  return cptr;
198}
199
200void *realloc(
201  void *ptr,
202  size_t size
203)
204{
205  rtems_unsigned32  old_size;
206  rtems_status_code status;
207  char *new_area;
208
209  if ( !ptr )
210    return malloc( size );
211
212  if ( !size ) {
213    free( ptr );
214    return (void *) 0;
215  }
216
217  status = rtems_region_get_segment_size( RTEMS_Malloc_Heap, ptr, &old_size );
218  if ( status != RTEMS_SUCCESSFUL ) {
219    errno = EINVAL;
220    return (void *) 0;
221  }
222
223  new_area = malloc( size );
224  if ( !new_area ) {
225    free( ptr );
226    return (void *) 0;
227  }
228
229  memcpy( new_area, ptr, (size < old_size) ? size : old_size );
230  free( ptr );
231
232  return new_area;
233
234}
235
236void free(
237  void *ptr
238)
239{
240  rtems_status_code status;
241
242  if ( !ptr )
243    return;
244
245  status = rtems_region_return_segment( RTEMS_Malloc_Heap, ptr );
246  if ( status != RTEMS_SUCCESSFUL ) {
247    errno = EINVAL;
248    assert( 0 );
249  }
250}
251
252/*
253 *  "Reentrant" versions of the above routines implemented above.
254 */
255
256#ifdef RTEMS_NEWLIB
257void *malloc_r(
258  struct _reent *ignored,
259  size_t  size
260)
261{
262  return malloc( size );
263}
264
265void *calloc_r(
266  size_t nelem,
267  size_t elsize
268)
269{
270  return calloc( nelem, elsize );
271}
272
273void *realloc_r(
274  void *ptr,
275  size_t size
276)
277{
278  return realloc_r( ptr, size );
279}
280
281void free_r(
282  void *ptr
283)
284{
285  free( ptr );
286}
287#endif
288
Note: See TracBrowser for help on using the repository browser.