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

Last change on this file since 706 was 686, checked in by guerin, 10 years ago

remove almalloc implementation

It is in fact useless because malloc already returns aligned addresses.
Should have read the doc first ;)

  • Property svn:executable set to *
File size: 14.8 KB
Line 
1////////////////////////////////////////////////////////////////////////////////
2// File     : malloc.c
3// Date     : 05/03/2013
4// Author   : Jean-Baptiste Bréjon / alain greiner
5// Copyright (c) UPMC-LIP6
6////////////////////////////////////////////////////////////////////////////////
7
8#include "malloc.h"
9#include "stdio.h"
10#include "giet_config.h"
11
12// Global variables defining the heap descriptors array (one heap per cluster)
13giet_heap_t     heap[X_SIZE][Y_SIZE];
14
15// Macro returning the smallest power of 2 larger or equal to size value
16#define GET_SIZE_INDEX(size)                (size <= 0x00000001) ? 0  :\
17                                            (size <= 0x00000002) ? 1  :\
18                                            (size <= 0x00000004) ? 2  :\
19                                            (size <= 0x00000008) ? 3  :\
20                                            (size <= 0x00000010) ? 4  :\
21                                            (size <= 0x00000020) ? 5  :\
22                                            (size <= 0x00000040) ? 6  :\
23                                            (size <= 0x00000080) ? 7  :\
24                                            (size <= 0x00000100) ? 8  :\
25                                            (size <= 0x00000200) ? 9  :\
26                                            (size <= 0x00000400) ? 10 :\
27                                            (size <= 0x00000800) ? 11 :\
28                                            (size <= 0x00001000) ? 12 :\
29                                            (size <= 0x00002000) ? 13 :\
30                                            (size <= 0x00004000) ? 14 :\
31                                            (size <= 0x00008000) ? 15 :\
32                                            (size <= 0x00010000) ? 16 :\
33                                            (size <= 0x00020000) ? 17 :\
34                                            (size <= 0x00040000) ? 18 :\
35                                            (size <= 0x00080000) ? 19 :\
36                                            (size <= 0x00100000) ? 20 :\
37                                            (size <= 0x00200000) ? 21 :\
38                                            (size <= 0x00400000) ? 22 :\
39                                            (size <= 0x00800000) ? 23 :\
40                                            (size <= 0x01000000) ? 24 :\
41                                            (size <= 0x02000000) ? 25 :\
42                                            (size <= 0x04000000) ? 26 :\
43                                            (size <= 0x08000000) ? 27 :\
44                                            (size <= 0x10000000) ? 28 :\
45                                            (size <= 0x20000000) ? 29 :\
46                                            (size <= 0x40000000) ? 30 :\
47                                            (size <= 0x80000000) ? 31 :\
48                                                                   32
49////////////////////////////////////////
50void display_free_array( unsigned int x,
51                         unsigned int y )
52{
53    unsigned int next;
54    unsigned int id;
55    unsigned int iter;
56
57    giet_tty_printf("\nUser Heap[%d][%d] base = %x / size = %x\n", x , y , 
58                   heap[x][y].heap_base, heap[x][y].heap_size );
59    for ( id = 0 ; id < 32 ; id++ )
60    { 
61        next = heap[x][y].free[id];
62        giet_tty_printf(" - free[%d] = " , id );
63        iter = 0;
64        while ( next != 0 )
65        {
66            giet_tty_printf("%x | ", next );
67            next = (*(unsigned int*)next);
68            iter++;
69        }
70        giet_tty_printf("0\n");
71    }
72}  // end display_free_array()
73
74
75
76////////////////////////////////
77void heap_init( unsigned int x,
78                unsigned int y )
79{
80    unsigned int heap_base;        // heap segment base
81    unsigned int heap_size;        // heap segment size
82    unsigned int heap_index;       // size_index in free[array]
83
84    unsigned int alloc_base;       // alloc[] array base
85    unsigned int alloc_size;       // alloc[] array size
86    unsigned int alloc_index;      // size_index in alloc[array]
87
88    unsigned int index;            // iterator
89
90    // get heap_base, heap size, and heap index
91    giet_heap_info( &heap_base, &heap_size, x, y );
92    heap_index = GET_SIZE_INDEX( heap_size );
93
94#if GIET_DEBUG_USER_MALLOC
95giet_tty_printf("\n[DEBUG USER_MALLOC] Starting Heap[%d][%d] initialisation /"
96                " base = %x / size = %x\n", x, y, heap_base, heap_size );
97#endif
98
99    // checking heap segment constraints
100    if ( heap_size == 0 )                                    // heap segment exist
101    {
102        giet_exit("ERROR in malloc() : heap not found \n");
103    }
104    if ( heap_size != (1<<heap_index) )                      // heap size power of 2
105    {
106        giet_exit("ERROR in malloc() : heap size must be power of 2\n");
107    }
108    if ( heap_base % heap_size )                             // heap segment aligned
109    {
110        giet_exit("ERROR in malloc() : heap segment must be aligned\n");
111    }
112
113    // compute size of block containin alloc[] array
114    alloc_size = heap_size / MIN_BLOCK_SIZE;
115    if ( alloc_size < MIN_BLOCK_SIZE) alloc_size = MIN_BLOCK_SIZE;
116
117    // get index for the corresponding block
118    alloc_index = GET_SIZE_INDEX( alloc_size );
119
120    // compute alloc[] array base address
121    alloc_base = heap_base + heap_size - alloc_size;
122
123    // reset the free[] array
124    for ( index = 0 ; index < 32 ; index++ )
125    {
126        heap[x][y].free[index] = 0;
127    }
128
129    // reset the alloc_size array
130    unsigned int   word;
131    unsigned int*  tab = (unsigned int*)alloc_base;
132    for ( word = 0 ; word < (alloc_size>>2) ; word++ )  tab[word] = 0;
133 
134    // split the heap into various sizes blocks,
135    // initializes the free[] array and NEXT pointers
136    // base is the block base address
137    unsigned int   base = heap_base;
138    unsigned int*  ptr;
139    for ( index = heap_index-1 ; index >= alloc_index ; index-- )
140    {
141        heap[x][y].free[index] = base;
142        ptr = (unsigned int*)base;
143        *ptr = 0;
144        base = base + (1<<index);
145    }
146
147    heap[x][y].init       = HEAP_INITIALIZED;
148    heap[x][y].x          = x;
149    heap[x][y].y          = y;
150    heap[x][y].heap_base  = heap_base;
151    heap[x][y].heap_size  = heap_size;
152    heap[x][y].alloc_size = alloc_size;
153    heap[x][y].alloc_base = alloc_base;
154
155    lock_init( &heap[x][y].lock );
156
157#if GIET_DEBUG_USER_MALLOC
158giet_tty_printf("\n[DEBUG USER_MALLOC] Completing Heap[%d][%d] initialisation\n", x, y );
159display_free_array(x,y);
160#endif
161               
162}  // end heap_init()
163
164////////////////////////////////////////////
165unsigned int split_block( giet_heap_t* heap,
166                          unsigned int vaddr, 
167                          unsigned int searched_index,
168                          unsigned int requested_index )
169{
170    // push the upper half block into free[searched_index-1]
171    unsigned int* new            = (unsigned int*)(vaddr + (1<<(searched_index-1)));
172    *new                         = heap->free[searched_index-1]; 
173    heap->free[searched_index-1] = (unsigned int)new;
174       
175    if ( searched_index == requested_index + 1 )  // terminal case: return lower half block
176    {
177        return vaddr;
178    }
179    else            // non terminal case : lower half block must be split again
180    {                               
181        return split_block( heap, vaddr, searched_index-1, requested_index );
182    }
183} // end split_block()
184
185//////////////////////////////////////////
186unsigned int get_block( giet_heap_t* heap,
187                        unsigned int searched_index,
188                        unsigned int requested_index )
189{
190    // test terminal case
191    if ( (1<<searched_index) > heap->heap_size )  // failure : return a NULL value
192    {
193        return 0;
194    }
195    else                            // search a block in free[searched_index]
196    {
197        unsigned int vaddr = heap->free[searched_index];
198        if ( vaddr == 0 )     // block not found : search in free[searched_index+1]
199        {
200            return get_block( heap, searched_index+1, requested_index );
201        }
202        else                // block found : pop it from free[searched_index]
203        {
204            // pop the block from free[searched_index]
205            unsigned int next = *((unsigned int*)vaddr); 
206            heap->free[searched_index] = next;
207           
208            // test if the block must be split
209            if ( searched_index == requested_index )  // no split required
210            {
211                return vaddr;
212            }
213            else                                      // split is required
214            {
215                return split_block( heap, vaddr, searched_index, requested_index );
216            }
217        } 
218    }
219} // end get_block()
220
221////////////////////////////////////////
222void * remote_malloc( unsigned int size,
223                      unsigned int x,
224                      unsigned int y ) 
225{
226
227#if GIET_DEBUG_USER_MALLOC
228giet_tty_printf("\n[DEBUG USER_MALLOC] request for Heap[%d][%d] / size = %x\n", 
229                 x, y, size );
230#endif
231
232    // checking arguments
233    if (size == 0) 
234    {
235        giet_exit("\nERROR in remote_malloc() : requested size = 0 \n");
236    }
237    if ( x >= X_SIZE )
238    {
239        giet_exit("\nERROR in remote_malloc() : x coordinate too large\n");
240    }
241    if ( y >= Y_SIZE )
242    {
243        giet_exit("\nERROR in remote_malloc() : y coordinate too large\n");
244    }
245
246    // checking initialization
247    if ( heap[x][y].init != HEAP_INITIALIZED )
248    {
249        giet_exit("\nERROR in remote_malloc() : heap not initialized\n");
250    }
251
252    // normalize size
253    if ( size < MIN_BLOCK_SIZE ) size = MIN_BLOCK_SIZE;
254
255    // compute requested_index for the free[] array
256    unsigned int requested_index = GET_SIZE_INDEX( size );
257
258    // take the lock protecting access to heap[x][y]
259    lock_acquire( &heap[x][y].lock );
260
261    // call the recursive function get_block
262    unsigned int base = get_block( &heap[x][y], 
263                                   requested_index, 
264                                   requested_index );
265
266    // check block found
267    if ( base == 0 )
268    {
269        lock_release( &heap[x][y].lock );
270        giet_exit("\nERROR in remote_malloc() : no more space\n");
271    }
272
273    // compute pointer in alloc[] array
274    unsigned offset    = (base - heap[x][y].heap_base) / MIN_BLOCK_SIZE;
275    unsigned char* ptr = (unsigned char*)(heap[x][y].alloc_base + offset);
276
277    // check the alloc[] array
278    if ( *ptr != 0 )
279    {
280        lock_release( &heap[x][y].lock );
281        giet_exit("\nERROR in remote_malloc() : block already allocated ???\n");
282    }
283
284    // update alloc_array
285    *ptr = requested_index;
286
287    // release the lock
288    lock_release( &heap[x][y].lock );
289 
290#if GIET_DEBUG_USER_MALLOC
291giet_tty_printf("\n[DEBUG USER_MALLOC] allocated block from heap[%d][%d] : "
292                "base = %x / size = %x\n", x , y , base , size );
293display_free_array(x,y);
294#endif
295
296    return (void*)base;
297
298} // end remote_malloc()
299
300
301//////////////////////////////////
302void * malloc( unsigned int size )
303{
304    // get cluster coordinates
305    unsigned int    x;
306    unsigned int    y;
307    unsigned int    lpid;
308    giet_proc_xyp( &x, &y, &lpid );
309
310    return remote_malloc( size, x, y );
311} 
312
313///////////////////////////////////////////
314void update_free_array( giet_heap_t* heap,
315                        unsigned int base,
316                        unsigned int size_index )
317{
318    // This recursive function try to merge the released block
319    // with the companion block if this companion block is free.
320    // This companion has the same size, and almost the same address
321    // (only one address bit is different)
322    // - If the companion is not in free[size_index],
323    //   the released block is pushed in free[size_index].
324    // - If the companion is found, it is evicted from free[size_index]
325    //   and the merged bloc is pushed in the free[size_index+1].
326
327
328    // compute released block size
329    unsigned int size = 1<<size_index;
330
331    // compute companion block and merged block base addresses
332    unsigned int companion_base; 
333    unsigned int merged_base; 
334
335    if ( (base & size) == 0 )   // the released block is aligned on (2*size)
336    {
337        companion_base  = base + size;
338        merged_base     = base;
339    }
340    else
341    {
342        companion_base  = base - size;
343        merged_base     = base - size;
344    }
345
346    // scan all blocks in free[size_index]
347    // the iter & prev variables are actually addresses
348    unsigned int  found = 0;
349    unsigned int  iter  = heap->free[size_index];
350    unsigned int  prev  = (unsigned int)&heap->free[size_index];
351    while ( iter ) 
352    {
353        if ( iter == companion_base ) 
354        {
355            found = 1;
356            break;
357        }
358        prev = iter;
359        iter = *(unsigned int*)iter;
360    }
361
362    if ( found == 0 )  // Companion not found => push in free[size_index] 
363    {
364        *(unsigned int*)base   = heap->free[size_index];
365        heap->free[size_index] = base;
366    }
367    else               // Companion found : merge
368    {
369        // evict the searched block from free[size_index]
370        *(unsigned int*)prev = *(unsigned int*)iter;
371
372        // call the update_free() function for free[size_index+1]
373        update_free_array( heap, merged_base , size_index+1 );
374    }
375}
376
377//////////////////////
378void free( void* ptr )
379{
380    // get the cluster coordinate from ptr value
381    unsigned int x;
382    unsigned int y;
383    giet_get_xy( ptr, &x, &y );
384
385#if GIET_DEBUG_USER_MALLOC
386giet_tty_printf("\n[DEBUG USER_MALLOC] Free for vaddr = %x / x = %d / y = %d\n",
387                 (unsigned int)ptr, x, y );
388#endif
389
390    // check ptr value
391    unsigned int base = (unsigned int)ptr;
392    if ( (base < heap[x][y].heap_base) || 
393         (base >= (heap[x][y].heap_base + heap[x][y].heap_size)) )
394    {
395        giet_exit("ERROR in free() : illegal pointer for released block");
396    }
397 
398    // get the lock protecting heap[x][y]
399    lock_acquire( &heap[x][y].lock );
400
401    // compute released block index in alloc[] array
402    unsigned index = (base - heap[x][y].heap_base ) / MIN_BLOCK_SIZE;
403 
404    // get the released block size_index
405    unsigned char* pchar      = (unsigned char*)(heap[x][y].alloc_base + index);
406    unsigned int   size_index = (unsigned int)*pchar;
407
408    // check block allocation
409    if ( size_index == 0 )
410    {
411        lock_release( &heap[x][y].lock );
412        giet_exit("\nERROR in free() : released block not allocated ???\n");
413    }
414
415    // check released block alignment
416    if ( base % (1 << size_index) )
417    {
418        giet_exit("\nERROR in free() : released block not aligned\n");
419    }
420
421    // call the recursive function update_free_array()
422    update_free_array( &heap[x][y], base, size_index ); 
423
424    // release the lock
425    lock_release( &heap[x][y].lock );
426
427#if GIET_DEBUG_USER_MALLOC
428display_free_array(x,y);
429#endif
430
431} // end free()
432
433// Local Variables:
434// tab-width: 4
435// c-basic-offset: 4
436// c-file-offsets:((innamespace . 0)(inline-open . 0))
437// indent-tabs-mode: nil
438// End:
439// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
440
441
442
Note: See TracBrowser for help on using the repository browser.