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

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

Cosmetic.

File size: 27.6 KB
Line 
1/*
2 * almosmkh.c - User level ALMOS-MKH specific library implementation.
3 *
4 * Author     Alain Greiner (2016,2017,2018)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <almosmkh.h>
25#include <hal_user.h>
26#include <hal_shared_types.h>
27#include <syscalls_numbers.h>
28#include <string.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <mman.h>
33
34#define  MALLOC_DEBUG    0
35 
36/////////////     Non standard system calls    /////////////////////////////////
37
38//////////////////////////
39int fg( unsigned int pid )
40{
41    return hal_user_syscall( SYS_FG,
42                             (reg_t)pid, 0, 0, 0 );
43}
44
45//////////////////////////////
46int is_fg( unsigned int   pid,
47           unsigned int * owner )
48{
49    return hal_user_syscall( SYS_IS_FG,
50                             (reg_t)pid,
51                             (reg_t)owner, 0, 0 );
52}
53
54//////////////////////////////////////
55int get_config( unsigned int * x_size,
56                unsigned int * y_size,
57                unsigned int * ncores )
58{
59    return hal_user_syscall( SYS_GET_CONFIG,
60                             (reg_t)x_size,
61                             (reg_t)y_size,
62                             (reg_t)ncores, 0 );
63}
64
65/////////////////////////////////
66int get_core( unsigned int * cxy,
67              unsigned int * lid )
68{
69    return hal_user_syscall( SYS_GET_CORE,
70                             (reg_t)cxy,
71                             (reg_t)lid, 0, 0 );
72}
73
74///////////////////////////////////////////
75int get_cycle( unsigned long long * cycle )
76{
77    return hal_user_syscall( SYS_GET_CYCLE,
78                             (reg_t)cycle, 0, 0, 0 );
79}
80
81/////////////////////////////////
82int utls( unsigned int operation,
83          unsigned int value )
84{
85    return hal_user_syscall( SYS_UTLS,
86                             (reg_t)operation,
87                             (reg_t)value, 0, 0 );
88}
89
90////////////
91int getint( void )
92{
93    unsigned int  i;
94    int           val;    // ASCII character value
95
96    unsigned char buf[32];
97    unsigned int  save          = 0;
98    unsigned int  dec           = 0;
99    unsigned int  done          = 0;
100    unsigned int  overflow      = 0;
101    unsigned int  length        = 0;
102 
103    // get characters
104    while (done == 0) 
105    {
106        // read one character
107        val = getchar();
108
109        // analyse character
110        if ((val > 0x2F) && (val < 0x3A))         // decimal character
111        {
112            buf[length] = (unsigned char)val;
113            length++;                     
114            putchar( val );                       // echo
115        }
116        else if (val == 0x0A)                     // LF character
117        {
118            done = 1;
119        }
120        else if ( (val == 0x7F) ||                // DEL character
121                  (val == 0x08) )                 // BS  character
122        {
123            if ( length > 0 ) 
124            {
125                length--;         
126                printf("\b \b");                  // BS /  / BS
127            }
128        }
129        else if ( val == 0 )                      // EOF
130        {
131            return -1;
132        }
133
134        // test buffer overflow
135        if ( length >= 32 ) 
136        {
137            overflow = 1;
138            done     = 1;
139        }
140    }  // end while characters
141
142    // string to int conversion with overflow detection
143    if ( overflow == 0 )
144    {
145        for (i = 0; (i < length) && (overflow == 0) ; i++) 
146        {
147            dec = dec * 10 + (buf[i] - 0x30);
148            if (dec < save)  overflow = 1; 
149            save = dec;
150        }
151    } 
152
153    // final evaluation
154    if ( overflow == 0 )
155    {
156        // return value
157        return dec;
158    }
159    else
160    {
161        // cancel all echo characters
162        for (i = 0; i < length ; i++) 
163        {
164            printf("\b \b");                  // BS /  / BS
165        }
166
167        // echo character '0'
168        putchar( '0' );
169
170        // return 0 value
171        return 0;
172    }
173}  // end getint()
174
175
176///////////////    non standard debug functions    //////////////////////////
177
178////////////////////////////////////
179void display_string( char * string )
180{
181    hal_user_syscall( SYS_DISPLAY,
182                      DISPLAY_STRING,
183                      (reg_t)string, 0, 0 );
184}
185
186///////////////////////////////////
187int display_vmm( unsigned int cxy, unsigned int pid )
188{
189    return hal_user_syscall( SYS_DISPLAY,
190                             DISPLAY_VMM,
191                             (reg_t)pid,
192                             (reg_t)cxy, 0 );
193} 
194
195////////////////////////////////
196int display_sched( unsigned int cxy,
197                   unsigned int lid )
198{
199    return hal_user_syscall( SYS_DISPLAY,
200                             DISPLAY_SCHED,
201                             (reg_t)cxy,
202                             (reg_t)lid, 0 );
203} 
204
205/////////////////////////////////////////////////
206int display_cluster_processes( unsigned int cxy )
207{
208    return hal_user_syscall( SYS_DISPLAY,
209                             DISPLAY_CLUSTER_PROCESSES,
210                             (reg_t)cxy, 0, 0 );
211} 
212
213///////////////////
214int display_chdev( void )
215{
216    return hal_user_syscall( SYS_DISPLAY,
217                             DISPLAY_CHDEV, 0, 0, 0 );
218} 
219
220///////////////////////
221int display_vfs( void )
222{
223    return hal_user_syscall( SYS_DISPLAY,
224                             DISPLAY_VFS, 0, 0, 0 );
225} 
226
227////////////////////////////////////////////////
228int display_txt_processes( unsigned int txt_id )
229{
230    return hal_user_syscall( SYS_DISPLAY,
231                             DISPLAY_TXT_PROCESSES,
232                             (reg_t)txt_id, 0, 0 );
233} 
234
235///////////////////////////////
236int trace( unsigned int active,
237           unsigned int cxy, 
238           unsigned int lid )
239{
240    return hal_user_syscall( SYS_TRACE,
241                             (reg_t)active,
242                             (reg_t)cxy,
243                             (reg_t)lid, 0 );
244}
245
246////////////////////////
247int display_dqdt( void )
248{
249    return hal_user_syscall( SYS_DISPLAY,
250                             DISPLAY_DQDT, 0, 0, 0 );
251} 
252
253/////////////////
254void idbg( void )
255{
256   char          cmd;
257   unsigned int  cxy;
258   unsigned int  lid;
259   unsigned int  txt;
260   unsigned int  active;
261
262   while( 1 )
263   {
264        printf("\n[idbg] cmd = ");
265        cmd = (char)getchar();
266
267        if( cmd == 'h' )
268        {
269            printf("h\n"
270                   "p : display on TXT0 process descriptors in cluster[cxy]\n"
271                   "s : display on TXT0 scheduler state for core[cxy,lid]\n"
272                   "v : display on TXT0 VMM for calling process in cluster [cxy]\n"
273                   "t : display on TXT0 process decriptors attached to TXT[tid]\n"
274                   "y : activate/desactivate trace for core[cxy,lid]\n"
275                   "x : force calling process to exit\n"
276                   "c : resume calling process execution\n"
277                   "h : list supported commands\n");
278        }
279        else if( cmd == 'p' )
280        {
281            printf("p / cxy = ");
282            cxy = getint();
283            display_cluster_processes( cxy );
284        }
285        else if( cmd == 's' )
286        {
287            printf("s / cxy = ");
288            cxy = getint();
289            printf(" / lid = ");
290            lid = getint();
291            display_sched( cxy , lid );
292        }
293        else if( cmd == 'v' )
294        {
295            printf("v / cxy = ");
296            cxy = getint();
297            display_vmm( cxy , (unsigned int)getpid() );
298        }
299        else if( cmd == 't' )
300        {
301            printf("t / txt_id = ");
302            txt = getint();
303            display_txt_processes( txt );
304        }
305        else if( cmd == 'y' )
306        {
307            printf("y / active = ");
308            active = getint();
309            printf(" / cxy = ");
310            cxy    = getint();
311            printf(" / lid = ");
312            lid    = getint();
313            trace( active , cxy , lid );
314        }
315        else if( cmd == 'x' )
316        {
317            printf("x\n");
318            exit( 0 );
319        }
320        else if( cmd == 'c' )
321        {
322            printf("c\n");
323            break;
324        }
325    }
326}  // end idbg()
327
328
329///////////////    non standard malloc functions    //////////////////////////
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 MALLOC_DEBUG
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 != (unsigned int)(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_base 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 ( (unsigned int)(1<<searched_index) > store->store_size )  // failure
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    int error;
594
595#if MALLOC_DEBUG
596printf("\n[MALLOC] %s : enter for size = %x / cxy = %x\n",
597__FUNCTION__ , size , cxy );
598#endif
599
600    // check arguments
601    if( size == 0 )
602    {
603        printf("\n[ERROR] in %s : requested size = 0 \n",
604        __FUNCTION__ );
605        return NULL;
606    }
607    if( cxy >= MALLOC_MAX_CLUSTERS )
608    {
609        printf("\n[ERROR] in %s : illegal cluster %x\n",
610        __FUNCTION__ , cxy );
611        return NULL;
612    }
613
614    // initializes target store if required
615    if( store[cxy].initialized != MALLOC_INITIALIZED )
616    {
617        store_init( cxy , MALLOC_LOCAL_STORE_SIZE );
618
619        if( store[cxy].initialized != MALLOC_INITIALIZED )
620        {
621            printf("\n[ERROR] in %s : cannot allocate store in cluster %x\n",
622            __FUNCTION__ , cxy );
623            return NULL;
624        }
625    }
626
627    // normalize size
628    if ( size < MALLOC_MIN_BLOCK_SIZE ) size = MALLOC_MIN_BLOCK_SIZE;
629
630    // compute requested_index for the free[] array
631    unsigned int requested_index = GET_SIZE_INDEX( size );
632
633    // take the lock protecting access to store[cxy]
634    error = pthread_mutex_lock( &store[cxy].mutex );
635
636    if( error )
637    {
638        printf("\n[ERROR] in %s : cannot take the lock protecting store in cluster %x\n",
639        __FUNCTION__ , cxy );
640        return NULL;
641    }
642
643    // call the recursive function get_block
644    unsigned int base = get_block( &store[cxy], 
645                                   requested_index, 
646                                   requested_index );
647
648    // check block found
649    if (base == 0)
650    {
651        pthread_mutex_unlock( &store[cxy].mutex );
652        printf("\n[ERROR] in %s : no more space in cluster %x\n",
653        __FUNCTION__ , cxy );
654        return NULL;
655    }
656
657    // compute pointer in alloc[] array
658    unsigned        offset = (base - store[cxy].store_base) / MALLOC_MIN_BLOCK_SIZE;
659    unsigned char * ptr    = (unsigned char*)(store[cxy].alloc_base + offset);
660
661    // DEPRECATED : we cannot check the alloc[] array,
662    // because it has not been initialised by store_init,
663    // to avoid physical memory allocation at heap creation [AG]
664    // if ( *ptr != 0 )
665    // {
666    //    pthread_mutex_unlock( &store[cxy].mutex );
667    //    printf("\n[PANIC] in %s : allocate an already allocated block...\n",
668    //    __FUNCTION__ );
669    //    return NULL;
670    // }
671
672    // update alloc_array
673    *ptr = requested_index;
674
675    // release the lock
676    pthread_mutex_unlock( &store[cxy].mutex );
677 
678#if MALLOC_DEBUG
679printf("\n[MALLOC] %s : exit / base = %x / size = %x / from store[%x]\n",
680__FUNCTION__, base , size , cxy );
681#endif
682
683    return (void*) base;
684
685} // end remote_malloc()
686
687
688
689//////////////////////////////////////////
690void * remote_calloc ( unsigned int count,
691                       unsigned int size,
692                       unsigned int cxy )
693{
694    void * ptr = remote_malloc( count * size , cxy );
695    memset( ptr , 0 , count * size );
696    return ptr;
697}
698
699//////////////////////////////////
700void * remote_realloc( void * ptr,
701                       unsigned int size,
702                       unsigned int cxy )
703{
704    // simple allocation when (ptr == NULL)
705    if( ptr == NULL )
706    {
707        return remote_malloc( size , cxy );
708    }
709
710    // simple free when (size == 0)
711    if( size == 0 )
712    {
713        remote_free( ptr , cxy );
714        return NULL;
715    }
716
717    // check cxy and ptr in general case
718    if( cxy >= MALLOC_MAX_CLUSTERS )
719    {
720        printf("\n[ERROR] in %s : illegal cluster index %x\n",
721        __FUNCTION__ , cxy );
722        return NULL;
723    }
724
725    unsigned int base = (unsigned int)ptr;
726
727    if( (base < store[cxy].store_base) || 
728        (base >= (store[cxy].store_base + store[cxy].store_size)) )
729    {
730        printf("\n[ERROR] in %s : illegal pointer = %x\n",
731        __FUNCTION__, ptr );
732        return NULL;
733    }
734 
735    // compute index in free[] array
736    int index = (base - store[cxy].store_base) / MALLOC_MIN_BLOCK_SIZE;
737
738    // compute old size
739    char        * pchar    = (char *) (store[cxy].alloc_base + index);
740    unsigned int  old_size = (unsigned int)(1 << ((int) *pchar));
741
742    // allocate a new block
743    void * new_ptr = remote_malloc( size , cxy );
744
745    // save old data to new block
746    int min_size = (int)((size < old_size) ? size : old_size);
747    memcpy( new_ptr, ptr, min_size );
748
749    // release old block
750    remote_free( ptr , cxy );
751
752    return new_ptr;
753}
754
755//////////////////////////////////////////////////////
756static void update_free_array( malloc_store_t * store,
757                               unsigned int     base,
758                               unsigned int     size_index )
759{
760    // This recursive function try to merge the released block
761    // with the companion block if this companion block is free.
762    // This companion has the same size, and almost the same address
763    // (only one address bit is different)
764    // - If the companion is not in free[size_index],
765    //   the released block is pushed in free[size_index].
766    // - If the companion is found, it is evicted from free[size_index]
767    //   and the merged bloc is pushed in the free[size_index+1].
768
769
770    // compute released block size
771    unsigned int size = 1<<size_index;
772
773    // compute companion block and merged block base addresses
774    unsigned int companion_base; 
775    unsigned int merged_base; 
776
777    if ( (base & size) == 0 )   // the released block is aligned on (2*size)
778    {
779        companion_base  = base + size;
780        merged_base     = base;
781    }
782    else
783    {
784        companion_base  = base - size;
785        merged_base     = base - size;
786    }
787
788    // scan all blocks in free[size_index]
789    // the iter & prev variables are actually addresses
790    unsigned int  found = 0;
791    unsigned int  iter  = store->free[size_index];
792    unsigned int  prev  = (unsigned int)&store->free[size_index];
793    while ( iter ) 
794    {
795        if ( iter == companion_base ) 
796        {
797            found = 1;
798            break;
799        }
800        prev = iter;
801        iter = *(unsigned int*)iter;
802    }
803
804    if ( found == 0 )  // Companion not found => push in free[size_index] 
805    {
806        *(unsigned int*)base   = store->free[size_index];
807        store->free[size_index] = base;
808    }
809    else               // Companion found : merge
810    {
811        // evict the searched block from free[size_index]
812        *(unsigned int*)prev = *(unsigned int*)iter;
813
814        // call the update_free() function for free[size_index+1]
815        update_free_array( store, merged_base , size_index+1 );
816    }
817}  // end update_free_array()
818
819////////////////////////////////////
820void remote_free( void        * ptr,
821                  unsigned int  cxy )
822{
823
824#if MALLOC_DEBUG
825printf("\n[MALLOC] %s : enter for block = %x / cxy = %x\n",
826__FUNCTION__, ptr, cxy );
827#endif
828
829    unsigned int base = (unsigned int)ptr;
830
831    // check cxy value
832    if( cxy >= MALLOC_MAX_CLUSTERS )
833    {
834        printf("\n[ERROR] in %s : illegal cluster index %x\n",
835        __FUNCTION__ , cxy );
836        return;
837    }
838
839    // check ptr value
840    if( (base < store[cxy].store_base) || 
841        (base >= (store[cxy].store_base + store[cxy].store_size)) )
842    {
843        printf("\n[ERROR] in %s : illegal pointer for released block = %x\n",
844        __FUNCTION__, ptr );
845        return;
846    }
847 
848    // get the lock protecting store[cxy]
849    pthread_mutex_lock( &store[cxy].mutex );
850
851    // compute released block index in alloc[] array
852    unsigned index = (base - store[cxy].store_base ) / MALLOC_MIN_BLOCK_SIZE;
853 
854    // get the released block size_index
855    unsigned char* pchar      = (unsigned char*)(store[cxy].alloc_base + index);
856    unsigned int   size_index = (unsigned int)*pchar;
857
858    // check block is allocated
859    if ( size_index == 0 )
860    {
861        pthread_mutex_unlock( &store[cxy].mutex );
862        printf("\n[ERROR] in %s : released block not allocated / ptr = %x\n",
863        __FUNCTION__, ptr );
864        return;
865    }
866
867    // check released block alignment
868    if ( base % (1 << size_index) )
869    {
870        pthread_mutex_unlock( &store[cxy].mutex );
871        printf("\n[ERROR] in %s : released block not aligned / ptr = %x\n",
872        __FUNCTION__, ptr );
873        return;
874    }
875
876    // reset the alloc[index] entry
877    *pchar = 0;
878
879    // call the recursive function update_free_array()
880    update_free_array( &store[cxy], base, size_index ); 
881
882    // release the lock
883    pthread_mutex_unlock( &store[cxy].mutex );
884
885#if MALLOC_DEBUG
886printf("\n[MALLOC] %s : conmpletes for block = %x / cxy = %x\n",
887__FUNCTION__, ptr, cxy );
888#endif
889
890} // end remote_free()
891
892// Local Variables:
893// tab-width: 4
894// c-basic-offset: 4
895// c-file-offsets:((innamespace . 0)(inline-open . 0))
896// indent-tabs-mode: nil
897// End:
898// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
899
900
901
Note: See TracBrowser for help on using the repository browser.