source: soft/giet_vm/giet_common/kernel_malloc.c @ 521

Last change on this file since 521 was 514, checked in by alain, 10 years ago

Remove vobj object from mapping_info.

  • Property svn:executable set to *
File size: 14.8 KB
RevLine 
[466]1////////////////////////////////////////////////////////////////////////////////
2// File     : kernel_malloc.c
3// Date     : 05/12/2014
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6////////////////////////////////////////////////////////////////////////////////
7//   Implementation note:
[495]8// - As this code is used to implement the SQT lock ptotecting TTY0,
[466]9//   all functions here use the kernel _nolock_printf() function.
10// - It must exist one vseg with the HEAP type in each cluster. The length
11//   must be a power of 2, and the base address must be aligned.
12// - All allocated blocks have a size that is a power of 2, larger or equal
13//   to MIN_BLOCK_SIZE (typically 64 bytes), and are aligned.
14// - All free blocks are pre-classed in 32 linked lists of free blocks, where
15//   all blocks in the same list have the same size.
16// - The NEXT pointer implementing those linked lists is written
17//   in the 4 first bytes of the block itself, using the unsigned int type.
18// - The pointers on the first free block for each size are stored in an
19//   array of pointers free[32] in the heap[x][y) structure itself.
20// - Each kernel_heap[x][y] structure is protected by a specific
21//   queuing spin-lock.
22// - The block size required can be any value, but the allocated block size
23//   is the smallest power of 2 value larger or equal to the requested size.
24// - It pop the linked list of free blocks corresponding to size,
25//   and returns the block B if the list[size] is not empty.
26// - If the list[size] is empty, it pop the list[size * 2].
27//   If a block B' is found, it break this block in 2 B/2 blocks, returns
28//   the first B/2 block and push the other B/2 block into list[size].
29// - If the list[size * 2] is empty, it pop the list[size * 4].
30//   If a block B is found, it break this block in 3 blocks B/4, B/4 and B/2,
31//   returns the first B/4 block, push the other blocks B/4 and B/2 into
32//   the proper lists. etc...
33////////////////////////////////////////////////////////////////////////////////
34
35#include "giet_config.h"
36#include "hard_config.h"
37#include "mapping_info.h"
38#include "kernel_malloc.h"
[495]39#include "kernel_locks.h"
[466]40#include "tty0.h"
41#include "utils.h"
42
43///////////////////////////////////////////////////////////////////////////////
44// Global variables defining the heap descriptors array (one heap per cluster)
45///////////////////////////////////////////////////////////////////////////////
46
[495]47__attribute__((section(".kdata")))
48kernel_heap_t kernel_heap[X_SIZE][Y_SIZE];
[466]49
50///////////////////////////////////////////////////////////////////////////////
51// Macro returning the smallest power of 2 larger or equal to size value
52///////////////////////////////////////////////////////////////////////////////
53#define GET_SIZE_INDEX(size)                (size <= 0x00000001) ? 0  :\
54                                            (size <= 0x00000002) ? 1  :\
55                                            (size <= 0x00000004) ? 2  :\
56                                            (size <= 0x00000008) ? 3  :\
57                                            (size <= 0x00000010) ? 4  :\
58                                            (size <= 0x00000020) ? 5  :\
59                                            (size <= 0x00000040) ? 6  :\
60                                            (size <= 0x00000080) ? 7  :\
61                                            (size <= 0x00000100) ? 8  :\
62                                            (size <= 0x00000200) ? 9  :\
63                                            (size <= 0x00000400) ? 10 :\
64                                            (size <= 0x00000800) ? 11 :\
65                                            (size <= 0x00001000) ? 12 :\
66                                            (size <= 0x00002000) ? 13 :\
67                                            (size <= 0x00004000) ? 14 :\
68                                            (size <= 0x00008000) ? 15 :\
69                                            (size <= 0x00010000) ? 16 :\
70                                            (size <= 0x00020000) ? 17 :\
71                                            (size <= 0x00040000) ? 18 :\
72                                            (size <= 0x00080000) ? 19 :\
73                                            (size <= 0x00100000) ? 20 :\
74                                            (size <= 0x00200000) ? 21 :\
75                                            (size <= 0x00400000) ? 22 :\
76                                            (size <= 0x00800000) ? 23 :\
77                                            (size <= 0x01000000) ? 24 :\
78                                            (size <= 0x02000000) ? 25 :\
79                                            (size <= 0x04000000) ? 26 :\
80                                            (size <= 0x08000000) ? 27 :\
81                                            (size <= 0x10000000) ? 28 :\
82                                            (size <= 0x20000000) ? 29 :\
83                                            (size <= 0x40000000) ? 30 :\
84                                            (size <= 0x80000000) ? 31 :\
85                                                                   32
[495]86
[466]87#if GIET_DEBUG_SYS_MALLOC
88////////////////////////////////////////////////
89static void _display_free_array( unsigned int x,
90                                 unsigned int y )
91{
92    _nolock_printf(" Kernel Heap[%d][%d]\n"
93                   " - heap_base   = %x\n"
94                   " - heap_size   = %x\n"
95                   " - free[0]     = %x\n"
96                   " - free[1]     = %x\n"
97                   " - free[2]     = %x\n"
98                   " - free[3]     = %x\n"
99                   " - free[4]     = %x\n"
100                   " - free[5]     = %x\n"
101                   " - free[6]     = %x\n"
102                   " - free[7]     = %x\n"
103                   " - free[8]     = %x\n"
104                   " - free[9]     = %x\n"
105                   " - free[10]    = %x\n"
106                   " - free[11]    = %x\n"
107                   " - free[12]    = %x\n"
108                   " - free[13]    = %x\n"
109                   " - free[14]    = %x\n"
110                   " - free[15]    = %x\n"
111                   " - free[16]    = %x\n"
112                   " - free[17]    = %x\n"
113                   " - free[18]    = %x\n"
114                   " - free[19]    = %x\n"
115                   " - free[20]    = %x\n"
116                   " - free[21]    = %x\n"
117                   " - free[22]    = %x\n"
118                   " - free[23]    = %x\n",
[495]119                   x, y, 
[466]120                   kernel_heap[x][y].heap_base, kernel_heap[x][y].heap_size, 
121                   kernel_heap[x][y].free[0] , kernel_heap[x][y].free[1], 
122                   kernel_heap[x][y].free[2] , kernel_heap[x][y].free[3],
123                   kernel_heap[x][y].free[4] , kernel_heap[x][y].free[5],
124                   kernel_heap[x][y].free[6] , kernel_heap[x][y].free[7],
125                   kernel_heap[x][y].free[8] , kernel_heap[x][y].free[9],
126                   kernel_heap[x][y].free[10], kernel_heap[x][y].free[11],
127                   kernel_heap[x][y].free[12], kernel_heap[x][y].free[13],
128                   kernel_heap[x][y].free[14], kernel_heap[x][y].free[15],
129                   kernel_heap[x][y].free[16], kernel_heap[x][y].free[17],
130                   kernel_heap[x][y].free[18], kernel_heap[x][y].free[19],
131                   kernel_heap[x][y].free[20], kernel_heap[x][y].free[21],
132                   kernel_heap[x][y].free[22], kernel_heap[x][y].free[23]);
133}  // end display_free array()
134#endif
135
136
137
138
[495]139/////////////////////////////////////////////////////
140unsigned int _get_heap_info( unsigned int* heap_base,
141                             unsigned int* heap_size,
142                             unsigned int  x,
143                             unsigned int  y )
[466]144{
145    mapping_header_t  * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
146    mapping_vseg_t    * vsegs    = _get_vseg_base(header);
147    mapping_pseg_t    * psegs    = _get_pseg_base(header);
148    mapping_cluster_t * clusters = _get_cluster_base(header);
149
150    unsigned int vseg_id;
151    unsigned int pseg_id;
152    unsigned int cluster_id;
153
154    // checking coordinates
155    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
156    {
[495]157        _nolock_printf("\n[GIET ERROR] _get_heap_info()"
158                       " illegal (%d,%d) coordinates\n", x , y );
[466]159        _exit();
160    }
161
162    // scan all global vsegs
163    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
164    {
165        pseg_id    = vsegs[vseg_id].psegid;
166        cluster_id = psegs[pseg_id].clusterid;
[514]167        if ( (vsegs[vseg_id].type == VSEG_TYPE_HEAP) &&
[466]168             (clusters[cluster_id].x == x) && 
169             (clusters[cluster_id].y == y) )
170        {
171            *heap_base = vsegs[vseg_id].vbase;
[514]172            *heap_size = vsegs[vseg_id].length;
[495]173            return 0;
[466]174        }
175    }
176
[495]177    return 1;
[466]178} // end _get_heap_info()
179
180
181
182/////////////////
183void _heap_init()
184{
185    unsigned int heap_base;
186    unsigned int heap_size;
187    unsigned int heap_index;
188    unsigned int index;
189    unsigned int x;
190    unsigned int y;
[495]191    unsigned int ko;
[466]192
193    for ( x = 0 ; x < X_SIZE ; x++ )
194    {
195        for ( y = 0 ; y < Y_SIZE ; y++ )
196        {
197            // get heap_base, heap size, and heap index
[495]198            ko = _get_heap_info( &heap_base, &heap_size, x, y );
199       
200            if ( ko )  // no kernel heap found in cluster[x][y]
[466]201            {
[495]202                // initialise kernel_heap[x][y] descriptor
203                kernel_heap[x][y].heap_base  = 0;
204                kernel_heap[x][y].heap_size  = 0;
205                _spin_lock_init( &kernel_heap[x][y].lock );
[466]206            }
[495]207            else       // kernel heap found in cluster[x][y]
[466]208            {
[495]209                heap_index = GET_SIZE_INDEX( heap_size );
[466]210
[495]211                // check heap[x][y] constraints
212                if ( heap_size != (1<<heap_index) )
213                {
214                    _nolock_printf("\n[GIET ERROR] in _heap_init()"
215                                   " kernel_heap[‰d,‰d] not power of 2\n", x , y );
216                    _exit();
217                }
218                if ( heap_base % heap_size ) 
219                {
220                    _nolock_printf("\n[GIET ERROR] in _heap_init()"
221                                   " kernel_heap[‰d,‰d] not aligned\n", x , y );
222                    _exit();
223                }
[466]224
[495]225                // initialise the free[] array
226                for ( index = 0 ; index < 32 ; index++ ) 
227                {
228                    if (index == heap_index) kernel_heap[x][y].free[index] = heap_base;
229                    else                     kernel_heap[x][y].free[index] = 0;
230                }
[466]231
[495]232                // initialise kernel_heap[x][y] descriptor
233                kernel_heap[x][y].heap_base  = heap_base;
234                kernel_heap[x][y].heap_size  = heap_size;
235                _spin_lock_init( &kernel_heap[x][y].lock );
236            }
[466]237
238#if GIET_DEBUG_SYS_MALLOC
[495]239_nolock_printf("\n[DEBUG KERNEL_MALLOC] Completing kernel_heap[%d][%d]"
240               " initialisation\n", x, y );
[466]241_display_free_array(x,y);
242#endif
243               
244        }
245    }
246}  // end _heap_init()
247
248
249
250//////////////////////////////////////////////
[495]251unsigned int _split_block( kernel_heap_t* heap,
252                           unsigned int   vaddr, 
253                           unsigned int   searched_index,
254                           unsigned int   requested_index )
[466]255{
256    // push the upper half block into free[searched_index-1]
257    unsigned int* new            = (unsigned int*)(vaddr + (1<<(searched_index-1)));
258    *new                         = heap->free[searched_index-1]; 
259    heap->free[searched_index-1] = (unsigned int)new;
260       
[495]261    if ( searched_index == requested_index + 1 )  //  return lower half block
[466]262    {
263        return vaddr;
264    }
265    else            // non terminal case : lower half block must be split again
266    {                               
[495]267        return _split_block( heap, vaddr, searched_index-1, requested_index );
[466]268    }
[495]269} // end _split_block()
[466]270
271
272
273/////////////////////////////////////////////
[495]274unsigned int _get_block( kernel_heap_t* heap,
275                         unsigned int   searched_index,
276                         unsigned int   requested_index )
[466]277{
278    // test terminal case
279    if ( (1<<searched_index) > heap->heap_size )  // failure : return a NULL value
280    {
281        return 0;
282    }
283    else                            // search a block in free[searched_index]
284    {
285        unsigned int vaddr = heap->free[searched_index];
286        if ( vaddr == 0 )     // block not found : search in free[searched_index+1]
287        {
[495]288            return _get_block( heap, searched_index+1, requested_index );
[466]289        }
290        else                // block found : pop it from free[searched_index]
291        {
292            // pop the block from free[searched_index]
293            unsigned int next = *((unsigned int*)vaddr); 
294            heap->free[searched_index] = next;
295           
296            // test if the block must be split
297            if ( searched_index == requested_index )  // no split required
298            {
299                return vaddr;
300            }
301            else                                      // split is required
302            {
[495]303                return _split_block( heap, vaddr, searched_index, requested_index );
[466]304            }
305        } 
306    }
[495]307} // end _get_block()
[466]308
309
310
311////////////////////////////////////////
312void* _remote_malloc( unsigned int size,
313                      unsigned int x,
314                      unsigned int y ) 
315{
316    // checking arguments
[495]317    if ( x >= X_SIZE )
[466]318    {
[495]319        _nolock_printf("\n[GIET ERROR] _remote_malloc() : x coordinate too large\n");
[466]320        _exit();
321    }
[495]322    if ( y >= Y_SIZE )
[466]323    {
[495]324        _nolock_printf("\n[GIET ERROR] _remote_malloc() : y coordinate too large\n");
[466]325        _exit();
326    }
[495]327    if ( kernel_heap[x][y].heap_size == 0 )
[466]328    {
[495]329        _nolock_printf("\n[GIET ERROR] _remote_malloc() : No heap[%d][%d]\n", x, y );
[466]330        _exit();
[495]331     
[466]332    }
333
334    // normalize size
335    if ( size < MIN_BLOCK_SIZE ) size = MIN_BLOCK_SIZE;
336
337    // compute requested_index for the free[] array
338    unsigned int requested_index = GET_SIZE_INDEX( size );
339
340    // take the lock
341    _spin_lock_acquire( &kernel_heap[x][y].lock );
342
343    // call the recursive function get_block
[495]344    unsigned int base = _get_block( &kernel_heap[x][y], 
345                                    requested_index, 
346                                    requested_index );
[466]347    // release the lock
348    _spin_lock_release( &kernel_heap[x][y].lock );
349 
[495]350    if ( base == 0 )
351    {
352        _nolock_printf("\n[GIET ERROR] _remote_malloc() : no more space "
353                       "in heap[%d][%d]", x, y );
354    }
355
[466]356#if GIET_DEBUG_SYS_MALLOC
357_nolock_printf("\n[DEBUG KERNEL_MALLOC] malloc vaddr %x from kernel_heap[%d][%d]\n", 
358               base , x , y );
359_display_free_array(x,y);
360#endif
361
362    return (void*)base;
363
[495]364} // end _remote_malloc()
[466]365
366
367
368// Local Variables:
369// tab-width: 4
370// c-basic-offset: 4
371// c-file-offsets:((innamespace . 0)(inline-open . 0))
372// indent-tabs-mode: nil
373// End:
374// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
375
376
377
Note: See TracBrowser for help on using the repository browser.