OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [libcsupport/] [src/] [malloc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
2
 *  RTEMS Malloc Family Implementation
3
 *
4
 *
5
 *  COPYRIGHT (c) 1989-1999.
6
 *  On-Line Applications Research Corporation (OAR).
7
 *
8
 *  The license and distribution terms for this file may be
9
 *  found in the file LICENSE in this distribution or at
10
 *  http://www.OARcorp.com/rtems/license.html.
11
 *
12
 *  malloc.c,v 1.29 2001/01/08 18:26:44 joel Exp
13
 */
14
 
15
#if HAVE_CONFIG_H
16
#include "config.h"
17
#endif
18
 
19
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
20
#include <rtems.h>
21
#include <rtems/libcsupport.h>
22
#ifdef RTEMS_NEWLIB
23
#include <sys/reent.h>
24
#endif
25
 
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <sys/types.h>
29
#include <assert.h>
30
#include <errno.h>
31
#include <string.h>
32
 
33
#include <unistd.h>    /* sbrk(2) */
34
 
35
rtems_id RTEMS_Malloc_Heap;
36
size_t RTEMS_Malloc_Sbrk_amount;
37
 
38
#ifdef RTEMS_DEBUG
39
#define MALLOC_STATS
40
#define MALLOC_DIRTY
41
#endif
42
 
43
#ifdef MALLOC_STATS
44
#define MSBUMP(f,n)    rtems_malloc_stats.f += (n)
45
 
46
struct {
47
    unsigned32  space_available;             /* current size of malloc area */
48
    unsigned32  malloc_calls;                /* # calls to malloc */
49
    unsigned32  free_calls;
50
    unsigned32  realloc_calls;
51
    unsigned32  calloc_calls;
52
    unsigned32  max_depth;                   /* most ever malloc'd at 1 time */
53
    unsigned64  lifetime_allocated;
54
    unsigned64  lifetime_freed;
55
} rtems_malloc_stats;
56
 
57
#else                   /* No rtems_malloc_stats */
58
#define MSBUMP(f,n)
59
#endif
60
 
61
void RTEMS_Malloc_Initialize(
62
  void   *start,
63
  size_t  length,
64
  size_t  sbrk_amount
65
)
66
{
67
  rtems_status_code   status;
68
  void               *starting_address;
69
  rtems_unsigned32    old_address;
70
  rtems_unsigned32    u32_address;
71
 
72
  /*
73
   * If the starting address is 0 then we are to attempt to
74
   * get length worth of memory using sbrk. Make sure we
75
   * align the address that we get back.
76
   */
77
 
78
  starting_address = start;
79
  RTEMS_Malloc_Sbrk_amount = sbrk_amount;
80
 
81
  if (!starting_address) {
82
    u32_address = (unsigned int)sbrk(length);
83
 
84
    if (u32_address == (rtems_unsigned32) -1) {
85
      rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
86
      /* DOES NOT RETURN!!! */
87
    }
88
 
89
    if (u32_address & (CPU_HEAP_ALIGNMENT-1)) {
90
      old_address = u32_address;
91
      u32_address = (u32_address + CPU_HEAP_ALIGNMENT) & ~(CPU_HEAP_ALIGNMENT-1);
92
 
93
       /*
94
        * adjust the length by whatever we aligned by
95
        */
96
 
97
      length -= u32_address - old_address;
98
    }
99
 
100
    starting_address = (void *)u32_address;
101
  }
102
 
103
  /*
104
   *  If the BSP is not clearing out the workspace, then it is most likely
105
   *  not clearing out the initial memory for the heap.  There is no
106
   *  standard supporting zeroing out the heap memory.  But much code
107
   *  with UNIX history seems to assume that memory malloc'ed during
108
   *  initialization (before any free's) is zero'ed.  This is true most
109
   *  of the time under UNIX because zero'ing memory when it is first
110
   *  given to a process eliminates the chance of a process seeing data
111
   *  left over from another process.  This would be a security violation.
112
   */
113
 
114
  if ( rtems_cpu_configuration_get_do_zero_of_workspace() )
115
     memset( starting_address, 0, length );
116
 
117
  /*
118
   *  Unfortunately we cannot use assert if this fails because if this
119
   *  has failed we do not have a heap and if we do not have a heap
120
   *  STDIO cannot work because there will be no buffers.
121
   */
122
 
123
  status = rtems_region_create(
124
    rtems_build_name( 'H', 'E', 'A', 'P' ),
125
    starting_address,
126
    length,
127
    CPU_HEAP_ALIGNMENT,
128
    RTEMS_DEFAULT_ATTRIBUTES,
129
    &RTEMS_Malloc_Heap
130
  );
131
  if ( status != RTEMS_SUCCESSFUL )
132
    rtems_fatal_error_occurred( status );
133
 
134
#ifdef MALLOC_STATS
135
  /* zero all the stats */
136
  (void) memset( &rtems_malloc_stats, 0, sizeof(rtems_malloc_stats) );
137
#endif
138
 
139
  MSBUMP(space_available, length);
140
}
141
 
142
#ifdef RTEMS_NEWLIB
143
void *malloc(
144
  size_t  size
145
)
146
{
147
  void              *return_this;
148
  void              *starting_address;
149
  rtems_unsigned32   the_size;
150
  rtems_unsigned32   sbrk_amount;
151
  rtems_status_code  status;
152
 
153
  MSBUMP(malloc_calls, 1);
154
 
155
  if ( !size )
156
    return (void *) 0;
157
 
158
  /*
159
   * Try to give a segment in the current region if there is not
160
   * enough space then try to grow the region using rtems_region_extend().
161
   * If this fails then return a NULL pointer.
162
   */
163
 
164
  status = rtems_region_get_segment(
165
    RTEMS_Malloc_Heap,
166
    size,
167
    RTEMS_NO_WAIT,
168
    RTEMS_NO_TIMEOUT,
169
    &return_this
170
  );
171
 
172
  if ( status != RTEMS_SUCCESSFUL ) {
173
    /*
174
     *  Round to the "requested sbrk amount" so hopefully we won't have
175
     *  to grow again for a while.  This effectively does sbrk() calls
176
     *  in "page" amounts.
177
     */
178
 
179
    sbrk_amount = RTEMS_Malloc_Sbrk_amount;
180
 
181
    if ( sbrk_amount == 0 )
182
      return (void *) 0;
183
 
184
    the_size = ((size + sbrk_amount) / sbrk_amount * sbrk_amount);
185
 
186
    if (((rtems_unsigned32)starting_address = (void *)sbrk(the_size))
187
            == (rtems_unsigned32) -1)
188
      return (void *) 0;
189
 
190
    status = rtems_region_extend(
191
      RTEMS_Malloc_Heap,
192
      starting_address,
193
      the_size
194
    );
195
    if ( status != RTEMS_SUCCESSFUL ) {
196
      sbrk(-the_size);
197
      errno = ENOMEM;
198
      return (void *) 0;
199
    }
200
 
201
    MSBUMP(space_available, the_size);
202
 
203
    status = rtems_region_get_segment(
204
      RTEMS_Malloc_Heap,
205
       size,
206
       RTEMS_NO_WAIT,
207
       RTEMS_NO_TIMEOUT,
208
       &return_this
209
    );
210
    if ( status != RTEMS_SUCCESSFUL ) {
211
      errno = ENOMEM;
212
      return (void *) 0;
213
    }
214
  }
215
 
216
#ifdef MALLOC_STATS
217
  if (return_this)
218
  {
219
      unsigned32 actual_size;
220
      unsigned32 current_depth;
221
      status = rtems_region_get_segment_size(
222
                   RTEMS_Malloc_Heap, return_this, &actual_size);
223
      MSBUMP(lifetime_allocated, actual_size);
224
      current_depth = rtems_malloc_stats.lifetime_allocated -
225
                   rtems_malloc_stats.lifetime_freed;
226
      if (current_depth > rtems_malloc_stats.max_depth)
227
          rtems_malloc_stats.max_depth = current_depth;
228
  }
229
#endif
230
 
231
#ifdef MALLOC_DIRTY
232
  (void) memset(return_this, 0xCF, size);
233
#endif
234
 
235
  return return_this;
236
}
237
 
238
void *calloc(
239
  size_t nelem,
240
  size_t elsize
241
)
242
{
243
  register char *cptr;
244
  int length;
245
 
246
  MSBUMP(calloc_calls, 1);
247
 
248
  length = nelem * elsize;
249
  cptr = malloc( length );
250
  if ( cptr )
251
    memset( cptr, '\0', length );
252
 
253
  MSBUMP(malloc_calls, -1);   /* subtract off the malloc */
254
 
255
  return cptr;
256
}
257
 
258
void *realloc(
259
  void *ptr,
260
  size_t size
261
)
262
{
263
  rtems_unsigned32  old_size;
264
  rtems_status_code status;
265
  char *new_area;
266
 
267
  MSBUMP(realloc_calls, 1);
268
 
269
  if ( !ptr )
270
    return malloc( size );
271
 
272
  if ( !size ) {
273
    free( ptr );
274
    return (void *) 0;
275
  }
276
 
277
  new_area = malloc( size );
278
 
279
  MSBUMP(malloc_calls, -1);   /* subtract off the malloc */
280
 
281
  if ( !new_area ) {
282
    free( ptr );
283
    return (void *) 0;
284
  }
285
 
286
  status = rtems_region_get_segment_size( RTEMS_Malloc_Heap, ptr, &old_size );
287
  if ( status != RTEMS_SUCCESSFUL ) {
288
    errno = EINVAL;
289
    return (void *) 0;
290
  }
291
 
292
  memcpy( new_area, ptr, (size < old_size) ? size : old_size );
293
  free( ptr );
294
 
295
  return new_area;
296
 
297
}
298
 
299
void free(
300
  void *ptr
301
)
302
{
303
  rtems_status_code status;
304
 
305
  MSBUMP(free_calls, 1);
306
 
307
  if ( !ptr )
308
    return;
309
 
310
#ifdef MALLOC_STATS
311
  {
312
      unsigned32        size;
313
      status = rtems_region_get_segment_size( RTEMS_Malloc_Heap, ptr, &size );
314
      if ( status == RTEMS_SUCCESSFUL ) {
315
          MSBUMP(lifetime_freed, size);
316
      }
317
  }
318
#endif
319
 
320
  status = rtems_region_return_segment( RTEMS_Malloc_Heap, ptr );
321
  if ( status != RTEMS_SUCCESSFUL ) {
322
    errno = EINVAL;
323
    assert( 0 );
324
  }
325
}
326
/* end if RTEMS_NEWLIB */
327
#endif
328
 
329
#ifdef MALLOC_STATS
330
/*
331
 * Dump the malloc statistics
332
 * May be called via atexit()  (installable by our bsp) or
333
 * at any time by user
334
 */
335
 
336
void malloc_dump(void)
337
{
338
    unsigned32 allocated = rtems_malloc_stats.lifetime_allocated -
339
                     rtems_malloc_stats.lifetime_freed;
340
 
341
    printf("Malloc stats\n");
342
    printf("  avail:%uk  allocated:%uk (%d%%) "
343
              "max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",
344
           (unsigned int) rtems_malloc_stats.space_available / 1024,
345
           (unsigned int) allocated / 1024,
346
           /* avoid float! */
347
           (allocated * 100) / rtems_malloc_stats.space_available,
348
           (unsigned int) rtems_malloc_stats.max_depth / 1024,
349
           (rtems_malloc_stats.max_depth * 100) / rtems_malloc_stats.space_available,
350
           (unsigned64) rtems_malloc_stats.lifetime_allocated / 1024,
351
           (unsigned64) rtems_malloc_stats.lifetime_freed / 1024);
352
    printf("  Call counts:   malloc:%d   free:%d   realloc:%d   calloc:%d\n",
353
           rtems_malloc_stats.malloc_calls,
354
           rtems_malloc_stats.free_calls,
355
           rtems_malloc_stats.realloc_calls,
356
           rtems_malloc_stats.calloc_calls);
357
}
358
 
359
 
360
void malloc_walk(size_t source, size_t printf_enabled)
361
{
362
   register Region_Control *the_region;
363
   Objects_Locations        location;
364
 
365
   the_region = _Region_Get( RTEMS_Malloc_Heap, &location );
366
   if ( location == OBJECTS_LOCAL )
367
   {
368
      _Heap_Walk( &the_region->Memory, source, printf_enabled );
369
      _Thread_Enable_dispatch();
370
   }
371
}
372
 
373
#else
374
 
375
void malloc_dump(void)
376
{
377
   return;
378
}
379
 
380
void malloc_walk(size_t source, size_t printf_enabled)
381
{
382
   return;
383
}
384
 
385
#endif
386
 
387
/*
388
 *  "Reentrant" versions of the above routines implemented above.
389
 */
390
 
391
#ifdef RTEMS_NEWLIB
392
void *_malloc_r(
393
  struct _reent *ignored,
394
  size_t  size
395
)
396
{
397
  return malloc( size );
398
}
399
 
400
void *_calloc_r(
401
  struct _reent *ignored,
402
  size_t nelem,
403
  size_t elsize
404
)
405
{
406
  return calloc( nelem, elsize );
407
}
408
 
409
void *_realloc_r(
410
  struct _reent *ignored,
411
  void *ptr,
412
  size_t size
413
)
414
{
415
  return realloc( ptr, size );
416
}
417
 
418
void _free_r(
419
  struct _reent *ignored,
420
  void *ptr
421
)
422
{
423
  free( ptr );
424
}
425
 
426
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.