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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libc/] [malloc.c] - Blame information for rev 173

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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