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

Last change on this file since 495 was 495, checked in by alain, 9 years ago

Introduce quad tree for distributed locks and barriers.

  • Property svn:executable set to *
File size: 14.9 KB
Line 
1////////////////////////////////////////////////////////////////////////////////
2// File     : kernel_malloc.c
3// Date     : 05/12/2014
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6////////////////////////////////////////////////////////////////////////////////
7//   Implementation note:
8// - As this code is used to implement the SQT lock ptotecting TTY0,
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"
39#include "kernel_locks.h"
40#include "tty0.h"
41#include "utils.h"
42
43///////////////////////////////////////////////////////////////////////////////
44// Global variables defining the heap descriptors array (one heap per cluster)
45///////////////////////////////////////////////////////////////////////////////
46
47__attribute__((section(".kdata")))
48kernel_heap_t kernel_heap[X_SIZE][Y_SIZE];
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
86
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",
119                   x, y, 
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
139/////////////////////////////////////////////////////
140unsigned int _get_heap_info( unsigned int* heap_base,
141                             unsigned int* heap_size,
142                             unsigned int  x,
143                             unsigned int  y )
144{
145    mapping_header_t  * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
146    mapping_vseg_t    * vsegs    = _get_vseg_base(header);
147    mapping_vobj_t    * vobjs    = _get_vobj_base(header);
148    mapping_pseg_t    * psegs    = _get_pseg_base(header);
149    mapping_cluster_t * clusters = _get_cluster_base(header);
150
151    unsigned int vseg_id;
152    unsigned int vobj_id;
153    unsigned int pseg_id;
154    unsigned int cluster_id;
155
156    // checking coordinates
157    if ( (x >= X_SIZE) || (y >= Y_SIZE) )
158    {
159        _nolock_printf("\n[GIET ERROR] _get_heap_info()"
160                       " illegal (%d,%d) coordinates\n", x , y );
161        _exit();
162    }
163
164    // scan all global vsegs
165    for ( vseg_id = 0 ; vseg_id < header->globals ; vseg_id++ )
166    {
167        pseg_id    = vsegs[vseg_id].psegid;
168        cluster_id = psegs[pseg_id].clusterid;
169        vobj_id    = vsegs[vseg_id].vobj_offset;
170        if ( (vobjs[vobj_id].type == VOBJ_TYPE_HEAP) &&
171             (clusters[cluster_id].x == x) && 
172             (clusters[cluster_id].y == y) )
173        {
174            *heap_base = vsegs[vseg_id].vbase;
175            *heap_size = vobjs[vobj_id].length;
176            return 0;
177        }
178    }
179
180    return 1;
181} // end _get_heap_info()
182
183
184
185/////////////////
186void _heap_init()
187{
188    unsigned int heap_base;
189    unsigned int heap_size;
190    unsigned int heap_index;
191    unsigned int index;
192    unsigned int x;
193    unsigned int y;
194    unsigned int ko;
195
196    for ( x = 0 ; x < X_SIZE ; x++ )
197    {
198        for ( y = 0 ; y < Y_SIZE ; y++ )
199        {
200            // get heap_base, heap size, and heap index
201            ko = _get_heap_info( &heap_base, &heap_size, x, y );
202       
203            if ( ko )  // no kernel heap found in cluster[x][y]
204            {
205                // initialise kernel_heap[x][y] descriptor
206                kernel_heap[x][y].heap_base  = 0;
207                kernel_heap[x][y].heap_size  = 0;
208                _spin_lock_init( &kernel_heap[x][y].lock );
209            }
210            else       // kernel heap found in cluster[x][y]
211            {
212                heap_index = GET_SIZE_INDEX( heap_size );
213
214                // check heap[x][y] constraints
215                if ( heap_size != (1<<heap_index) )
216                {
217                    _nolock_printf("\n[GIET ERROR] in _heap_init()"
218                                   " kernel_heap[‰d,‰d] not power of 2\n", x , y );
219                    _exit();
220                }
221                if ( heap_base % heap_size ) 
222                {
223                    _nolock_printf("\n[GIET ERROR] in _heap_init()"
224                                   " kernel_heap[‰d,‰d] not aligned\n", x , y );
225                    _exit();
226                }
227
228                // initialise the free[] array
229                for ( index = 0 ; index < 32 ; index++ ) 
230                {
231                    if (index == heap_index) kernel_heap[x][y].free[index] = heap_base;
232                    else                     kernel_heap[x][y].free[index] = 0;
233                }
234
235                // initialise kernel_heap[x][y] descriptor
236                kernel_heap[x][y].heap_base  = heap_base;
237                kernel_heap[x][y].heap_size  = heap_size;
238                _spin_lock_init( &kernel_heap[x][y].lock );
239            }
240
241#if GIET_DEBUG_SYS_MALLOC
242_nolock_printf("\n[DEBUG KERNEL_MALLOC] Completing kernel_heap[%d][%d]"
243               " initialisation\n", x, y );
244_display_free_array(x,y);
245#endif
246               
247        }
248    }
249}  // end _heap_init()
250
251
252
253//////////////////////////////////////////////
254unsigned int _split_block( kernel_heap_t* heap,
255                           unsigned int   vaddr, 
256                           unsigned int   searched_index,
257                           unsigned int   requested_index )
258{
259    // push the upper half block into free[searched_index-1]
260    unsigned int* new            = (unsigned int*)(vaddr + (1<<(searched_index-1)));
261    *new                         = heap->free[searched_index-1]; 
262    heap->free[searched_index-1] = (unsigned int)new;
263       
264    if ( searched_index == requested_index + 1 )  //  return lower half block
265    {
266        return vaddr;
267    }
268    else            // non terminal case : lower half block must be split again
269    {                               
270        return _split_block( heap, vaddr, searched_index-1, requested_index );
271    }
272} // end _split_block()
273
274
275
276/////////////////////////////////////////////
277unsigned int _get_block( kernel_heap_t* heap,
278                         unsigned int   searched_index,
279                         unsigned int   requested_index )
280{
281    // test terminal case
282    if ( (1<<searched_index) > heap->heap_size )  // failure : return a NULL value
283    {
284        return 0;
285    }
286    else                            // search a block in free[searched_index]
287    {
288        unsigned int vaddr = heap->free[searched_index];
289        if ( vaddr == 0 )     // block not found : search in free[searched_index+1]
290        {
291            return _get_block( heap, searched_index+1, requested_index );
292        }
293        else                // block found : pop it from free[searched_index]
294        {
295            // pop the block from free[searched_index]
296            unsigned int next = *((unsigned int*)vaddr); 
297            heap->free[searched_index] = next;
298           
299            // test if the block must be split
300            if ( searched_index == requested_index )  // no split required
301            {
302                return vaddr;
303            }
304            else                                      // split is required
305            {
306                return _split_block( heap, vaddr, searched_index, requested_index );
307            }
308        } 
309    }
310} // end _get_block()
311
312
313
314////////////////////////////////////////
315void* _remote_malloc( unsigned int size,
316                      unsigned int x,
317                      unsigned int y ) 
318{
319    // checking arguments
320    if ( x >= X_SIZE )
321    {
322        _nolock_printf("\n[GIET ERROR] _remote_malloc() : x coordinate too large\n");
323        _exit();
324    }
325    if ( y >= Y_SIZE )
326    {
327        _nolock_printf("\n[GIET ERROR] _remote_malloc() : y coordinate too large\n");
328        _exit();
329    }
330    if ( kernel_heap[x][y].heap_size == 0 )
331    {
332        _nolock_printf("\n[GIET ERROR] _remote_malloc() : No heap[%d][%d]\n", x, y );
333        _exit();
334     
335    }
336
337    // normalize size
338    if ( size < MIN_BLOCK_SIZE ) size = MIN_BLOCK_SIZE;
339
340    // compute requested_index for the free[] array
341    unsigned int requested_index = GET_SIZE_INDEX( size );
342
343    // take the lock
344    _spin_lock_acquire( &kernel_heap[x][y].lock );
345
346    // call the recursive function get_block
347    unsigned int base = _get_block( &kernel_heap[x][y], 
348                                    requested_index, 
349                                    requested_index );
350    // release the lock
351    _spin_lock_release( &kernel_heap[x][y].lock );
352 
353    if ( base == 0 )
354    {
355        _nolock_printf("\n[GIET ERROR] _remote_malloc() : no more space "
356                       "in heap[%d][%d]", x, y );
357    }
358
359#if GIET_DEBUG_SYS_MALLOC
360_nolock_printf("\n[DEBUG KERNEL_MALLOC] malloc vaddr %x from kernel_heap[%d][%d]\n", 
361               base , x , y );
362_display_free_array(x,y);
363#endif
364
365    return (void*)base;
366
367} // end _remote_malloc()
368
369
370
371// Local Variables:
372// tab-width: 4
373// c-basic-offset: 4
374// c-file-offsets:((innamespace . 0)(inline-open . 0))
375// indent-tabs-mode: nil
376// End:
377// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
378
379
380
Note: See TracBrowser for help on using the repository browser.