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

Last change on this file since 450 was 445, checked in by alain, 6 years ago

Restructure the mini_libc.

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