unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / services / memalloc / common / v2_0 / src / malloc.cxx
1 //========================================================================
2 //
3 //      malloc.cxx
4 //
5 //      Implementation of ISO C memory allocation routines
6 //
7 //========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):     jlarmour
44 // Contributors:  
45 // Date:          2000-04-30
46 // Purpose:       Provides ISO C calloc(), malloc(), realloc() and free()
47 //                functions
48 // Description:   Implementation of ISO standard allocation routines as per
49 //                ISO C section 7.10.3
50 // Usage:       
51 //
52 //####DESCRIPTIONEND####
53 //
54 //========================================================================
55
56 // CONFIGURATION
57
58 #include <pkgconf/memalloc.h>   // Configuration header
59
60 // Do we want these functions?
61 #ifdef CYGPKG_MEMALLOC_MALLOC_ALLOCATORS
62
63 // INCLUDES
64
65 #include <cyg/infra/cyg_type.h>    // Common type definitions and support
66 #include <cyg/infra/cyg_trac.h>    // Common tracing support
67 #include <cyg/infra/cyg_ass.h>     // Common assertion support
68 #include <string.h>                // For memset() and memmove()
69 #include <stdlib.h>                // header for this file
70 #ifdef CYGBLD_MEMALLOC_MALLOC_EXTERNAL_HEAP_H
71 # include CYGBLD_MEMALLOC_MALLOC_EXTERNAL_HEAP_H
72 #else
73 # include <pkgconf/heaps.hxx>       // heap pools information
74 #endif
75 #include CYGBLD_MEMALLOC_MALLOC_IMPLEMENTATION_HEADER
76
77 // STATIC VARIABLES
78
79 // First deal with the worst case, that the memory layout didn't define a
80 // heap
81 #if CYGMEM_HEAP_COUNT == 0
82
83 // the data space for the memory pool
84 cyg_uint8 cyg_memalloc_mallocpool_memory[ 
85     CYGNUM_MEMALLOC_FALLBACK_MALLOC_POOL_SIZE ] CYGBLD_ATTRIB_WEAK;
86
87 // the memory pool object itself
88 CYGCLS_MEMALLOC_MALLOC_IMPL cyg_memalloc_mallocpool
89    CYGBLD_ATTRIB_INIT_PRI( CYG_INIT_MEMALLOC ) =
90    CYGCLS_MEMALLOC_MALLOC_IMPL( cyg_memalloc_mallocpool_memory,
91                                 sizeof( cyg_memalloc_mallocpool_memory ) );
92
93 # define POOL cyg_memalloc_mallocpool
94
95 #elif CYGMEM_HEAP_COUNT == 1
96 // one heap, so it's straightforward
97
98 # define POOL (*cygmem_memalloc_heaps[0])
99
100 #else 
101 // multiple heaps
102 #ifdef CYGBLD_MEMALLOC_MALLOC_EXTERNAL_JOIN_H
103 # include CYGBLD_MEMALLOC_MALLOC_EXTERNAL_JOIN_H
104 #else
105 # include <cyg/memalloc/memjoin.hxx>
106 #endif
107
108 Cyg_Mempool_Joined<CYGCLS_MEMALLOC_MALLOC_IMPL> cyg_memalloc_mallocpool
109    CYGBLD_ATTRIB_INIT_PRI( CYG_INIT_MEMALLOC ) =
110      Cyg_Mempool_Joined<CYGCLS_MEMALLOC_MALLOC_IMPL>(
111        CYGMEM_HEAP_COUNT, cygmem_memalloc_heaps
112      );
113
114 # define POOL cyg_memalloc_mallocpool
115
116 #endif
117
118 // FUNCTIONS
119
120 void *
121 malloc( size_t size )
122 {
123     void *data_ptr;
124
125     CYG_REPORT_FUNCNAMETYPE( "malloc", "returning pointer %08x" );
126     
127     CYG_REPORT_FUNCARG1DV( size );
128
129 #ifdef CYGSEM_MEMALLOC_MALLOC_ZERO_RETURNS_NULL
130     // first check if size wanted is 0
131     if ( 0 == size ) {
132         CYG_REPORT_RETVAL( NULL );
133         return NULL;
134     } // if
135 #endif
136
137     // ask the pool for the data
138     data_ptr = POOL.try_alloc( size );
139
140     // if it isn't NULL is the pointer valid?
141     if ( NULL != data_ptr ) {
142         CYG_CHECK_DATA_PTR( data_ptr,
143                             "allocator returned invalid pointer!" );
144
145         // And just check its alignment
146         CYG_ASSERT( !((CYG_ADDRWORD)data_ptr & (sizeof(CYG_ADDRWORD) - 1)),
147                     "Allocator has returned badly aligned data!");
148     } // if
149
150     CYG_REPORT_RETVAL( data_ptr );
151
152     return data_ptr;
153 } // malloc()
154
155
156 void
157 free( void *ptr )
158 {
159     cyg_bool freeret;
160
161     CYG_REPORT_FUNCNAME( "free");
162     
163     CYG_REPORT_FUNCARG1XV( ptr );
164
165     // if null pointer, do nothing as per spec
166     if ( NULL==ptr )
167         return;
168
169     CYG_CHECK_DATA_PTR( ptr, "Pointer to free isn't even valid!" );
170
171     // get pool to free it
172     freeret = POOL.free( (cyg_uint8 *) ptr );
173
174     CYG_ASSERT( freeret , "Couldn't free!" );
175
176     CYG_REPORT_RETURN();
177
178 } // free()
179
180
181 void *
182 calloc( size_t nmemb, size_t size )
183 {
184     void *data_ptr;
185     cyg_ucount32 realsize;
186
187     CYG_REPORT_FUNCNAMETYPE( "calloc", "returning pointer %08x" );
188     
189     CYG_REPORT_FUNCARG2DV( nmemb, size );
190
191     realsize = nmemb * size;
192
193     data_ptr = malloc( realsize );
194
195     // Fill with 0's if non-NULL
196     if ( data_ptr != NULL )
197         memset( data_ptr, 0, realsize );
198
199     CYG_REPORT_RETVAL( data_ptr );
200     return data_ptr;
201 } // calloc()
202
203
204 externC void *
205 realloc( void *ptr, size_t size )
206 {
207     cyg_int32 oldsize;
208
209     CYG_REPORT_FUNCNAMETYPE( "realloc", "returning pointer %08x" );
210
211     CYG_REPORT_FUNCARG2( "ptr=%08x, size=%d", ptr, size );
212
213     // if pointer is NULL, we must malloc it
214     if ( ptr == NULL ) {
215         ptr = malloc( size );
216         CYG_REPORT_RETVAL( ptr );
217         return ptr;
218     } // if
219
220     CYG_CHECK_DATA_PTR( ptr, "realloc() passed a bogus pointer!" );
221
222     // if size is 0, we must free it
223     if (size == 0) {
224         free(ptr);
225         CYG_REPORT_RETVAL( NULL );
226         return NULL;
227     } // if
228         
229     void *newptr;
230
231     // otherwise try to resize allocation
232     newptr = POOL.resize_alloc( (cyg_uint8 *)ptr, size, &oldsize );
233
234     if ( NULL == newptr ) {
235         // if resize_alloc doesn't return a pointer, it failed, so we
236         // just have to allocate new space instead, and later copy it
237         
238         CYG_ASSERT( oldsize != 0,
239                     "resize_alloc() couldn't determine allocation size!" );
240
241         newptr = malloc( size );
242         
243         if ( NULL != newptr ) {
244             memcpy( newptr, ptr, size < (size_t) oldsize ? size
245                     : (size_t) oldsize );
246             free( ptr );
247         }
248     }
249     
250     CYG_REPORT_RETVAL( newptr );
251     return newptr;
252 } // realloc()
253
254
255 externC struct mallinfo
256 mallinfo( void )
257 {
258     struct mallinfo ret = { 0 }; // initialize to all zeros
259     Cyg_Mempool_Status stat;
260
261     CYG_REPORT_FUNCTION();
262
263     POOL.get_status( CYG_MEMPOOL_STAT_ARENASIZE|
264                      CYG_MEMPOOL_STAT_FREEBLOCKS|
265                      CYG_MEMPOOL_STAT_TOTALALLOCATED|
266                      CYG_MEMPOOL_STAT_TOTALFREE|
267                      CYG_MEMPOOL_STAT_MAXFREE, stat );
268
269     if ( stat.arenasize > 0 )
270         ret.arena = stat.arenasize;
271     
272     if ( stat.freeblocks > 0 )
273         ret.ordblks = stat.freeblocks;
274
275     if ( stat.totalallocated > 0 )
276         ret.uordblks = stat.totalallocated;
277     
278     if ( stat.totalfree > 0 )
279         ret.fordblks = stat.totalfree;
280
281     if ( stat.maxfree > 0 )
282         ret.maxfree = stat.maxfree;
283
284     CYG_REPORT_RETURN();
285     return ret;
286 } // mallinfo()
287
288 #endif // ifdef CYGPKG_MEMALLOC_MALLOC_ALLOCATORS
289
290 // EOF malloc.cxx