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

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

This version modifies the exec syscall and fixes a large number of small bugs.
The version number has been updated (0.1)

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