source: trunk/libs/libalmosmkh/almosmkh.c @ 580

Last change on this file since 580 was 580, checked in by alain, 6 years ago

1) Register the kernel process in the cluster manager local list.
2) Introduce a new service in idbg : display the set of busylocks taken by a given thread.

File size: 29.3 KB
Line 
1/*
2 * almosmkh.c - User level ALMOS-MKH specific library implementation.
3 *
4 * Author     Alain Greiner (2016,2017,2018)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <almosmkh.h>
25#include <hal_user.h>
26#include <hal_shared_types.h>
27#include <syscalls_numbers.h>
28#include <string.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <mman.h>
33
34#define  MALLOC_DEBUG    0
35 
36/////////////     Non standard system calls    /////////////////////////////////
37
38//////////////////////////
39int fg( unsigned int pid )
40{
41    return hal_user_syscall( SYS_FG,
42                             (reg_t)pid, 0, 0, 0 );
43}
44
45//////////////////////////////
46int is_fg( unsigned int   pid,
47           unsigned int * owner )
48{
49    return hal_user_syscall( SYS_IS_FG,
50                             (reg_t)pid,
51                             (reg_t)owner, 0, 0 );
52}
53
54//////////////////////////////////////
55int get_config( unsigned int * x_size,
56                unsigned int * y_size,
57                unsigned int * ncores )
58{
59    return hal_user_syscall( SYS_GET_CONFIG,
60                             (reg_t)x_size,
61                             (reg_t)y_size,
62                             (reg_t)ncores, 0 );
63}
64
65/////////////////////////////////
66int get_core( unsigned int * cxy,
67              unsigned int * lid )
68{
69    return hal_user_syscall( SYS_GET_CORE,
70                             (reg_t)cxy,
71                             (reg_t)lid, 0, 0 );
72}
73
74///////////////////////////////////////////
75int get_cycle( unsigned long long * cycle )
76{
77    return hal_user_syscall( SYS_GET_CYCLE,
78                             (reg_t)cycle, 0, 0, 0 );
79}
80
81/////////////////////////////////
82int utls( unsigned int operation,
83          unsigned int value )
84{
85    return hal_user_syscall( SYS_UTLS,
86                             (reg_t)operation,
87                             (reg_t)value, 0, 0 );
88}
89
90///////////////////////////////
91unsigned int get_uint32( void )
92{
93    unsigned int  i;
94    int           c;    // ASCII character value
95
96    unsigned char buf[32];
97
98    unsigned int  save          = 0;
99    unsigned int  value         = 0;
100    unsigned int  done          = 0;
101    unsigned int  overflow      = 0;
102    unsigned int  length        = 0;
103
104    // get characters
105    while (done == 0) 
106    {
107        // read one character
108        c = getchar();
109
110        // analyse this character
111        if ( ((c > 0x2F) && (c < 0x3A)) ||                      // 0 to 9
112             ((c > 0x40) && (c < 0x47)) ||                      // A to F
113             ((c > 0x60) && (c < 0x67)) ||                      // a to f
114             (((c == 0x58) || (c == 0x78)) && (length == 1)) )  // X or x
115        {
116            putchar( c );                       // echo
117            if ( c > 0x60 )  c = c - 0x20;      // to upper case
118            buf[length] = (unsigned char)c;
119            length++;                     
120        }
121        else if (c == 0x0A)                                     // LF character
122        {
123            done = 1;
124        }
125        else if ( (c == 0x7F) ||                                // DEL character
126                  (c == 0x08) )                                 // BS  character
127        {
128            if ( length > 0 ) 
129            {
130                length--;         
131                printf("\b \b");                // BS /  / BS
132            }
133        }
134        else if ( c == 0 )                                      // EOF character
135        {
136            return -1;
137        }
138
139        // test buffer overflow
140        if ( length >= 32 ) 
141        {
142            overflow = 1;
143            done     = 1;
144        }
145    }  // end while characters
146
147    // string to int conversion with overflow detection
148    if ( overflow == 0 )
149    {
150        // test (decimal / hexa)
151        if( (buf[0] == 0x30) && (buf[1] == 0x58) )     // hexadecimal input
152        {
153            for (i = 2; (i < length) && (overflow == 0) ; i++)
154            {
155                if( buf[i] < 0x40 ) value = (value << 4) + (buf[i] - 0x30);
156                else                value = (value << 4) + (buf[i] - 0x37);
157                if (value < save) overflow = 1; 
158                save = value;
159            }
160        }
161        else                                           // decimal input
162        {
163            for (i = 0; (i < length) && (overflow == 0) ; i++) 
164            {
165                value = (value * 10) + (buf[i] - 0x30);
166                if (value < save) overflow = 1; 
167                save = value;
168            }
169        }
170    } 
171
172    // final evaluation
173    if ( overflow == 0 )
174    {
175        // return value
176        return value;
177    }
178    else
179    {
180        // cancel all echo characters
181        for (i = 0; i < length ; i++) 
182        {
183            printf("\b \b");                  // BS /  / BS
184        }
185
186        // echo character '0'
187        putchar( '0' );
188
189        // return 0 value
190        return 0;
191    }
192}  // end get_uint32()
193
194
195///////////////    non standard debug functions    //////////////////////////
196
197////////////////////////////////////
198void display_string( char * string )
199{
200    hal_user_syscall( SYS_DISPLAY,
201                      DISPLAY_STRING,
202                      (reg_t)string, 0, 0 );
203}
204
205/////////////////////////////////////////////////////
206int display_vmm( unsigned int cxy, unsigned int pid )
207{
208    return hal_user_syscall( SYS_DISPLAY,
209                             DISPLAY_VMM,
210                             (reg_t)cxy,
211                             (reg_t)pid, 0 );
212} 
213
214////////////////////////////////
215int display_sched( unsigned int cxy,
216                   unsigned int lid )
217{
218    return hal_user_syscall( SYS_DISPLAY,
219                             DISPLAY_SCHED,
220                             (reg_t)cxy,
221                             (reg_t)lid, 0 );
222} 
223
224/////////////////////////////////////////////////
225int display_cluster_processes( unsigned int cxy )
226{
227    return hal_user_syscall( SYS_DISPLAY,
228                             DISPLAY_CLUSTER_PROCESSES,
229                             (reg_t)cxy, 0, 0 );
230} 
231
232////////////////////////////////////////
233int display_busylocks( unsigned int pid,
234                       unsigned int trdid )
235{
236    return hal_user_syscall( SYS_DISPLAY,
237                             DISPLAY_BUSYLOCKS,
238                             (reg_t)pid,
239                             (reg_t)trdid, 0 );
240} 
241
242/////////////////////////
243int display_chdev( void )
244{
245    return hal_user_syscall( SYS_DISPLAY,
246                             DISPLAY_CHDEV, 0, 0, 0 );
247} 
248
249///////////////////////
250int display_vfs( void )
251{
252    return hal_user_syscall( SYS_DISPLAY,
253                             DISPLAY_VFS, 0, 0, 0 );
254} 
255
256////////////////////////////////////////////////
257int display_txt_processes( unsigned int txt_id )
258{
259    return hal_user_syscall( SYS_DISPLAY,
260                             DISPLAY_TXT_PROCESSES,
261                             (reg_t)txt_id, 0, 0 );
262} 
263
264///////////////////////////////
265int trace( unsigned int active,
266           unsigned int cxy, 
267           unsigned int lid )
268{
269    return hal_user_syscall( SYS_TRACE,
270                             (reg_t)active,
271                             (reg_t)cxy,
272                             (reg_t)lid, 0 );
273}
274
275////////////////////////
276int display_dqdt( void )
277{
278    return hal_user_syscall( SYS_DISPLAY,
279                             DISPLAY_DQDT, 0, 0, 0 );
280} 
281
282/////////////////
283void idbg( void )
284{
285   char          cmd;
286   unsigned int  cxy;
287   unsigned int  lid;
288   unsigned int  txt;
289   unsigned int  pid;
290   unsigned int  trdid;
291   unsigned int  active;
292
293   while( 1 )
294   {
295        printf("\n[idbg] cmd = ");
296        cmd = (char)getchar();
297
298        if( cmd == 'h' )
299        {
300            printf("h\n"
301                   "p : display on TXT0 process descriptors in cluster[cxy]\n"
302                   "s : display on TXT0 scheduler state for core[cxy,lid]\n"
303                   "v : display on TXT0 VMM state for process[cxy,pid]\n"
304                   "t : display on TXT0 process decriptors attached to TXT[tid]\n"
305                   "b : display on TXT0 busylocks taken by thread[pid,trdid]\n"
306                   "y : activate/desactivate trace for core[cxy,lid]\n"
307                   "x : force calling process to exit\n"
308                   "c : resume calling process execution\n"
309                   "h : list supported commands\n");
310        }
311        else if( cmd == 'p' )
312        {
313            printf("p / cxy = ");
314            cxy = get_uint32();
315            display_cluster_processes( cxy );
316        }
317        else if( cmd == 's' )
318        {
319            printf("s / cxy = ");
320            cxy = get_uint32();
321            printf(" / lid = ");
322            lid = get_uint32();
323            display_sched( cxy , lid );
324        }
325        else if( cmd == 'v' )
326        {
327            printf("v / cxy = ");
328            cxy = get_uint32();
329            printf(" / pid = ");
330            pid = get_uint32();
331            display_vmm( cxy , pid );
332        }
333        else if( cmd == 't' )
334        {
335            printf("t / txt_id = ");
336            txt = get_uint32();
337            display_txt_processes( txt );
338        }
339        else if( cmd == 'y' )
340        {
341            printf("y / active = ");
342            active = get_uint32();
343            printf(" / cxy = ");
344            cxy    = get_uint32();
345            printf(" / lid = ");
346            lid    = get_uint32();
347            trace( active , cxy , lid );
348        }
349        else if( cmd == 'b' )
350        {
351            printf("b / pid = ");
352            pid = get_uint32();
353            printf(" / trdid = ");
354            trdid = get_uint32();
355            display_busylocks( pid , trdid );
356        }
357        else if( cmd == 'x' )
358        {
359            printf("x\n");
360            exit( 0 );
361        }
362        else if( cmd == 'c' )
363        {
364            printf("c\n");
365            break;
366        }
367    }
368}  // end idbg()
369
370
371///////////////    non standard malloc functions    //////////////////////////
372
373/////////////////////////////////////////////////////////////////////////////////////////
374// Global variable defining the allocator array (one per cluster)
375// This array (about 16 Kbytes ) will be stored in the data segment
376// of any application linked with this malloc libray.
377/////////////////////////////////////////////////////////////////////////////////////////
378
379malloc_store_t   store[MALLOC_MAX_CLUSTERS];
380
381// Macro returning the smallest power of 2 larger or equal to size value
382
383#define GET_SIZE_INDEX(size)                (size <= 0x00000001) ? 0  :\
384                                            (size <= 0x00000002) ? 1  :\
385                                            (size <= 0x00000004) ? 2  :\
386                                            (size <= 0x00000008) ? 3  :\
387                                            (size <= 0x00000010) ? 4  :\
388                                            (size <= 0x00000020) ? 5  :\
389                                            (size <= 0x00000040) ? 6  :\
390                                            (size <= 0x00000080) ? 7  :\
391                                            (size <= 0x00000100) ? 8  :\
392                                            (size <= 0x00000200) ? 9  :\
393                                            (size <= 0x00000400) ? 10 :\
394                                            (size <= 0x00000800) ? 11 :\
395                                            (size <= 0x00001000) ? 12 :\
396                                            (size <= 0x00002000) ? 13 :\
397                                            (size <= 0x00004000) ? 14 :\
398                                            (size <= 0x00008000) ? 15 :\
399                                            (size <= 0x00010000) ? 16 :\
400                                            (size <= 0x00020000) ? 17 :\
401                                            (size <= 0x00040000) ? 18 :\
402                                            (size <= 0x00080000) ? 19 :\
403                                            (size <= 0x00100000) ? 20 :\
404                                            (size <= 0x00200000) ? 21 :\
405                                            (size <= 0x00400000) ? 22 :\
406                                            (size <= 0x00800000) ? 23 :\
407                                            (size <= 0x01000000) ? 24 :\
408                                            (size <= 0x02000000) ? 25 :\
409                                            (size <= 0x04000000) ? 26 :\
410                                            (size <= 0x08000000) ? 27 :\
411                                            (size <= 0x10000000) ? 28 :\
412                                            (size <= 0x20000000) ? 29 :\
413                                            (size <= 0x40000000) ? 30 :\
414                                            (size <= 0x80000000) ? 31 :\
415                                                                   32
416
417////////////////////////////////////////////////////////////////////////////////////////////
418// This static function display the current state of the allocator in cluster <cxy>.
419////////////////////////////////////////////////////////////////////////////////////////////
420
421#if MALLOC_DEBUG
422static void display_free_array( unsigned int cxy )
423{
424    unsigned int next;
425    unsigned int id;
426    unsigned int iter;
427
428    printf("\n*****   store[%x] base = %x / size = %x\n", 
429    cxy , store[cxy].store_base, store[cxy].store_size );
430    for ( id = 0 ; id < 32 ; id++ )
431    { 
432        next = store[cxy].free[id];
433        printf(" - free[%d] = " , id );
434        iter = 0;
435        while ( next != 0 )
436        {
437            printf("%x | ", next );
438            next = (*(unsigned int*)next);
439            iter++;
440        }
441        printf("0\n");
442    }
443}  // end display_free_array()
444#endif
445
446
447////////////////////////////////////////////////////////////////////i//////////////////////
448// This static function initialises the store in the cluster identified by the <cxy>
449// arguments. It is called by the malloc() or remote_malloc when a specific store(x,y)
450// is accessed for the first time by a remote() or remote_malloc() request.
451// It uses the mmap( MAP_REMOTE ) syscall to allocate a new vseg mapped in cluster (cxy).
452////////////////////////////////////////////////////////////////////i//////////////////////
453// @ cxy        : target cluster identifier (fixed format).
454// @ store_size : store size (bytes).
455// # return without setting the initialized field in store(cxy) if failure.
456////////////////////////////////////////////////////////////////////i//////////////////////
457static void store_init( unsigned int cxy,
458                        unsigned int store_size )
459{
460    unsigned int   store_base;       // store base address
461    unsigned int   free_index;       // index in free[array]
462
463    unsigned int   alloc_base;       // alloc[] array base
464    unsigned int   alloc_size;       // alloc[] array size
465    unsigned int   alloc_index;      // index in alloc[array]
466
467    unsigned int   iter;             // iterator
468
469#if MALLOC_DEBUG
470printf("\n[MALLOC] %s : enter for store[%x] / size = %x\n",
471__FUNCTION__, cxy, store_size );
472#endif
473
474    // get index in free[] array from size
475    free_index = GET_SIZE_INDEX( store_size );
476
477    // check store size power of 2
478    if( store_size != (unsigned int)(1<<free_index) )
479    {
480        printf("\n[ERROR] in %s : store[%x] size not power of 2 / size = %x\n",
481        __FUNCTION__, cxy , store_size );
482        return;
483    }
484
485    // allocate store in virtual space
486    void * vadr = mmap( NULL,                     // MAP_FIXED not supported
487                        store_size,
488                        PROT_READ | PROT_WRITE,
489                        MAP_REMOTE| MAP_SHARED,
490                        cxy,                      // fd is cluster identifier
491                        0 );                      // offset unused
492
493    if( vadr == NULL )
494    {
495        printf("\n[ERROR] in %s : cannot mmap store[%x]\n",
496        __FUNCTION__, cxy );
497        return;
498    }
499
500    store_base = (unsigned int)vadr;
501
502    // check allocated store alignment
503    if( store_base % store_size )
504    {
505        printf("\n[ERROR] in %s : store[%x] not aligned / base = %x / size = %x\n",
506        __FUNCTION__, cxy , store_base , store_size );
507        return;
508    }
509
510#if MALLOC_DEBUG
511printf("\n[MALLOC] %s : mmap done for store[%x] / base = %x\n",
512__FUNCTION__, cxy, store_base );
513#endif
514
515    // compute size of block containing alloc[] array
516    alloc_size = store_size / MALLOC_MIN_BLOCK_SIZE;
517    if ( alloc_size < MALLOC_MIN_BLOCK_SIZE) alloc_size = MALLOC_MIN_BLOCK_SIZE;
518
519    // get index for the corresponding block
520    alloc_index = GET_SIZE_INDEX( alloc_size );
521
522    // compute alloc[] array base address
523    alloc_base = store_base + store_size - alloc_size;
524
525    // reset the free[] array
526    for ( iter = 0 ; iter < 32 ; iter++ )
527    {
528        store[cxy].free[iter] = 0;
529    }
530
531    // DEPRECATED: we don't reset the alloc_base array
532    // because we don't want to allocate the physical memory
533    // when the heap is created  [AG]
534    // memset( (void *)alloc_base , 0 , alloc_size );
535 
536    // split the store into various sizes blocks,
537    // initializes the free[] array and NEXT pointers
538    // base is the block base address
539    unsigned int   base = store_base;
540    unsigned int * ptr;
541    for ( iter = free_index-1 ; iter >= alloc_index ; iter-- )
542    {
543        store[cxy].free[iter] = base;
544        ptr = (unsigned int*)base;
545        *ptr = 0;
546        base = base + (1<<iter);
547    }
548
549    // initialize store mutex
550    if( pthread_mutex_init( &store[cxy].mutex , NULL ) )
551    {
552        printf("\n[ERROR] in %s : cannot initialize mutex for store[%x]\n", 
553        __FUNCTION__, cxy );
554        return;
555    }
556
557    store[cxy].cxy         = cxy;
558    store[cxy].store_base  = store_base;
559    store[cxy].store_size  = store_size;
560    store[cxy].alloc_size  = alloc_size;
561    store[cxy].alloc_base  = alloc_base;
562    store[cxy].initialized = MALLOC_INITIALIZED;
563
564
565#if MALLOC_DEBUG
566printf("\n[MALLOC] %s : completes store[%x] initialisation\n",
567__FUNCTION__, cxy );
568
569display_free_array( cxy );
570#endif
571
572}  // end store_init()
573
574////////////////////////////////////////////////////////
575static unsigned int split_block( malloc_store_t * store,
576                                 unsigned int     vaddr, 
577                                 unsigned int     searched_index,
578                                 unsigned int     requested_index )
579{
580    // push the upper half block into free[searched_index-1]
581    unsigned int* new            = (unsigned int*)(vaddr + (1<<(searched_index-1)));
582    *new                         = store->free[searched_index-1]; 
583    store->free[searched_index-1] = (unsigned int)new;
584       
585    if ( searched_index == requested_index + 1 )  // terminal case: return lower half block
586    {
587        return vaddr;
588    }
589    else            // non terminal case : lower half block must be split again
590    {                               
591        return split_block( store, vaddr, searched_index-1, requested_index );
592    }
593} // end split_block()
594
595//////////////////////////////////////////////////////
596static unsigned int get_block( malloc_store_t * store,
597                               unsigned int     searched_index,
598                               unsigned int     requested_index )
599{
600    // test terminal case
601    if ( (unsigned int)(1<<searched_index) > store->store_size )  // failure
602    {
603        return 0;
604    }
605    else                            // search a block in free[searched_index]
606    {
607        unsigned int vaddr = store->free[searched_index];
608        if ( vaddr == 0 )     // block not found : search in free[searched_index+1]
609        {
610            return get_block( store, searched_index+1, requested_index );
611        }
612        else                // block found : pop it from free[searched_index]
613        {
614            // pop the block from free[searched_index]
615            unsigned int next = *((unsigned int*)vaddr); 
616            store->free[searched_index] = next;
617           
618            // test if the block must be split
619            if ( searched_index == requested_index )  // no split required
620            {
621                return vaddr;
622            }
623            else                                      // split is required
624            {
625                return split_block( store, vaddr, searched_index, requested_index );
626            }
627        } 
628    }
629} // end get_block()
630
631////////////////////////////////////////
632void * remote_malloc( unsigned int size,
633                      unsigned int cxy )
634{
635    int error;
636
637#if MALLOC_DEBUG
638printf("\n[MALLOC] %s : enter for size = %x / cxy = %x\n",
639__FUNCTION__ , size , cxy );
640#endif
641
642    // check arguments
643    if( size == 0 )
644    {
645        printf("\n[ERROR] in %s : requested size = 0 \n",
646        __FUNCTION__ );
647        return NULL;
648    }
649    if( cxy >= MALLOC_MAX_CLUSTERS )
650    {
651        printf("\n[ERROR] in %s : illegal cluster %x\n",
652        __FUNCTION__ , cxy );
653        return NULL;
654    }
655
656    // initializes target store if required
657    if( store[cxy].initialized != MALLOC_INITIALIZED )
658    {
659        store_init( cxy , MALLOC_LOCAL_STORE_SIZE );
660
661        if( store[cxy].initialized != MALLOC_INITIALIZED )
662        {
663            printf("\n[ERROR] in %s : cannot allocate store in cluster %x\n",
664            __FUNCTION__ , cxy );
665            return NULL;
666        }
667    }
668
669    // normalize size
670    if ( size < MALLOC_MIN_BLOCK_SIZE ) size = MALLOC_MIN_BLOCK_SIZE;
671
672    // compute requested_index for the free[] array
673    unsigned int requested_index = GET_SIZE_INDEX( size );
674
675    // take the lock protecting access to store[cxy]
676    error = pthread_mutex_lock( &store[cxy].mutex );
677
678    if( error )
679    {
680        printf("\n[ERROR] in %s : cannot take the lock protecting store in cluster %x\n",
681        __FUNCTION__ , cxy );
682        return NULL;
683    }
684
685    // call the recursive function get_block
686    unsigned int base = get_block( &store[cxy], 
687                                   requested_index, 
688                                   requested_index );
689
690    // check block found
691    if (base == 0)
692    {
693        pthread_mutex_unlock( &store[cxy].mutex );
694        printf("\n[ERROR] in %s : no more space in cluster %x\n",
695        __FUNCTION__ , cxy );
696        return NULL;
697    }
698
699    // compute pointer in alloc[] array
700    unsigned        offset = (base - store[cxy].store_base) / MALLOC_MIN_BLOCK_SIZE;
701    unsigned char * ptr    = (unsigned char*)(store[cxy].alloc_base + offset);
702
703    // DEPRECATED : we cannot check the alloc[] array,
704    // because it has not been initialised by store_init,
705    // to avoid physical memory allocation at heap creation [AG]
706    // if ( *ptr != 0 )
707    // {
708    //    pthread_mutex_unlock( &store[cxy].mutex );
709    //    printf("\n[PANIC] in %s : allocate an already allocated block...\n",
710    //    __FUNCTION__ );
711    //    return NULL;
712    // }
713
714    // update alloc_array
715    *ptr = requested_index;
716
717    // release the lock
718    pthread_mutex_unlock( &store[cxy].mutex );
719 
720#if MALLOC_DEBUG
721printf("\n[MALLOC] %s : exit / base = %x / size = %x / from store[%x]\n",
722__FUNCTION__, base , size , cxy );
723#endif
724
725    return (void*) base;
726
727} // end remote_malloc()
728
729
730
731//////////////////////////////////////////
732void * remote_calloc ( unsigned int count,
733                       unsigned int size,
734                       unsigned int cxy )
735{
736    void * ptr = remote_malloc( count * size , cxy );
737    memset( ptr , 0 , count * size );
738    return ptr;
739}
740
741//////////////////////////////////
742void * remote_realloc( void * ptr,
743                       unsigned int size,
744                       unsigned int cxy )
745{
746    // simple allocation when (ptr == NULL)
747    if( ptr == NULL )
748    {
749        return remote_malloc( size , cxy );
750    }
751
752    // simple free when (size == 0)
753    if( size == 0 )
754    {
755        remote_free( ptr , cxy );
756        return NULL;
757    }
758
759    // check cxy and ptr in general case
760    if( cxy >= MALLOC_MAX_CLUSTERS )
761    {
762        printf("\n[ERROR] in %s : illegal cluster index %x\n",
763        __FUNCTION__ , cxy );
764        return NULL;
765    }
766
767    unsigned int base = (unsigned int)ptr;
768
769    if( (base < store[cxy].store_base) || 
770        (base >= (store[cxy].store_base + store[cxy].store_size)) )
771    {
772        printf("\n[ERROR] in %s : illegal pointer = %x\n",
773        __FUNCTION__, ptr );
774        return NULL;
775    }
776 
777    // compute index in free[] array
778    int index = (base - store[cxy].store_base) / MALLOC_MIN_BLOCK_SIZE;
779
780    // compute old size
781    char        * pchar    = (char *) (store[cxy].alloc_base + index);
782    unsigned int  old_size = (unsigned int)(1 << ((int) *pchar));
783
784    // allocate a new block
785    void * new_ptr = remote_malloc( size , cxy );
786
787    // save old data to new block
788    int min_size = (int)((size < old_size) ? size : old_size);
789    memcpy( new_ptr, ptr, min_size );
790
791    // release old block
792    remote_free( ptr , cxy );
793
794    return new_ptr;
795}
796
797//////////////////////////////////////////////////////
798static void update_free_array( malloc_store_t * store,
799                               unsigned int     base,
800                               unsigned int     size_index )
801{
802    // This recursive function try to merge the released block
803    // with the companion block if this companion block is free.
804    // This companion has the same size, and almost the same address
805    // (only one address bit is different)
806    // - If the companion is not in free[size_index],
807    //   the released block is pushed in free[size_index].
808    // - If the companion is found, it is evicted from free[size_index]
809    //   and the merged bloc is pushed in the free[size_index+1].
810
811
812    // compute released block size
813    unsigned int size = 1<<size_index;
814
815    // compute companion block and merged block base addresses
816    unsigned int companion_base; 
817    unsigned int merged_base; 
818
819    if ( (base & size) == 0 )   // the released block is aligned on (2*size)
820    {
821        companion_base  = base + size;
822        merged_base     = base;
823    }
824    else
825    {
826        companion_base  = base - size;
827        merged_base     = base - size;
828    }
829
830    // scan all blocks in free[size_index]
831    // the iter & prev variables are actually addresses
832    unsigned int  found = 0;
833    unsigned int  iter  = store->free[size_index];
834    unsigned int  prev  = (unsigned int)&store->free[size_index];
835    while ( iter ) 
836    {
837        if ( iter == companion_base ) 
838        {
839            found = 1;
840            break;
841        }
842        prev = iter;
843        iter = *(unsigned int*)iter;
844    }
845
846    if ( found == 0 )  // Companion not found => push in free[size_index] 
847    {
848        *(unsigned int*)base   = store->free[size_index];
849        store->free[size_index] = base;
850    }
851    else               // Companion found : merge
852    {
853        // evict the searched block from free[size_index]
854        *(unsigned int*)prev = *(unsigned int*)iter;
855
856        // call the update_free() function for free[size_index+1]
857        update_free_array( store, merged_base , size_index+1 );
858    }
859}  // end update_free_array()
860
861////////////////////////////////////
862void remote_free( void        * ptr,
863                  unsigned int  cxy )
864{
865
866#if MALLOC_DEBUG
867printf("\n[MALLOC] %s : enter for block = %x / cxy = %x\n",
868__FUNCTION__, ptr, cxy );
869#endif
870
871    unsigned int base = (unsigned int)ptr;
872
873    // check cxy value
874    if( cxy >= MALLOC_MAX_CLUSTERS )
875    {
876        printf("\n[ERROR] in %s : illegal cluster index %x\n",
877        __FUNCTION__ , cxy );
878        return;
879    }
880
881    // check ptr value
882    if( (base < store[cxy].store_base) || 
883        (base >= (store[cxy].store_base + store[cxy].store_size)) )
884    {
885        printf("\n[ERROR] in %s : illegal pointer for released block = %x\n",
886        __FUNCTION__, ptr );
887        return;
888    }
889 
890    // get the lock protecting store[cxy]
891    pthread_mutex_lock( &store[cxy].mutex );
892
893    // compute released block index in alloc[] array
894    unsigned index = (base - store[cxy].store_base ) / MALLOC_MIN_BLOCK_SIZE;
895 
896    // get the released block size_index
897    unsigned char* pchar      = (unsigned char*)(store[cxy].alloc_base + index);
898    unsigned int   size_index = (unsigned int)*pchar;
899
900    // check block is allocated
901    if ( size_index == 0 )
902    {
903        pthread_mutex_unlock( &store[cxy].mutex );
904        printf("\n[ERROR] in %s : released block not allocated / ptr = %x\n",
905        __FUNCTION__, ptr );
906        return;
907    }
908
909    // check released block alignment
910    if ( base % (1 << size_index) )
911    {
912        pthread_mutex_unlock( &store[cxy].mutex );
913        printf("\n[ERROR] in %s : released block not aligned / ptr = %x\n",
914        __FUNCTION__, ptr );
915        return;
916    }
917
918    // reset the alloc[index] entry
919    *pchar = 0;
920
921    // call the recursive function update_free_array()
922    update_free_array( &store[cxy], base, size_index ); 
923
924    // release the lock
925    pthread_mutex_unlock( &store[cxy].mutex );
926
927#if MALLOC_DEBUG
928printf("\n[MALLOC] %s : conmpletes for block = %x / cxy = %x\n",
929__FUNCTION__, ptr, cxy );
930#endif
931
932} // end remote_free()
933
934// Local Variables:
935// tab-width: 4
936// c-basic-offset: 4
937// c-file-offsets:((innamespace . 0)(inline-open . 0))
938// indent-tabs-mode: nil
939// End:
940// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
941
942
943
Note: See TracBrowser for help on using the repository browser.