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

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

This version has been tested on the sort multithreaded application
for TSAR_IOB architectures ranging from 1 to 8 clusters.
It fixes three bigs bugs:
1) the dev_ioc device API has been modified: the dev_ioc_sync_read()
and dev_ioc_sync_write() function use now extended pointers on the
kernel buffer to access a mapper stored in any cluster.
2) the hal_uspace API has been modified: the hal_copy_to_uspace()
and hal_copy_from_uspace() functions use now a (cxy,ptr) couple
to identify the target buffer (equivalent to an extended pointer.
3) an implementation bug has been fixed in the assembly code contained
in the hal_copy_to_uspace() and hal_copy_from_uspace() functions.

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