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

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