source: soft/giet_vm/giet_libs/malloc.c @ 385

Last change on this file since 385 was 382, checked in by alain, 10 years ago

Major evolution of the malloc library, to provide two new services:

  • all allocated blocks are aligned, and the size is a power of 2.
  • the remote-malloc() function allows the application to explicitely define the cluster(x,y).

We keep only the close-fit allocation policy.
These services were required to implement the distributed SBT barrier.

  • Property svn:executable set to *
File size: 11.4 KB
RevLine 
[382]1////////////////////////////////////////////////////////////////////////////////
2// File     : malloc.c
3// Date     : 05/03/2013
4// Author   : Jean-Baptiste Bréjon / alain greiner
5// Copyright (c) UPMC-LIP6
6////////////////////////////////////////////////////////////////////////////////
[258]7
8#include "malloc.h"
9#include "stdio.h"
10
[382]11// Global variables defining the heap descriptors array (one heap per cluster)
12giet_heap_t heap[X_SIZE][Y_SIZE];
[325]13
[382]14// Macro returning the smallest power of 2 larger or equal to size value
15#define GET_SIZE_INDEX(size)                (size <= 0x00000001) ? 0  :\
16                                            (size <= 0x00000002) ? 1  :\
17                                            (size <= 0x00000004) ? 2  :\
18                                            (size <= 0x00000008) ? 3  :\
19                                            (size <= 0x00000010) ? 4  :\
20                                            (size <= 0x00000020) ? 5  :\
21                                            (size <= 0x00000040) ? 6  :\
22                                            (size <= 0x00000080) ? 7  :\
23                                            (size <= 0x00000100) ? 8  :\
24                                            (size <= 0x00000200) ? 9  :\
25                                            (size <= 0x00000400) ? 10 :\
26                                            (size <= 0x00000800) ? 11 :\
27                                            (size <= 0x00001000) ? 12 :\
28                                            (size <= 0x00002000) ? 13 :\
29                                            (size <= 0x00004000) ? 14 :\
30                                            (size <= 0x00008000) ? 15 :\
31                                            (size <= 0x00010000) ? 16 :\
32                                            (size <= 0x00020000) ? 17 :\
33                                            (size <= 0x00040000) ? 18 :\
34                                            (size <= 0x00080000) ? 19 :\
35                                            (size <= 0x00100000) ? 20 :\
36                                            (size <= 0x00200000) ? 21 :\
37                                            (size <= 0x00400000) ? 22 :\
38                                            (size <= 0x00800000) ? 23 :\
39                                            (size <= 0x01000000) ? 24 :\
40                                            (size <= 0x02000000) ? 25 :\
41                                            (size <= 0x04000000) ? 26 :\
42                                            (size <= 0x08000000) ? 27 :\
43                                            (size <= 0x10000000) ? 28 :\
44                                            (size <= 0x20000000) ? 29 :\
45                                            (size <= 0x40000000) ? 30 :\
46                                            (size <= 0x80000000) ? 31 :\
47                                                                   32
48////////////////////////////////
49void heap_init( unsigned int x,
50                unsigned int y )
51{
52    unsigned int heap_base;        // heap segment base
53    unsigned int heap_size;        // heap segment size
54    unsigned int heap_index;       // size_index in free[array]
[258]55
[382]56    unsigned int alloc_base;       // alloc[] array base
57    unsigned int alloc_size;       // alloc[] array size
58    unsigned int alloc_index;      // size_index in free[array]
[258]59
[382]60    unsigned int index;            // iterator
[258]61
[382]62    // get heap_base, heap size, and heap index
63    giet_heap_info( &heap_base, &heap_size, x, y );
64    heap_index = GET_SIZE_INDEX( heap_size );
[258]65
[382]66    // checking heap segment constraints
67    if ( heap_size == 0 )                                    // heap segment exist
68    {
69        giet_exit("ERROR in malloc() : heap not found \n");
[258]70    }
[382]71    if ( heap_size != (1<<heap_index) )                      // heap size power of 2
[258]72    {
[382]73        giet_exit("ERROR in malloc() : heap size must be power of 2\n");
[258]74    }
[382]75    if ( heap_base % heap_size )                             // heap segment aligned
[258]76    {
[382]77        giet_exit("ERROR in malloc() : heap segment must be aligned\n");
[258]78    }
79
[382]80    // compute alloc[] minimal array size
81    alloc_size = heap_size / MIN_BLOCK_SIZE;
[258]82
[382]83    // get index for the corresponding block
84    alloc_index = GET_SIZE_INDEX( alloc_size );
[258]85
[382]86    // compute alloc[] array base address
87    alloc_base = heap_base + heap_size - alloc_size;
[258]88
[382]89    // reset the free[] array
90    for ( index = 0 ; index < 32 ; index++ )
91    {
92        heap[x][y].free[index] = 0;
[258]93    }
94
[382]95    // split the heap into various sizes blocks,
96    // initializes the free[] array and NEXT pointers
97    // base is the block base address
98    unsigned int   base = heap_base;
99    unsigned int*  ptr;
100    for ( index = heap_index-1 ; index > alloc_index ; index-- )
101    {
102        heap[x][y].free[index] = base;
103        ptr = (unsigned int*)base;
104        *ptr = 0;
105        base = base + (1<<index);
[258]106    }
107
[382]108    heap[x][y].init       = HEAP_INITIALIZED;
109    heap[x][y].x          = x;
110    heap[x][y].y          = y;
111    heap[x][y].heap_base  = heap_base;
112    heap[x][y].heap_size  = heap_size;
113    heap[x][y].alloc_size = alloc_size;
114    heap[x][y].alloc_base = alloc_base;
[258]115
[382]116    lock_release( &heap[x][y].lock );
[258]117
[382]118#if GIET_DEBUG_MALLOC
119giet_shr_printf("\n[MALLOC DEBUG] Heap[%d][%d] initialisation\n"
120                " - heap_base  = %x\n"
121                " - heap_size  = %x\n"
122                " - alloc_base = %x\n"
123                " - alloc_size = %x\n"
124                " - free[0]    = %x\n"
125                " - free[1]    = %x\n"
126                " - free[2]    = %x\n"
127                " - free[3]    = %x\n"
128                " - free[4]    = %x\n"
129                " - free[5]    = %x\n"
130                " - free[6]    = %x\n"
131                " - free[7]    = %x\n"
132                " - free[8]    = %x\n"
133                " - free[9]    = %x\n"
134                " - free[10]   = %x\n"
135                " - free[11]   = %x\n"
136                " - free[12]   = %x\n"
137                " - free[13]   = %x\n"
138                " - free[14]   = %x\n"
139                " - free[15]   = %x\n"
140                " - free[16]   = %x\n"
141                " - free[17]   = %x\n"
142                " - free[18]   = %x\n"
143                " - free[19]   = %x\n"
144                " - free[20]   = %x\n"
145                " - free[21]   = %x\n"
146                " - free[22]   = %x\n"
147                " - free[23]   = %x\n",
148                heap[x][y].x, heap[x][y].y, 
149                heap[x][y].heap_base, heap[x][y].heap_size, 
150                heap[x][y].alloc_base, heap[x][y].alloc_size,
151                heap[x][y].free[0], heap[x][y].free[1], 
152                heap[x][y].free[2], heap[x][y].free[3],
153                heap[x][y].free[4], heap[x][y].free[5],
154                heap[x][y].free[6], heap[x][y].free[7],
155                heap[x][y].free[8], heap[x][y].free[9],
156                heap[x][y].free[10], heap[x][y].free[11],
157                heap[x][y].free[12], heap[x][y].free[13],
158                heap[x][y].free[14], heap[x][y].free[15],
159                heap[x][y].free[16], heap[x][y].free[17],
160                heap[x][y].free[18], heap[x][y].free[19],
161                heap[x][y].free[20], heap[x][y].free[21],
162                heap[x][y].free[22], heap[x][y].free[23] );
163#endif
164               
165}  // end heap_init()
[258]166
[382]167////////////////////////////////////////////
168unsigned int split_block( giet_heap_t* heap,
169                          unsigned int vaddr, 
170                          unsigned int searched_index,
171                          unsigned int requested_index )
172{
173    // push the upper half block into free[searched_index-1]
174    unsigned int* new            = (unsigned int*)(vaddr + (1<<(searched_index-1)));
175    *new                         = heap->free[searched_index-1]; 
176    heap->free[searched_index-1] = (unsigned int)new;
177       
178    if ( searched_index == requested_index + 1 )  // terminal case: return lower half block
179    {
180        return vaddr;
[258]181    }
[382]182    else            // non terminal case : lower half block must be split again
183    {                               
184        return split_block( heap, vaddr, searched_index-1, requested_index );
[258]185    }
[382]186} // end split_block()
[258]187
[382]188//////////////////////////////////////////
189unsigned int get_block( giet_heap_t* heap,
190                        unsigned int searched_index,
191                        unsigned int requested_index )
192{
193    // test terminal case
194    if ( (1<<searched_index) > heap->heap_size )  // failure : return a NULL value
[258]195    {
[382]196        return 0;
[258]197    }
[382]198    else                            // search a block in free[searched_index]
[258]199    {
[382]200        unsigned int vaddr = heap->free[searched_index];
201        if ( vaddr == 0 )     // block not found : search in free[searched_index+1]
[258]202        {
[382]203            return get_block( heap, searched_index+1, requested_index );
[258]204        }
[382]205        else                // block found : pop it from free[searched_index]
[258]206        {
[382]207            // pop the block from free[searched_index]
208            unsigned int next = *((unsigned int*)vaddr); 
209            heap->free[searched_index] = next;
210           
211            // test if the block must be split
212            if ( searched_index == requested_index )  // no split required
213            {
214                return vaddr;
[258]215            }
[382]216            else                                      // split is required
217            {
218                return split_block( heap, vaddr, searched_index, requested_index );
[258]219            }
[382]220        } 
[258]221    }
[382]222} // end get_block()
[258]223
[382]224////////////////////////////////////////
225void * remote_malloc( unsigned int size,
226                      unsigned int x,
227                      unsigned int y ) 
[258]228{
[382]229    // checking arguments
230    if (size == 0) 
[258]231    {
[382]232        giet_exit("ERROR in malloc() : requested size = 0 \n");
[258]233    }
[382]234    if ( x >= X_SIZE )
[258]235    {
[382]236        giet_exit("ERROR in malloc() : x coordinate too large\n");
[258]237    }
[382]238    if ( y >= Y_SIZE )
[258]239    {
[382]240        giet_exit("ERROR in malloc() : y coordinate too large\n");
[258]241    }
242
[382]243    // initializes the heap if first access
244    if ( heap[x][y].init != HEAP_INITIALIZED )
[258]245    {
[382]246        heap_init( x, y );
[258]247    }
248
[382]249    // compute requested_index for the free[] array
250    unsigned int requested_index = GET_SIZE_INDEX( size );
[258]251
[382]252    // take the lock protecting access to heap(x,y)
253    lock_acquire( &heap[x][y].lock );
[258]254
[382]255    // call the recursive function get_block
256    unsigned int base = get_block( &heap[x][y], 
257                                   requested_index, 
258                                   requested_index );
[258]259
[382]260    // update the alloc[] array
261    unsigned offset = (base - heap[x][y].heap_base) / MIN_BLOCK_SIZE;
262    unsigned char* ptr = (unsigned char*)(heap[x][y].alloc_base + offset);
263    *ptr = requested_index;
[258]264
[382]265    // release the lock
266    lock_release( &heap[x][y].lock );
267 
268    return (void*)base;
[258]269
[382]270} // end remote_malloc()
[258]271
272
[382]273//////////////////////////////////
274void * malloc( unsigned int size )
275{
276    unsigned int proc_id    = giet_procid();
277    unsigned int cluster_xy = proc_id / NB_PROCS_MAX;
278    unsigned int x          = cluster_xy >> Y_WIDTH;
279    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
[258]280
[382]281    return remote_malloc( size, x, y );
282} 
[258]283
284
[382]285//////////////////////
286void free( void* ptr )
287{
288    // To be done
289    // - first : to compute the cluster coordinate
290    // - second : retrieve the block length from the
291    // - third : try to concatenate with another free block of same size
292    // - fourth : update the free[] array
[258]293}
294
295
296
297
298// Local Variables:
299// tab-width: 4
300// c-basic-offset: 4
301// c-file-offsets:((innamespace . 0)(inline-open . 0))
302// indent-tabs-mode: nil
303// End:
304// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
305
306
307
Note: See TracBrowser for help on using the repository browser.