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

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

Introduce sigificant modifs in VFS to support the <ls> command,
and the . and .. directories entries.

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