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

Last change on this file since 597 was 597, checked in by alain, 3 years ago

Rewrite the mmap() and stat() syscalls to implement the cat command in ksh.

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