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

Last change on this file since 700 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
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"
[468]10#include "giet_config.h"
[258]11
[382]12// Global variables defining the heap descriptors array (one heap per cluster)
[588]13giet_heap_t     heap[X_SIZE][Y_SIZE];
[325]14
[382]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
[394]49////////////////////////////////////////
50void display_free_array( unsigned int x,
51                         unsigned int y )
52{
[588]53    unsigned int next;
54    unsigned int id;
55    unsigned int iter;
[394]56
[680]57    giet_tty_printf("\nUser Heap[%d][%d] base = %x / size = %x\n", x , y , 
[588]58                   heap[x][y].heap_base, heap[x][y].heap_size );
[680]59    for ( id = 0 ; id < 32 ; id++ )
[588]60    { 
61        next = heap[x][y].free[id];
[680]62        giet_tty_printf(" - free[%d] = " , id );
[588]63        iter = 0;
64        while ( next != 0 )
65        {
[680]66            giet_tty_printf("%x | ", next );
[588]67            next = (*(unsigned int*)next);
68            iter++;
69        }
[680]70        giet_tty_printf("0\n");
[588]71    }
72}  // end display_free_array()
73
74
75
[382]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]
[258]83
[382]84    unsigned int alloc_base;       // alloc[] array base
85    unsigned int alloc_size;       // alloc[] array size
[588]86    unsigned int alloc_index;      // size_index in alloc[array]
[258]87
[382]88    unsigned int index;            // iterator
[258]89
[382]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 );
[258]93
[468]94#if GIET_DEBUG_USER_MALLOC
[680]95giet_tty_printf("\n[DEBUG USER_MALLOC] Starting Heap[%d][%d] initialisation /"
[468]96                " base = %x / size = %x\n", x, y, heap_base, heap_size );
97#endif
98
[382]99    // checking heap segment constraints
100    if ( heap_size == 0 )                                    // heap segment exist
101    {
102        giet_exit("ERROR in malloc() : heap not found \n");
[258]103    }
[382]104    if ( heap_size != (1<<heap_index) )                      // heap size power of 2
[258]105    {
[382]106        giet_exit("ERROR in malloc() : heap size must be power of 2\n");
[258]107    }
[382]108    if ( heap_base % heap_size )                             // heap segment aligned
[258]109    {
[382]110        giet_exit("ERROR in malloc() : heap segment must be aligned\n");
[258]111    }
112
[390]113    // compute size of block containin alloc[] array
[382]114    alloc_size = heap_size / MIN_BLOCK_SIZE;
[390]115    if ( alloc_size < MIN_BLOCK_SIZE) alloc_size = MIN_BLOCK_SIZE;
[258]116
[382]117    // get index for the corresponding block
118    alloc_index = GET_SIZE_INDEX( alloc_size );
[258]119
[382]120    // compute alloc[] array base address
121    alloc_base = heap_base + heap_size - alloc_size;
[258]122
[382]123    // reset the free[] array
124    for ( index = 0 ; index < 32 ; index++ )
125    {
126        heap[x][y].free[index] = 0;
[258]127    }
128
[588]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 
[382]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;
[390]139    for ( index = heap_index-1 ; index >= alloc_index ; index-- )
[382]140    {
141        heap[x][y].free[index] = base;
142        ptr = (unsigned int*)base;
143        *ptr = 0;
144        base = base + (1<<index);
[258]145    }
146
[382]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;
[258]154
[468]155    lock_init( &heap[x][y].lock );
[258]156
[468]157#if GIET_DEBUG_USER_MALLOC
[680]158giet_tty_printf("\n[DEBUG USER_MALLOC] Completing Heap[%d][%d] initialisation\n", x, y );
[394]159display_free_array(x,y);
[382]160#endif
161               
162}  // end heap_init()
[258]163
[382]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;
[258]178    }
[382]179    else            // non terminal case : lower half block must be split again
180    {                               
181        return split_block( heap, vaddr, searched_index-1, requested_index );
[258]182    }
[382]183} // end split_block()
[258]184
[382]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
[258]192    {
[382]193        return 0;
[258]194    }
[382]195    else                            // search a block in free[searched_index]
[258]196    {
[382]197        unsigned int vaddr = heap->free[searched_index];
198        if ( vaddr == 0 )     // block not found : search in free[searched_index+1]
[258]199        {
[382]200            return get_block( heap, searched_index+1, requested_index );
[258]201        }
[382]202        else                // block found : pop it from free[searched_index]
[258]203        {
[382]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;
[258]212            }
[382]213            else                                      // split is required
214            {
215                return split_block( heap, vaddr, searched_index, requested_index );
[258]216            }
[382]217        } 
[258]218    }
[382]219} // end get_block()
[258]220
[382]221////////////////////////////////////////
222void * remote_malloc( unsigned int size,
223                      unsigned int x,
224                      unsigned int y ) 
[258]225{
[397]226
[468]227#if GIET_DEBUG_USER_MALLOC
[680]228giet_tty_printf("\n[DEBUG USER_MALLOC] request for Heap[%d][%d] / size = %x\n", 
[397]229                 x, y, size );
230#endif
231
[382]232    // checking arguments
233    if (size == 0) 
[258]234    {
[588]235        giet_exit("\nERROR in remote_malloc() : requested size = 0 \n");
[258]236    }
[382]237    if ( x >= X_SIZE )
[258]238    {
[588]239        giet_exit("\nERROR in remote_malloc() : x coordinate too large\n");
[258]240    }
[382]241    if ( y >= Y_SIZE )
[258]242    {
[588]243        giet_exit("\nERROR in remote_malloc() : y coordinate too large\n");
[258]244    }
245
[541]246    // checking initialization
[382]247    if ( heap[x][y].init != HEAP_INITIALIZED )
[258]248    {
[588]249        giet_exit("\nERROR in remote_malloc() : heap not initialized\n");
[258]250    }
251
[390]252    // normalize size
253    if ( size < MIN_BLOCK_SIZE ) size = MIN_BLOCK_SIZE;
254
[382]255    // compute requested_index for the free[] array
256    unsigned int requested_index = GET_SIZE_INDEX( size );
[258]257
[394]258    // take the lock protecting access to heap[x][y]
[382]259    lock_acquire( &heap[x][y].lock );
[258]260
[382]261    // call the recursive function get_block
262    unsigned int base = get_block( &heap[x][y], 
263                                   requested_index, 
264                                   requested_index );
[258]265
[588]266    // check block found
267    if ( base == 0 )
[390]268    {
[588]269        lock_release( &heap[x][y].lock );
270        giet_exit("\nERROR in remote_malloc() : no more space\n");
[390]271    }
[258]272
[588]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
[382]287    // release the lock
288    lock_release( &heap[x][y].lock );
289 
[468]290#if GIET_DEBUG_USER_MALLOC
[680]291giet_tty_printf("\n[DEBUG USER_MALLOC] allocated block from heap[%d][%d] : "
[588]292                "base = %x / size = %x\n", x , y , base , size );
[394]293display_free_array(x,y);
294#endif
295
[382]296    return (void*)base;
[258]297
[382]298} // end remote_malloc()
[258]299
300
[382]301//////////////////////////////////
302void * malloc( unsigned int size )
303{
[431]304    // get cluster coordinates
305    unsigned int    x;
306    unsigned int    y;
307    unsigned int    lpid;
308    giet_proc_xyp( &x, &y, &lpid );
[258]309
[382]310    return remote_malloc( size, x, y );
311} 
[258]312
[394]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].
[258]326
[394]327
328    // compute released block size
329    unsigned int size = 1<<size_index;
330
[588]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)
[394]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];
[588]351    while ( iter ) 
[394]352    {
353        if ( iter == companion_base ) 
354        {
355            found = 1;
356            break;
357        }
[588]358        prev = iter;
[394]359        iter = *(unsigned int*)iter;
360    }
361
[588]362    if ( found == 0 )  // Companion not found => push in free[size_index] 
[394]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
[382]377//////////////////////
378void free( void* ptr )
379{
[394]380    // get the cluster coordinate from ptr value
[390]381    unsigned int x;
382    unsigned int y;
383    giet_get_xy( ptr, &x, &y );
384
[468]385#if GIET_DEBUG_USER_MALLOC
[680]386giet_tty_printf("\n[DEBUG USER_MALLOC] Free for vaddr = %x / x = %d / y = %d\n",
[397]387                 (unsigned int)ptr, x, y );
388#endif
389
[394]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    }
[390]397 
[588]398    // get the lock protecting heap[x][y]
399    lock_acquire( &heap[x][y].lock );
400
[394]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;
[390]407
[588]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
[394]415    // check released block alignment
416    if ( base % (1 << size_index) )
417    {
[588]418        giet_exit("\nERROR in free() : released block not aligned\n");
[394]419    }
[258]420
[394]421    // call the recursive function update_free_array()
422    update_free_array( &heap[x][y], base, size_index ); 
[258]423
[394]424    // release the lock
425    lock_release( &heap[x][y].lock );
[258]426
[468]427#if GIET_DEBUG_USER_MALLOC
[394]428display_free_array(x,y);
429#endif
[258]430
[394]431} // end free()
432
[258]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.