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

Last change on this file since 623 was 623, checked in by alain, 5 years ago

Introduce three new types of vsegs (KCODE,KDATA,KDEV)
to map the kernel vsegs in the process VSL and GPT.
This now used by both the TSAR and the I86 architectures.

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