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

Last change on this file since 678 was 678, checked in by alain, 3 years ago

Introduce the fget_string() function.

File size: 56.9 KB
RevLine 
[445]1/*
2 * almosmkh.c - User level ALMOS-MKH specific library implementation.
3 *
[657]4 * Author     Alain Greiner (2016,2017,2018,2019,2020)
[445]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>
[637]26#include <hal_macros.h>
[457]27#include <hal_shared_types.h>
[643]28#include <shared_fbf.h>
[445]29#include <syscalls_numbers.h>
30#include <string.h>
[444]31#include <stdio.h>
[445]32#include <stdlib.h>
33#include <unistd.h>
34#include <mman.h>
[444]35
[637]36#define  DEBUG_REMOTE_MALLOC     0
[638]37#define  DEBUG_PTHREAD_PARALLEL  0
[573]38 
[637]39//////////////////////////////////////////////////////////////////////////////////////
40/////////////     Non standard system calls    ///////////////////////////////////////
41//////////////////////////////////////////////////////////////////////////////////////
[444]42
43//////////////////////////
44int fg( unsigned int pid )
45{
46    return hal_user_syscall( SYS_FG,
47                             (reg_t)pid, 0, 0, 0 );
48}
49
[457]50//////////////////////////////
51int is_fg( unsigned int   pid,
52           unsigned int * owner )
53{
54    return hal_user_syscall( SYS_IS_FG,
55                             (reg_t)pid,
56                             (reg_t)owner, 0, 0 );
57}
58
[661]59///////////////////////////////////////////////
60int get_config( struct hard_config_s * config )
[444]61{
62    return hal_user_syscall( SYS_GET_CONFIG,
[661]63                             (reg_t)config, 0, 0, 0);
[444]64}
65
[637]66////////////////////////////////////
67int get_core_id( unsigned int * cxy,
68                 unsigned int * lid )
[444]69{
[637]70    return hal_user_syscall( SYS_GET_CORE_ID,
[444]71                             (reg_t)cxy,
72                             (reg_t)lid, 0, 0 );
73}
74
[637]75/////////////////////////////////////
76int get_nb_cores( unsigned int   cxy,
77                  unsigned int * ncores )
78{
79    return hal_user_syscall( SYS_GET_NB_CORES,
80                             (reg_t)cxy,
81                             (reg_t)ncores, 0, 0 );
82}
83
[444]84///////////////////////////////////////////
[637]85int get_best_core( unsigned int   base_cxy,
86                   unsigned int   level,
87                   unsigned int * cxy,
88                   unsigned int * lid )
89{
90    return hal_user_syscall( SYS_GET_BEST_CORE,
91                             (reg_t)base_cxy,
92                             (reg_t)level,
93                             (reg_t)cxy,
94                             (reg_t)lid );
95}
96
97///////////////////////////////////////////
[444]98int get_cycle( unsigned long long * cycle )
99{
100    return hal_user_syscall( SYS_GET_CYCLE,
101                             (reg_t)cycle, 0, 0, 0 );
102}
103
[589]104//////////////////////////////////
105int place_fork( unsigned int cxy )
106{
107    return hal_user_syscall( SYS_PLACE_FORK,
108                             (reg_t)cxy, 0, 0, 0 );
109}
110
[444]111/////////////////////////////////
112int utls( unsigned int operation,
113          unsigned int value )
114{
115    return hal_user_syscall( SYS_UTLS,
116                             (reg_t)operation,
117                             (reg_t)value, 0, 0 );
118}
119
[678]120////////////////////////////////////////
121void get_uint32( unsigned int * buffer )
[444]122{
123    unsigned int  i;
[580]124    int           c;    // ASCII character value
[444]125
126    unsigned char buf[32];
[580]127
[444]128    unsigned int  save          = 0;
[580]129    unsigned int  value         = 0;
[444]130    unsigned int  done          = 0;
131    unsigned int  overflow      = 0;
132    unsigned int  length        = 0;
[580]133
[444]134    // get characters
135    while (done == 0) 
136    {
137        // read one character
[580]138        c = getchar();
[444]139
[580]140        // analyse this character
141        if ( ((c > 0x2F) && (c < 0x3A)) ||                      // 0 to 9
142             ((c > 0x40) && (c < 0x47)) ||                      // A to F
143             ((c > 0x60) && (c < 0x67)) ||                      // a to f
144             (((c == 0x58) || (c == 0x78)) && (length == 1)) )  // X or x
[444]145        {
[580]146            putchar( c );                       // echo
147            if ( c > 0x60 )  c = c - 0x20;      // to upper case
148            buf[length] = (unsigned char)c;
[444]149            length++;                     
150        }
[580]151        else if (c == 0x0A)                                     // LF character
[444]152        {
153            done = 1;
154        }
[580]155        else if ( (c == 0x7F) ||                                // DEL character
156                  (c == 0x08) )                                 // BS  character
[444]157        {
158            if ( length > 0 ) 
159            {
160                length--;         
[580]161                printf("\b \b");                // BS /  / BS
[444]162            }
163        }
[580]164        else if ( c == 0 )                                      // EOF character
[444]165        {
[657]166            overflow = 1;
167            done     = 1;
[444]168        }
169
170        // test buffer overflow
171        if ( length >= 32 ) 
172        {
173            overflow = 1;
174            done     = 1;
175        }
176    }  // end while characters
177
[580]178    // string to int conversion with overflow detection
[444]179    if ( overflow == 0 )
180    {
[580]181        // test (decimal / hexa)
182        if( (buf[0] == 0x30) && (buf[1] == 0x58) )     // hexadecimal input
[444]183        {
[580]184            for (i = 2; (i < length) && (overflow == 0) ; i++)
185            {
186                if( buf[i] < 0x40 ) value = (value << 4) + (buf[i] - 0x30);
187                else                value = (value << 4) + (buf[i] - 0x37);
188                if (value < save) overflow = 1; 
189                save = value;
190            }
[444]191        }
[580]192        else                                           // decimal input
193        {
194            for (i = 0; (i < length) && (overflow == 0) ; i++) 
195            {
196                value = (value * 10) + (buf[i] - 0x30);
197                if (value < save) overflow = 1; 
198                save = value;
199            }
200        }
[444]201    } 
202
[678]203    // write value to buffer
[444]204    if ( overflow == 0 )
205    {
206        // return value
[657]207        *buffer = value;
[444]208    }
209    else
210    {
211        // cancel all echo characters
212        for (i = 0; i < length ; i++) 
213        {
214            printf("\b \b");                  // BS /  / BS
215        }
216
217        // echo character '0'
218        putchar( '0' );
219
220        // return 0 value
[657]221        *buffer = 0;
[444]222    }
[580]223}  // end get_uint32()
[444]224
[678]225///////////////////////////////
[626]226int get_string( char * string,
227                int    maxlen )
228{
229    int c;
230    int length = 0;
[445]231
[678]232    while( 1 )
[626]233    {
234        // check buffer overflow
235        if( length >= maxlen-1 )
236        {
[661]237            // cancel all echo characters
238            while( length )
239            {
240               printf("\b \b");             // cancel one echo character
241               length--;                   
242            }
[626]243        }
244
245        // read one character
246        c = getchar();
247
248        // analyse this character
249        if ( (c >= 0x20) && (c < 0x7F) )    // printable character
250        {
251            putchar( c );                   // echo
252            string[length] = (char)c;       // register character in string
253            length++;                       // update length
254        }
[678]255        else if( c == 0x0A )                // LF character marks end of string
[626]256        {
[678]257            putchar( c );                   // echo
258            string[length] = 0;             // register NUL character in string
259            return length + 1;
[626]260        }
261        else if ( (c == 0x7F) ||            // DEL character
262                  (c == 0x08) )             // BS  character
263        {
264            if ( length > 0 ) 
265            {
[661]266                printf("\b \b");            // cancel one echo character
[626]267                length--;         
268            }
269        }
[678]270    }
271
272    // set NUL character in string and return success
273
274}  // end get_string()
275
276
277/////////////////////////////
278int fget_string( int    fdid,
279                 char * string,
280                 int    maxlen )
281{
282    int  ret;
283    char c;
284    int  length = 0;
285
286    while( 1 )
287    {
288        // check buffer overflow
289        if( length >= maxlen-1 )  length = 0;                 
290
291        // read one character from stream
292        ret = read( fdid , &c , 1 );
293
294        if( ret == 1 )
[626]295        {
[678]296            if ( (c >= 0x20) && (c < 0x7F) )    // printable character
[661]297            {
[678]298                string[length] = (char)c;       // register character in string
299                length++;                       // update length
[661]300            }
[678]301            else if ( c == 0 )                  // end of string
302            {
303                string[length] = (char)c;       // register character in string
304                length++;                       // update length
305                break;                          // exit loop
306            }
307            // discard all characters not printable or NUL
[626]308        }
[678]309        else 
310        {
311            printf("\n[%s] cannot read stream %d\n", __FUNCTION__, fdid );
312            length = 0;
313            break;
314        }
[626]315    }
[678]316}  // end fget_string()
[626]317
318
[637]319//////////////////////////////////////////////////////////////////////////////////////
320///////////////    non standard debug functions    ///////////////////////////////////
321//////////////////////////////////////////////////////////////////////////////////////
[626]322
[641]323///////////////////////////////////////////
324int get_thread_info( thread_info_t * info )
325{
326    return hal_user_syscall( SYS_GET_THREAD_INFO,
327                             (reg_t)info, 0, 0, 0 );
328}
329
[445]330////////////////////////////////////
331void display_string( char * string )
332{
333    hal_user_syscall( SYS_DISPLAY,
334                      DISPLAY_STRING,
335                      (reg_t)string, 0, 0 );
336}
337
[580]338/////////////////////////////////////////////////////
[640]339int display_vmm( unsigned int cxy,
340                 unsigned int pid,
341                 unsigned int mapping )
[445]342{
343    return hal_user_syscall( SYS_DISPLAY,
344                             DISPLAY_VMM,
[580]345                             (reg_t)cxy,
[640]346                             (reg_t)pid,
347                             (reg_t)mapping );
[445]348} 
349
[597]350////////////////////////////////////
[445]351int display_sched( unsigned int cxy,
352                   unsigned int lid )
353{
354    return hal_user_syscall( SYS_DISPLAY,
355                             DISPLAY_SCHED,
356                             (reg_t)cxy,
357                             (reg_t)lid, 0 );
358} 
359
[597]360////////////////////////////////////////////////
[589]361int display_cluster_processes( unsigned int cxy,
362                               unsigned int owned )
[445]363{
364    return hal_user_syscall( SYS_DISPLAY,
365                             DISPLAY_CLUSTER_PROCESSES,
[589]366                             (reg_t)cxy,
367                             (reg_t)owned, 0 );
[445]368} 
369
[580]370////////////////////////////////////////
371int display_busylocks( unsigned int pid,
372                       unsigned int trdid )
373{
374    return hal_user_syscall( SYS_DISPLAY,
375                             DISPLAY_BUSYLOCKS,
376                             (reg_t)pid,
377                             (reg_t)trdid, 0 );
378} 
379
380/////////////////////////
[478]381int display_chdev( void )
[445]382{
383    return hal_user_syscall( SYS_DISPLAY,
384                             DISPLAY_CHDEV, 0, 0, 0 );
385} 
386
[573]387///////////////////////
[478]388int display_vfs( void )
[445]389{
390    return hal_user_syscall( SYS_DISPLAY,
391                             DISPLAY_VFS, 0, 0, 0 );
392} 
393
394////////////////////////////////////////////////
395int display_txt_processes( unsigned int txt_id )
396{
397    return hal_user_syscall( SYS_DISPLAY,
398                             DISPLAY_TXT_PROCESSES,
399                             (reg_t)txt_id, 0, 0 );
400} 
401
[597]402////////////////////////
403int display_dqdt( void )
404{
405    return hal_user_syscall( SYS_DISPLAY,
406                             DISPLAY_DQDT, 0, 0, 0 );
407} 
408
[611]409///////////////////////////////////////
410int display_mapper( char        * path,
411                    unsigned int  page_id,
412                    unsigned int  nbytes)
413{
414    return hal_user_syscall( SYS_DISPLAY,
415                             DISPLAY_MAPPER,
416                             (reg_t)path,
417                             (reg_t)page_id,
418                             (reg_t)nbytes );
419} 
420
[623]421///////////////////////////////////////
422int display_barrier( unsigned int pid )
423{
424    return hal_user_syscall( SYS_DISPLAY,
425                             DISPLAY_BARRIER,
426                             (reg_t)pid, 0, 0 );
427} 
428
[626]429///////////////////////////////////////
[657]430int display_fat( unsigned int  min_slot,
431                 unsigned int  nb_slots )
[626]432{
433    return hal_user_syscall( SYS_DISPLAY,
434                             DISPLAY_FAT,
[657]435                             (reg_t)min_slot,
436                             (reg_t)nb_slots, 0 );
[626]437} 
438
[661]439/////////////////////////////////////
440int display_socket( unsigned int pid,
441                    unsigned int fdid )
442{
443    return hal_user_syscall( SYS_DISPLAY,
444                             DISPLAY_SOCKET,
445                             (reg_t)pid,
446                             (reg_t)fdid, 0 );
447}
448
[678]449////////////////////////////////////////
450int display_fd_array( unsigned int pid )
451{
452    return hal_user_syscall( SYS_DISPLAY,
453                             DISPLAY_FD,
454                             (reg_t)pid, 0, 0 );
455}
456
457///////////////////////////////////////////
458int display_fbf_windows( unsigned int pid )
459{
460    return hal_user_syscall( SYS_DISPLAY,
461                             DISPLAY_WINDOWS,
462                             (reg_t)pid, 0, 0 );
463}
464
[573]465///////////////////////////////
[445]466int trace( unsigned int active,
[457]467           unsigned int cxy, 
[445]468           unsigned int lid )
469{
470    return hal_user_syscall( SYS_TRACE,
471                             (reg_t)active,
[457]472                             (reg_t)cxy,
[445]473                             (reg_t)lid, 0 );
474}
475
[573]476/////////////////
[478]477void idbg( void )
[444]478{
479   char          cmd;
480
481   while( 1 )
482   {
[626]483        // display prompt
[444]484        printf("\n[idbg] cmd = ");
[626]485
486        // get a one character command
[444]487        cmd = (char)getchar();
488
[626]489        // display all busylocks owned by thread(pid,trdid)
490        if( cmd == 'b' )
[444]491        {
[657]492            unsigned int pid;
493            unsigned int trdid;
494
[626]495            printf("b / pid = ");
[678]496            get_uint32( &pid );
[657]497
[626]498            printf(" / trdid = ");
[678]499            get_uint32( &trdid );
[657]500
[678]501            display_busylocks( pid , trdid );
[444]502        }
[626]503        // return to calling process
504        else if( cmd == 'c' )
505        {
506            printf("c\n");
507            break;
508        }
[657]509        // display FAT mapper(min,slots)
[626]510        else if( cmd == 'f' )
511        {
[657]512            unsigned int min;
513            unsigned int slots;
514
515            printf(" / min = ");
[678]516            get_uint32( &min );
[657]517
518            printf(" / slots = ");
[678]519            get_uint32( &slots );
[657]520
[678]521            display_fat( min , slots );
[626]522        }
523        // list all supported commands
524        else if( cmd == 'h' )
525        {
526            printf("h\n" 
527                   "- b : display on TXT0 busylocks taken by thread[pid,trdid]\n"
528                   "- c : resume calling process execution\n"
[657]529                   "- f : display on TXT0 FAT mapper[min_slot,nb_slotss]\n"
[626]530                   "- h : list of supported commands\n"
531                   "- m : display on TXT0 mapper[path,page,nbytes]\n"
532                   "- p : display on TXT0 process descriptors in cluster[cxy]\n"
533                   "- q : display on TXT0 DQDT state\n"
534                   "- s : display on TXT0 scheduler state for core[cxy,lid]\n"
535                   "- t : display on TXT0 process decriptors attached to TXT[tid]\n"
536                   "- v : display on TXT0 VMM state for process[cxy,pid]\n"
537                   "- x : force calling process to exit\n"
538                   "- y : activate/desactivate trace for core[cxy,lid]\n"
539                   );
540        }
541        // display MAPPER(path,page,nbytes)
542        else if( cmd == 'm' )
543        {
544            char  path[128];
[657]545            unsigned int page;
546            unsigned int nbytes;
547
[626]548            printf("m / path = ");
[678]549            get_string( path , 128 );
[657]550
[626]551            printf(" / page = ");
[678]552            get_uint32( &page );
[657]553
[626]554            printf(" / nbytes = ");
[678]555            get_uint32( &nbytes );
[657]556
[678]557            display_mapper( path , page , nbytes );
[626]558        }
559        // display all processes in cluster(cxy)
[444]560        else if( cmd == 'p' )
561        {
[657]562            unsigned int cxy;
563
[444]564            printf("p / cxy = ");
[678]565            get_uint32( &cxy );
[657]566
[678]567            display_cluster_processes( cxy , 0 );
[444]568        }
[626]569        // display DQDT
570        else if( cmd == 'q' )
571        {
572            printf("q\n");
573            display_dqdt();
574        }
575        // display scheduler state for core(cxy,lid)
[444]576        else if( cmd == 's' )
577        {
[657]578            unsigned int cxy;
579            unsigned int lid;
580
[444]581            printf("s / cxy = ");
[678]582            get_uint32( &cxy );
[657]583
[444]584            printf(" / lid = ");
[678]585            get_uint32( &lid );
[657]586
[678]587            display_sched( cxy , lid );
[444]588        }
[626]589        // display all processes attached to TXT(txt_id)
590        else if( cmd == 't' )
591        {
[657]592            unsigned int txt_id;
593
[626]594            printf("t / txt_id = ");
[678]595            get_uint32( &txt_id );
[657]596
[678]597            display_txt_processes( txt_id );
[626]598        }
599        // display vmm state for process(cxy, pid)
[444]600        else if( cmd == 'v' )
601        {
[657]602            unsigned int cxy;
603            unsigned int pid;
604            unsigned int map;
605
[444]606            printf("v / cxy = ");
[678]607            get_uint32( &cxy );
[657]608
[580]609            printf(" / pid = ");
[678]610            get_uint32( &pid );
[657]611
[640]612            printf(" / mapping = ");
[678]613            get_uint32( &map );
[657]614
[678]615            display_vmm( cxy , pid , map );
[444]616        }
[626]617        // force the calling process to exit
618        else if( cmd == 'x' )
[444]619        {
[626]620            printf("x\n");
621            exit( 0 );
[444]622        }
[626]623        // activate scheduler trace for core(cxy,lid)
[444]624        else if( cmd == 'y' )
625        {
[657]626            unsigned int active;
627            unsigned int cxy;
628            unsigned int lid;
629
[444]630            printf("y / active = ");
[678]631            get_uint32( &active );
[657]632
[444]633            printf(" / cxy = ");
[678]634            get_uint32( &cxy );
[657]635
[444]636            printf(" / lid = ");
[678]637            get_uint32( &lid );
[657]638
[678]639            trace( active , cxy , lid );
[444]640        }
[626]641    }  // en while
[444]642}  // end idbg()
643
644
[637]645/////////////////////////////////////////////////////////////////////////////////////////
646///////////////    non standard remote_malloc    ////////////////////////////////////////
647/////////////////////////////////////////////////////////////////////////////////////////
[444]648
[445]649/////////////////////////////////////////////////////////////////////////////////////////
650// Global variable defining the allocator array (one per cluster)
651// This array (about 16 Kbytes ) will be stored in the data segment
[637]652// of any application linked with this libray.
[445]653/////////////////////////////////////////////////////////////////////////////////////////
654
655malloc_store_t   store[MALLOC_MAX_CLUSTERS];
656
657// Macro returning the smallest power of 2 larger or equal to size value
658
659#define GET_SIZE_INDEX(size)                (size <= 0x00000001) ? 0  :\
660                                            (size <= 0x00000002) ? 1  :\
661                                            (size <= 0x00000004) ? 2  :\
662                                            (size <= 0x00000008) ? 3  :\
663                                            (size <= 0x00000010) ? 4  :\
664                                            (size <= 0x00000020) ? 5  :\
665                                            (size <= 0x00000040) ? 6  :\
666                                            (size <= 0x00000080) ? 7  :\
667                                            (size <= 0x00000100) ? 8  :\
668                                            (size <= 0x00000200) ? 9  :\
669                                            (size <= 0x00000400) ? 10 :\
670                                            (size <= 0x00000800) ? 11 :\
671                                            (size <= 0x00001000) ? 12 :\
672                                            (size <= 0x00002000) ? 13 :\
673                                            (size <= 0x00004000) ? 14 :\
674                                            (size <= 0x00008000) ? 15 :\
675                                            (size <= 0x00010000) ? 16 :\
676                                            (size <= 0x00020000) ? 17 :\
677                                            (size <= 0x00040000) ? 18 :\
678                                            (size <= 0x00080000) ? 19 :\
679                                            (size <= 0x00100000) ? 20 :\
680                                            (size <= 0x00200000) ? 21 :\
681                                            (size <= 0x00400000) ? 22 :\
682                                            (size <= 0x00800000) ? 23 :\
683                                            (size <= 0x01000000) ? 24 :\
684                                            (size <= 0x02000000) ? 25 :\
685                                            (size <= 0x04000000) ? 26 :\
686                                            (size <= 0x08000000) ? 27 :\
687                                            (size <= 0x10000000) ? 28 :\
688                                            (size <= 0x20000000) ? 29 :\
689                                            (size <= 0x40000000) ? 30 :\
690                                            (size <= 0x80000000) ? 31 :\
691                                                                   32
692
693////////////////////////////////////////////////////////////////////////////////////////////
694// This static function display the current state of the allocator in cluster <cxy>.
695////////////////////////////////////////////////////////////////////////////////////////////
696
[637]697#if DEBUG_REMOTE_MALLOC
[445]698static void display_free_array( unsigned int cxy )
699{
700    unsigned int next;
701    unsigned int id;
702    unsigned int iter;
703
704    printf("\n*****   store[%x] base = %x / size = %x\n", 
705    cxy , store[cxy].store_base, store[cxy].store_size );
706    for ( id = 0 ; id < 32 ; id++ )
707    { 
708        next = store[cxy].free[id];
709        printf(" - free[%d] = " , id );
710        iter = 0;
711        while ( next != 0 )
712        {
713            printf("%x | ", next );
714            next = (*(unsigned int*)next);
715            iter++;
716        }
717        printf("0\n");
718    }
719}  // end display_free_array()
720#endif
721
722
723////////////////////////////////////////////////////////////////////i//////////////////////
724// This static function initialises the store in the cluster identified by the <cxy>
[650]725// arguments. It is called by the remote_malloc() function when a specific store(x,y)
726// is accessed for the first time.
[445]727// It uses the mmap( MAP_REMOTE ) syscall to allocate a new vseg mapped in cluster (cxy).
728////////////////////////////////////////////////////////////////////i//////////////////////
729// @ cxy        : target cluster identifier (fixed format).
730// @ store_size : store size (bytes).
731// # return without setting the initialized field in store(cxy) if failure.
732////////////////////////////////////////////////////////////////////i//////////////////////
733static void store_init( unsigned int cxy,
734                        unsigned int store_size )
735{
736    unsigned int   store_base;       // store base address
737    unsigned int   free_index;       // index in free[array]
738
739    unsigned int   alloc_base;       // alloc[] array base
740    unsigned int   alloc_size;       // alloc[] array size
741    unsigned int   alloc_index;      // index in alloc[array]
742
743    unsigned int   iter;             // iterator
744
[637]745#if DEBUG_REMOTE_MALLOC
746unsigned int core_cxy;
747unsigned int core_lid;
748get_core_id( &core_cxy , &core_lid );
749printf("\n[%s] core[%x,%d] enter for store[%x] / size = %x\n",
750__FUNCTION__, core_cxy, core_lid, cxy, store_size );
[445]751#endif
752
753    // get index in free[] array from size
754    free_index = GET_SIZE_INDEX( store_size );
755
756    // check store size power of 2
[473]757    if( store_size != (unsigned int)(1<<free_index) )
[445]758    {
759        printf("\n[ERROR] in %s : store[%x] size not power of 2 / size = %x\n",
760        __FUNCTION__, cxy , store_size );
761        return;
762    }
763
764    // allocate store in virtual space
765    void * vadr = mmap( NULL,                     // MAP_FIXED not supported
766                        store_size,
767                        PROT_READ | PROT_WRITE,
768                        MAP_REMOTE| MAP_SHARED,
769                        cxy,                      // fd is cluster identifier
770                        0 );                      // offset unused
771
772    if( vadr == NULL )
773    {
774        printf("\n[ERROR] in %s : cannot mmap store[%x]\n",
775        __FUNCTION__, cxy );
776        return;
777    }
778
779    store_base = (unsigned int)vadr;
780
781    // check allocated store alignment
782    if( store_base % store_size )
783    {
784        printf("\n[ERROR] in %s : store[%x] not aligned / base = %x / size = %x\n",
785        __FUNCTION__, cxy , store_base , store_size );
786        return;
787    }
788
[637]789#if DEBUG_REMOTE_MALLOC
790printf("\n[%s] core[%x,%d] created vseg %x for store[%x]\n",
791__FUNCTION__, core_cxy, core_lid, store_base, cxy );
[445]792#endif
793
794    // compute size of block containing alloc[] array
795    alloc_size = store_size / MALLOC_MIN_BLOCK_SIZE;
796    if ( alloc_size < MALLOC_MIN_BLOCK_SIZE) alloc_size = MALLOC_MIN_BLOCK_SIZE;
797
798    // get index for the corresponding block
799    alloc_index = GET_SIZE_INDEX( alloc_size );
800
801    // compute alloc[] array base address
802    alloc_base = store_base + store_size - alloc_size;
803
804    // reset the free[] array
805    for ( iter = 0 ; iter < 32 ; iter++ )
806    {
807        store[cxy].free[iter] = 0;
808    }
809
810    // split the store into various sizes blocks,
811    // initializes the free[] array and NEXT pointers
812    // base is the block base address
813    unsigned int   base = store_base;
814    unsigned int * ptr;
815    for ( iter = free_index-1 ; iter >= alloc_index ; iter-- )
816    {
817        store[cxy].free[iter] = base;
818        ptr = (unsigned int*)base;
819        *ptr = 0;
820        base = base + (1<<iter);
821    }
822
823    // initialize store mutex
824    if( pthread_mutex_init( &store[cxy].mutex , NULL ) )
825    {
826        printf("\n[ERROR] in %s : cannot initialize mutex for store[%x]\n", 
827        __FUNCTION__, cxy );
828        return;
829    }
830
831    store[cxy].cxy         = cxy;
832    store[cxy].store_base  = store_base;
833    store[cxy].store_size  = store_size;
834    store[cxy].alloc_size  = alloc_size;
835    store[cxy].alloc_base  = alloc_base;
836    store[cxy].initialized = MALLOC_INITIALIZED;
837
838
[637]839#if DEBUG_REMOTE_MALLOC
840printf("\n[%s] core[%x,%d] completed store[%x] initialisation\n",
841__FUNCTION__, core_cxy, core_lid, cxy );
842#endif
[445]843
[637]844#if (DEBUG_REMOTE_MALLOC & 1)
[445]845display_free_array( cxy );
846#endif
847
848}  // end store_init()
849
850////////////////////////////////////////////////////////
851static unsigned int split_block( malloc_store_t * store,
852                                 unsigned int     vaddr, 
853                                 unsigned int     searched_index,
854                                 unsigned int     requested_index )
855{
856    // push the upper half block into free[searched_index-1]
857    unsigned int* new            = (unsigned int*)(vaddr + (1<<(searched_index-1)));
858    *new                         = store->free[searched_index-1]; 
859    store->free[searched_index-1] = (unsigned int)new;
860       
861    if ( searched_index == requested_index + 1 )  // terminal case: return lower half block
862    {
863        return vaddr;
864    }
865    else            // non terminal case : lower half block must be split again
866    {                               
867        return split_block( store, vaddr, searched_index-1, requested_index );
868    }
869} // end split_block()
870
871//////////////////////////////////////////////////////
872static unsigned int get_block( malloc_store_t * store,
873                               unsigned int     searched_index,
874                               unsigned int     requested_index )
875{
876    // test terminal case
[473]877    if ( (unsigned int)(1<<searched_index) > store->store_size )  // failure
[445]878    {
879        return 0;
880    }
881    else                            // search a block in free[searched_index]
882    {
883        unsigned int vaddr = store->free[searched_index];
884        if ( vaddr == 0 )     // block not found : search in free[searched_index+1]
885        {
886            return get_block( store, searched_index+1, requested_index );
887        }
888        else                // block found : pop it from free[searched_index]
889        {
890            // pop the block from free[searched_index]
891            unsigned int next = *((unsigned int*)vaddr); 
892            store->free[searched_index] = next;
893           
894            // test if the block must be split
895            if ( searched_index == requested_index )  // no split required
896            {
897                return vaddr;
898            }
899            else                                      // split is required
900            {
901                return split_block( store, vaddr, searched_index, requested_index );
902            }
903        } 
904    }
905} // end get_block()
906
907////////////////////////////////////////
908void * remote_malloc( unsigned int size,
909                      unsigned int cxy )
910{
[573]911    int error;
[445]912
[637]913#if DEBUG_REMOTE_MALLOC
914unsigned int core_cxy;
915unsigned int core_lid;
916get_core_id( &core_cxy , &core_lid );
917printf("\n[%s] core[%x,%d] enter for size = %x / target_cxy = %x\n",
918__FUNCTION__ , core_cxy, core_lid, size , cxy );
[445]919#endif
920
921    // check arguments
922    if( size == 0 )
923    {
924        printf("\n[ERROR] in %s : requested size = 0 \n",
925        __FUNCTION__ );
926        return NULL;
927    }
928    if( cxy >= MALLOC_MAX_CLUSTERS )
929    {
930        printf("\n[ERROR] in %s : illegal cluster %x\n",
931        __FUNCTION__ , cxy );
932        return NULL;
933    }
934
935    // initializes target store if required
936    if( store[cxy].initialized != MALLOC_INITIALIZED )
937    {
938        store_init( cxy , MALLOC_LOCAL_STORE_SIZE );
939
940        if( store[cxy].initialized != MALLOC_INITIALIZED )
941        {
942            printf("\n[ERROR] in %s : cannot allocate store in cluster %x\n",
943            __FUNCTION__ , cxy );
944            return NULL;
945        }
946    }
947
948    // normalize size
949    if ( size < MALLOC_MIN_BLOCK_SIZE ) size = MALLOC_MIN_BLOCK_SIZE;
950
951    // compute requested_index for the free[] array
952    unsigned int requested_index = GET_SIZE_INDEX( size );
953
954    // take the lock protecting access to store[cxy]
[573]955    error = pthread_mutex_lock( &store[cxy].mutex );
[445]956
[573]957    if( error )
958    {
959        printf("\n[ERROR] in %s : cannot take the lock protecting store in cluster %x\n",
960        __FUNCTION__ , cxy );
961        return NULL;
962    }
963
[445]964    // call the recursive function get_block
965    unsigned int base = get_block( &store[cxy], 
966                                   requested_index, 
967                                   requested_index );
968
969    // check block found
970    if (base == 0)
971    {
972        pthread_mutex_unlock( &store[cxy].mutex );
973        printf("\n[ERROR] in %s : no more space in cluster %x\n",
974        __FUNCTION__ , cxy );
975        return NULL;
976    }
977
978    // compute pointer in alloc[] array
979    unsigned        offset = (base - store[cxy].store_base) / MALLOC_MIN_BLOCK_SIZE;
980    unsigned char * ptr    = (unsigned char*)(store[cxy].alloc_base + offset);
981
982    // update alloc_array
983    *ptr = requested_index;
984
985    // release the lock
986    pthread_mutex_unlock( &store[cxy].mutex );
987 
[637]988#if DEBUG_REMOTE_MALLOC
989printf("\n[%s] core[%x,%d] exit / base = %x / size = %x / from store[%x]\n",
990__FUNCTION__, core_cxy, core_lid, base , size , cxy );
[445]991#endif
992
993    return (void*) base;
994
995} // end remote_malloc()
996
997//////////////////////////////////////////
998void * remote_calloc ( unsigned int count,
999                       unsigned int size,
1000                       unsigned int cxy )
1001{
1002    void * ptr = remote_malloc( count * size , cxy );
1003    memset( ptr , 0 , count * size );
1004    return ptr;
1005}
1006
1007//////////////////////////////////
1008void * remote_realloc( void * ptr,
1009                       unsigned int size,
1010                       unsigned int cxy )
1011{
1012    // simple allocation when (ptr == NULL)
1013    if( ptr == NULL )
1014    {
1015        return remote_malloc( size , cxy );
1016    }
1017
1018    // simple free when (size == 0)
1019    if( size == 0 )
1020    {
1021        remote_free( ptr , cxy );
1022        return NULL;
1023    }
1024
1025    // check cxy and ptr in general case
1026    if( cxy >= MALLOC_MAX_CLUSTERS )
1027    {
1028        printf("\n[ERROR] in %s : illegal cluster index %x\n",
1029        __FUNCTION__ , cxy );
1030        return NULL;
1031    }
1032
1033    unsigned int base = (unsigned int)ptr;
1034
1035    if( (base < store[cxy].store_base) || 
1036        (base >= (store[cxy].store_base + store[cxy].store_size)) )
1037    {
1038        printf("\n[ERROR] in %s : illegal pointer = %x\n",
1039        __FUNCTION__, ptr );
1040        return NULL;
1041    }
1042 
1043    // compute index in free[] array
1044    int index = (base - store[cxy].store_base) / MALLOC_MIN_BLOCK_SIZE;
1045
1046    // compute old size
[473]1047    char        * pchar    = (char *) (store[cxy].alloc_base + index);
1048    unsigned int  old_size = (unsigned int)(1 << ((int) *pchar));
[445]1049
1050    // allocate a new block
1051    void * new_ptr = remote_malloc( size , cxy );
1052
1053    // save old data to new block
[473]1054    int min_size = (int)((size < old_size) ? size : old_size);
[445]1055    memcpy( new_ptr, ptr, min_size );
1056
1057    // release old block
1058    remote_free( ptr , cxy );
1059
1060    return new_ptr;
1061
[637]1062}  // end remote_realloc()
1063
1064
[445]1065//////////////////////////////////////////////////////
1066static void update_free_array( malloc_store_t * store,
1067                               unsigned int     base,
1068                               unsigned int     size_index )
1069{
1070    // This recursive function try to merge the released block
1071    // with the companion block if this companion block is free.
1072    // This companion has the same size, and almost the same address
1073    // (only one address bit is different)
1074    // - If the companion is not in free[size_index],
1075    //   the released block is pushed in free[size_index].
1076    // - If the companion is found, it is evicted from free[size_index]
1077    //   and the merged bloc is pushed in the free[size_index+1].
1078
1079
1080    // compute released block size
1081    unsigned int size = 1<<size_index;
1082
1083    // compute companion block and merged block base addresses
1084    unsigned int companion_base; 
1085    unsigned int merged_base; 
1086
1087    if ( (base & size) == 0 )   // the released block is aligned on (2*size)
1088    {
1089        companion_base  = base + size;
1090        merged_base     = base;
1091    }
1092    else
1093    {
1094        companion_base  = base - size;
1095        merged_base     = base - size;
1096    }
1097
1098    // scan all blocks in free[size_index]
1099    // the iter & prev variables are actually addresses
1100    unsigned int  found = 0;
1101    unsigned int  iter  = store->free[size_index];
1102    unsigned int  prev  = (unsigned int)&store->free[size_index];
1103    while ( iter ) 
1104    {
1105        if ( iter == companion_base ) 
1106        {
1107            found = 1;
1108            break;
1109        }
1110        prev = iter;
1111        iter = *(unsigned int*)iter;
1112    }
1113
1114    if ( found == 0 )  // Companion not found => push in free[size_index] 
1115    {
1116        *(unsigned int*)base   = store->free[size_index];
1117        store->free[size_index] = base;
1118    }
1119    else               // Companion found : merge
1120    {
1121        // evict the searched block from free[size_index]
1122        *(unsigned int*)prev = *(unsigned int*)iter;
1123
1124        // call the update_free() function for free[size_index+1]
1125        update_free_array( store, merged_base , size_index+1 );
1126    }
1127}  // end update_free_array()
1128
1129////////////////////////////////////
1130void remote_free( void        * ptr,
1131                  unsigned int  cxy )
1132{
1133
[637]1134#if DEBUG_REMOTE_MALLOC
[445]1135printf("\n[MALLOC] %s : enter for block = %x / cxy = %x\n",
1136__FUNCTION__, ptr, cxy );
1137#endif
1138
1139    unsigned int base = (unsigned int)ptr;
1140
1141    // check cxy value
1142    if( cxy >= MALLOC_MAX_CLUSTERS )
1143    {
1144        printf("\n[ERROR] in %s : illegal cluster index %x\n",
1145        __FUNCTION__ , cxy );
1146        return;
1147    }
1148
1149    // check ptr value
1150    if( (base < store[cxy].store_base) || 
1151        (base >= (store[cxy].store_base + store[cxy].store_size)) )
1152    {
1153        printf("\n[ERROR] in %s : illegal pointer for released block = %x\n",
1154        __FUNCTION__, ptr );
1155        return;
1156    }
1157 
1158    // get the lock protecting store[cxy]
1159    pthread_mutex_lock( &store[cxy].mutex );
1160
1161    // compute released block index in alloc[] array
1162    unsigned index = (base - store[cxy].store_base ) / MALLOC_MIN_BLOCK_SIZE;
1163 
1164    // get the released block size_index
1165    unsigned char* pchar      = (unsigned char*)(store[cxy].alloc_base + index);
1166    unsigned int   size_index = (unsigned int)*pchar;
1167
1168    // check block is allocated
1169    if ( size_index == 0 )
1170    {
1171        pthread_mutex_unlock( &store[cxy].mutex );
1172        printf("\n[ERROR] in %s : released block not allocated / ptr = %x\n",
1173        __FUNCTION__, ptr );
1174        return;
1175    }
1176
1177    // check released block alignment
1178    if ( base % (1 << size_index) )
1179    {
1180        pthread_mutex_unlock( &store[cxy].mutex );
1181        printf("\n[ERROR] in %s : released block not aligned / ptr = %x\n",
1182        __FUNCTION__, ptr );
1183        return;
1184    }
1185
1186    // reset the alloc[index] entry
1187    *pchar = 0;
1188
1189    // call the recursive function update_free_array()
1190    update_free_array( &store[cxy], base, size_index ); 
1191
1192    // release the lock
1193    pthread_mutex_unlock( &store[cxy].mutex );
1194
[637]1195#if DEBUG_REMOTE_MALLOC
[445]1196printf("\n[MALLOC] %s : conmpletes for block = %x / cxy = %x\n",
1197__FUNCTION__, ptr, cxy );
1198#endif
1199
1200} // end remote_free()
1201
[637]1202/////////////////////////////////////////////////////////////////////////////////////////
1203///////////////    non standard pthread_parallel_create    //////////////////////////////
1204/////////////////////////////////////////////////////////////////////////////////////////
1205
1206#define X_MAX                   16              // max number of clusters in a row
1207#define Y_MAX                   16              // max number of clusters in a column
[650]1208#define CLUSTERS_MAX            X_MAX * Y_MAX   // max number of clusters
1209#define LEVEL_MAX               5               // max level of DQT
[637]1210#define CORES_MAX               4               // max number of cores per cluster
1211
1212/////////////////////////////////////////////////////////////////////////////////////////
[650]1213//      Global variables
1214//
1215// WARNING :  arguments of the pthread_create() function MUST be global variables.
[637]1216/////////////////////////////////////////////////////////////////////////////////////////
1217
[650]1218// 2D array of <build> threads attributes / indexed by [cid][level]
1219__attribute__((aligned(4096)))
1220pthread_attr_t                pthread_build_attr[CLUSTERS_MAX][LEVEL_MAX];
[637]1221
[650]1222// 2D array of <build> threads arguments / indexed by [cid][level]
1223__attribute__((aligned(4096)))
1224pthread_parallel_build_args_t pthread_build_args[CLUSTERS_MAX][LEVEL_MAX];
[637]1225
[650]1226// 1D array of <work> threads attributes / indexed by [tid]
1227__attribute__((aligned(4096)))
1228pthread_attr_t                pthread_work_attr[CLUSTERS_MAX * CORES_MAX];
[637]1229
[650]1230// 1D array of <work> threads arguments / indexed by [tid]
1231__attribute__((aligned(4096)))
1232pthread_parallel_work_args_t  pthread_work_args[CLUSTERS_MAX * CORES_MAX];
[637]1233
[650]1234// kernel thread identifier / unused, but required by pthread_create()
1235__attribute__((aligned(4096)))
1236pthread_t                     trdid;
1237
1238///////////////////////////////////////////////////////////////////////////
1239static void pthread_recursive_build( pthread_parallel_build_args_t * args )
[637]1240{
1241
1242    // get arguments
[650]1243    unsigned int         cid               = args->cid;
1244    unsigned int         level             = args->level;
1245    unsigned int         parent_cid        = args->parent_cid;
1246    pthread_barrier_t  * parent_barrier    = args->parent_barrier;
1247    unsigned int         root_level        = args->root_level;
1248    void               * work_func         = args->work_func;
1249    unsigned int         x_size            = args->x_size;
1250    unsigned int         y_size            = args->y_size;
1251    unsigned int         ncores            = args->ncores;
[637]1252
[650]1253#if DEBUG_PTHREAD_PARALLEL
1254printf("\n[%s] <build> thread[%d][%d] enters / parent_cid %d / work_func %x\n",
1255__FUNCTION__, cid , level , parent_cid , work_func );
1256#endif
[637]1257
[650]1258    // set error default value in pthread_build_args[cid][level]
1259    pthread_build_args[cid][level].error = 0;
1260
1261    // get cxy from cid
1262    unsigned int cxy = HAL_CXY_FROM_XY( cid / y_size , cid % y_size );
1263
1264    // allocate the parent/child barrier in local cluster
1265    pthread_barrier_t * barrier = (pthread_barrier_t *)malloc( sizeof(pthread_barrier_t) );
1266
1267    if( barrier == NULL )
1268    {
1269        printf("\n[ERROR] in %s : cannot allocate barrier for <build> thread[%d][%d]\n",
1270        __FUNCTION__ , cid , level );
1271
1272        // report error to parent
1273        pthread_build_args[parent_cid][level+1].error = 1;
1274    }
1275
[637]1276    ///////////////////////////////////////////////////////////
[650]1277    if( level == 0 )             // children are <work> threads
[637]1278    {
1279
[650]1280        // check number of cores in local cluster
1281        unsigned int actual_ncores;
1282        get_nb_cores( cxy , &actual_ncores );
[637]1283
[650]1284        if( actual_ncores != ncores )
[637]1285        {
[650]1286            printf("\n[ERROR] in %s : actual_ncores (%d) in cluster %x\n",
1287            __FUNCTION__ , actual_ncores, cxy );
[637]1288
1289            // report error to parent
[650]1290            pthread_build_args[parent_cid][level+1].error = 1;
[637]1291        }
1292
[650]1293        // initializes barrier for (ncores + 1) in flat mode
1294        if( pthread_barrier_init( barrier , NULL , ncores + 1 ) )
[637]1295        {
[650]1296            printf("\n[ERROR] in %s : cannot init barrier for <build> thread[%d][%d]\n",
1297            __FUNCTION__ , cid , level );
[637]1298
1299            // report error to parent
[650]1300            pthread_build_args[parent_cid][level+1].error = 1;
[637]1301        }
1302
1303#if DEBUG_PTHREAD_PARALLEL
[650]1304printf("\n[%s] <build> thread[%d][%d] initialized barrier / %d children\n",
1305__FUNCTION__, cid, level, ncores );
[637]1306#endif
[650]1307        unsigned int   lid;     // core local index for <work> thread
1308        unsigned int   tid;     // <work> thread continuous index
1309
1310        // <build> thread creates ncores <work> threads
[637]1311        for ( lid = 0 ; lid < ncores ; lid++ )
1312        {
[650]1313            // compute work thread tid
1314            tid = (cid * ncores) + lid;
[637]1315
[650]1316            // set attributes for <work> thread[tid]
1317            pthread_work_attr[tid].attributes = PT_ATTR_DETACH |
1318                                                PT_ATTR_CLUSTER_DEFINED |
1319                                                PT_ATTR_CORE_DEFINED;
1320            pthread_work_attr[tid].cxy        = cxy;
1321            pthread_work_attr[tid].lid        = lid;
[637]1322
[650]1323            // set tid and barrier arguments for <work> thread[tid]
1324            pthread_work_args[tid].tid     = tid;
1325            pthread_work_args[tid].barrier = barrier;
1326
1327            // create <work> thread
[637]1328            if ( pthread_create( &trdid,                  // unused
[650]1329                                 &pthread_work_attr[tid],
[637]1330                                 work_func,
[650]1331                                 &pthread_work_args[tid] ) ) 
[637]1332            {
[650]1333                printf("\n[ERROR] in %s : <build> thread[%d][%d] cannot create <work> thread[%d]\n",
1334                __FUNCTION__ , cid , level , tid );
[637]1335
1336                // report error to parent
[650]1337                pthread_build_args[parent_cid][level+1].error = 1;
[637]1338            }
1339
1340#if DEBUG_PTHREAD_PARALLEL
[650]1341printf("\n[%s] <build> thread[%d][%d] created <work> thread[%d]\n",
1342__FUNCTION__, cid, level, tid );
[637]1343#endif
1344        }
1345
[650]1346        // wait on barrier until all <work> children threads completed
1347        if( pthread_barrier_wait( barrier ) )
[637]1348        {
[650]1349            printf("\n[ERROR] in %s / barrier for <build> thread[%x][%d]\n",
1350            __FUNCTION__ , cid , level );
[637]1351
1352            // report error to parent
[650]1353            pthread_build_args[parent_cid][level+1].error = 1;
[637]1354        }
1355
1356#if DEBUG_PTHREAD_PARALLEL
[650]1357printf("\n[%s] <build> thread[%d][%d] resume after children completion\n",
1358__FUNCTION__ , cid , level );
[637]1359#endif
1360
1361    }  // end level == 0
1362
1363    ////////////////////////////////////////////////////////////
1364    else                        // children are "build" threads
1365    {
[650]1366        // the 4 children threads can be linked to any core in each
1367        // sub-macro-cluster[i][j] with [ij] in {00,01,10,11}
[637]1368
1369        unsigned int parent_x;          // X coordinate of parent macro-cluster
1370        unsigned int parent_y;          // Y coordinate of parent macro-cluster
1371        unsigned int child_x;           // X coordinate of child macro-cluster
1372        unsigned int child_y;           // Y coordinate of child macro-cluster
[650]1373        unsigned int child_cid[2][2];   // selected cluster cid for child[i][j]
1374        unsigned int child_cxy[2][2];   // selected cluster cxy for child[i][j]
1375        unsigned int child_lid[2][2];   // selected core index  for child[i][j]
1376        int          child_sts[2][2];   // -1 if error / 0 if success / +1 if no core
1377        unsigned int i;                 // loop index for children
1378        unsigned int j;                 // loop index for children
[637]1379
[650]1380        unsigned int nb_children = 0;   // actual number of children (can be < 4)
1381
[637]1382        // get parent macro-cluster mask and half-size from level
1383        unsigned int mask = (1 << level) - 1;
1384        unsigned int half = (level > 0) ? (1 << (level - 1)) : 0;
1385
1386        // get parent macro-cluster coordinates
1387        parent_x = HAL_X_FROM_CXY( cxy ) & ~mask;
1388        parent_y = HAL_Y_FROM_CXY( cxy ) & ~mask;
1389
[650]1390        // First step : select core for each child thread
1391        for (i = 0 ; i < 2 ; i++)
[637]1392        {
1393            // compute child macro-cluster X coordinate
[650]1394            child_x = (i == 0) ? parent_x : (parent_x + half);
[637]1395
[650]1396            for (j = 0 ; j < 2 ; j++)
[637]1397            {
1398                // compute child macro-cluster Y coordinate
[650]1399                child_y = (j == 0) ? parent_y : (parent_y + half);
[637]1400
1401                // select the best core in macro-cluster
[650]1402                unsigned int best_cxy;
1403                unsigned int best_lid;
1404
1405                child_sts[i][j] = get_best_core( HAL_CXY_FROM_XY( child_x , child_y ),
[637]1406                                                 level-1,
[650]1407                                                 &best_cxy,
1408                                                 &best_lid );
[637]1409
[650]1410                if( child_sts[i][j] < 0 )  // failure => report error
[637]1411                {
[678]1412                    printf("\n[ERROR] in %s : child[%d,%d] of <build> thread[%d,%d]\n",
[650]1413                    __FUNCTION__ , i , j , cid , level );
[637]1414
1415                    // report error to parent
[650]1416                    pthread_build_args[parent_cid][level+1].error = 1;
[637]1417                }
[650]1418                else if (child_sts[i][j] > 0 )  // macro-cluster empty => does nothing
[637]1419                {
1420                }
1421                else                            // core found
1422                {
[650]1423                    child_cxy[i][j] = best_cxy;
1424                    child_lid[i][j] = best_lid;
1425                    child_cid[i][j] = (HAL_X_FROM_CXY(best_cxy) * y_size) + HAL_Y_FROM_CXY( best_cxy);
[637]1426                    nb_children++;
1427
[650]1428#if DEBUG_PTHREAD_PARALLEL
1429printf("\n[%s] <build> thread[%d][%d] select core[%x][%d] for child[%d][%d]\n",
1430__FUNCTION__ , cid , level , best_cxy , best_lid , i , j );
1431#endif
[637]1432
[650]1433                }
1434            }  // end for j
1435        }  // end for i
[637]1436
[650]1437        // second step : initialize barrier for (nb_children + 1) in flat mode
1438        if( pthread_barrier_init( barrier , NULL , nb_children + 1 ) )
[637]1439        {
[650]1440            printf("\n[ERROR] in %s : cannot init barrier for <build> thread[%d][%d]\n",
1441            __FUNCTION__ , cid , level );
[637]1442
1443            // report error to parent
[650]1444            pthread_build_args[parent_cid][level+1].error = 1;
[637]1445        }
1446
1447#if DEBUG_PTHREAD_PARALLEL
[650]1448printf("\n[%s] <build> thread[%d][%d] initialized barrier / %d children\n",
1449__FUNCTION__, cid, level, nb_children );
[637]1450#endif
[650]1451
1452        // Third step : actually create the children threads
1453        for (i = 0 ; i < 2 ; i++)
[637]1454        {
[650]1455            for (j = 0 ; j < 2 ; j++)
[637]1456            {
1457                // thread is created only if macro-cluster is active
[650]1458                if( child_sts[i][j] == 0 )
[637]1459                {
[650]1460                    unsigned int tgt_cid = child_cid[i][j];
1461                    unsigned int tgt_lid = child_lid[i][j];
1462                    unsigned int tgt_cxy = child_cxy[i][j];
[637]1463
1464                    // set child thread attributes
[650]1465                    pthread_build_attr[tgt_cid][level-1].attributes = PT_ATTR_DETACH |
1466                                                                      PT_ATTR_CLUSTER_DEFINED |
1467                                                                      PT_ATTR_CORE_DEFINED;
1468                    pthread_build_attr[tgt_cid][level-1].cxy        = tgt_cxy;
1469                    pthread_build_attr[tgt_cid][level-1].lid        = tgt_lid;
[637]1470
[650]1471                    // propagate build function arguments from parent to child
1472                    pthread_build_args[tgt_cid][level-1].cid            = tgt_cid;
1473                    pthread_build_args[tgt_cid][level-1].level          = level-1;
1474                    pthread_build_args[tgt_cid][level-1].parent_cid     = cid;
1475                    pthread_build_args[tgt_cid][level-1].parent_barrier = barrier;
1476                    pthread_build_args[tgt_cid][level-1].root_level     = root_level;
1477                    pthread_build_args[tgt_cid][level-1].work_func      = work_func;
1478                    pthread_build_args[tgt_cid][level-1].x_size         = x_size;
1479                    pthread_build_args[tgt_cid][level-1].y_size         = y_size;
1480                    pthread_build_args[tgt_cid][level-1].ncores         = ncores;
[637]1481                   
1482                    // create thread
1483                    if( pthread_create( &trdid,                         
[650]1484                                        &pthread_build_attr[tgt_cid][level-1],   
[637]1485                                        &pthread_recursive_build,                         
[650]1486                                        &pthread_build_args[tgt_cid][level-1] ) )
[637]1487                    {
[650]1488                        printf("\n[ERROR] in %s : cannot create <build> thread[%x][%d]\n",
1489                        __FUNCTION__ , child_cid , level -1 );
[637]1490
1491                        // report error to parent
[650]1492                        pthread_build_args[parent_cid][level+1].error = 1;
[637]1493                    }
1494
1495#if DEBUG_PTHREAD_PARALLEL
[650]1496printf("\n[%s] <build> thread[%d][%d] created <build> thread[%d][%d] on core[%x,%d]\n",
1497__FUNCTION__, cid, level, tgt_cid, (level - 1), tgt_cxy, tgt_lid );
[637]1498#endif
1499                }  //end if sts[x][y]
1500            }  // end for y
1501        }  // end for x
1502       
[650]1503        // wait on barrier until all <build> children threads completed
1504        if( pthread_barrier_wait( barrier ) )
[637]1505        {
[650]1506            printf("\n[ERROR] in %s / barrier for <build> thread[%d][%d]\n",
1507            __FUNCTION__ , cid , level );
[637]1508
1509            // report error to parent
[650]1510            pthread_build_args[parent_cid][level+1].error = 1;
[637]1511        }
1512
1513#if DEBUG_PTHREAD_PARALLEL
1514printf("\n[%s] <build> thread[%x][%d] resume after children completion\n",
[650]1515__FUNCTION__, cid, level );
[637]1516#endif
1517
1518    }  // end level > 0
1519
1520    // report error to parent when required
[650]1521    if( pthread_build_args[cid][level].error )
[637]1522    {
[650]1523        pthread_build_args[parent_cid][level+1].error = 1;
[637]1524    }
1525
[650]1526    // all <build> threads - but the root - signal completion to parent thread and exit
[637]1527    if( level < root_level )
1528    {
[650]1529        if( pthread_barrier_wait( parent_barrier ) )
[637]1530        {
[650]1531            printf("\n[ERROR] in %s / parent barrier for <build> thread[%d][%d]\n",
1532            __FUNCTION__ , cid , level );
[637]1533
1534            // report error to parent
[650]1535            pthread_build_args[parent_cid][level+1].error = 1;
[637]1536        }
1537   
1538#if DEBUG_PTHREAD_PARALLEL
1539printf("\n[%s] <build> thread[%x][%d] exit\n",
[650]1540__FUNCTION__, cid , level );
[637]1541#endif
[650]1542        // <build> thread exit
[637]1543        pthread_exit( NULL );
1544    }
1545}  // end pthread_recursive_build()
1546
[650]1547
1548//////////////////////////////////////////////////////
1549int pthread_parallel_create( unsigned int  root_level,
1550                             void        * work_func )
[637]1551{
[650]1552
[637]1553#if DEBUG_PTHREAD_PARALLEL
[650]1554printf("\n[%s] enter / root_level %d / func %x\n",
1555__FUNCTION__, root_level, work_func );
[637]1556#endif
1557
[650]1558    // get platform parameters
[661]1559    hard_config_t  config;
1560    get_config( &config );
1561    unsigned int   x_size = config.x_size;
1562    unsigned int   y_size = config.y_size;
1563    unsigned int   ncores = config.ncores;
[650]1564
1565    // get calling thread cluster identifier
1566    unsigned int   root_cxy;
1567    unsigned int   root_lid;    // unused, but required by get_core_id()
[637]1568    get_core_id( &root_cxy , &root_lid );
1569
[650]1570    // get calling thread continuous index
1571    unsigned int x        = HAL_X_FROM_CXY( root_cxy );
1572    unsigned int y        = HAL_Y_FROM_CXY( root_cxy );
1573    unsigned int root_cid = (y_size * x) + y; 
1574
[637]1575    // set the build function arguments for the root <build> thread
[650]1576    pthread_build_args[root_cid][root_level].cid               = root_cid; 
1577    pthread_build_args[root_cid][root_level].level             = root_level;
1578    pthread_build_args[root_cid][root_level].parent_cid        = -1;
1579    pthread_build_args[root_cid][root_level].parent_barrier    = NULL;
1580    pthread_build_args[root_cid][root_level].root_level        = root_level;
1581    pthread_build_args[root_cid][root_level].work_func         = work_func;
1582    pthread_build_args[root_cid][root_level].x_size            = x_size;
1583    pthread_build_args[root_cid][root_level].y_size            = y_size;
1584    pthread_build_args[root_cid][root_level].ncores            = ncores;
[637]1585   
[650]1586    // call the recursive function
1587    pthread_recursive_build( &pthread_build_args[root_cid][root_level] );
[637]1588
[650]1589    // check error when execution completes
1590    if( pthread_build_args[root_cid][root_level].error )
[637]1591    {
1592        printf("\n[error] in  %s\n", __FUNCTION__ );
1593        return -1;
1594    }
1595
1596    return 0;
1597
1598}  // end pthread_parallel_create()
1599
[643]1600/////////////////////////////////////////////////////////////////////////////////////////
1601///////////////    non standard Frame Buffer related syscalls
1602/////////////////////////////////////////////////////////////////////////////////////////
[637]1603
[678]1604////////////////////////////////
1605int fbf_get_config( int * width,
1606                    int * height,
1607                    int * type )
[643]1608{
1609    return hal_user_syscall( SYS_FBF,
[657]1610                             (reg_t)FBF_GET_CONFIG, 
[643]1611                             (reg_t)width,
1612                             (reg_t)height,                           
1613                             (reg_t)type );                           
1614}
[637]1615
[678]1616////////////////////////////
1617int fbf_read( void * buffer,
1618              int    length,
1619              int    offset )
[643]1620{
[678]1621    printf("[WARNING] the <%s> syscall is deprecated\n", __FUNCTION__ );
1622
[643]1623    return hal_user_syscall( SYS_FBF,
[657]1624                             (reg_t)FBF_DIRECT_READ, 
[643]1625                             (reg_t)buffer,
1626                             (reg_t)length,                           
1627                             (reg_t)offset );                         
1628}
1629
[678]1630/////////////////////////////
1631int fbf_write( void * buffer,
1632               int    length,
1633               int    offset )
[643]1634{
[678]1635    printf("[WARNING] the <%s> syscall is deprecated\n", __FUNCTION__ );
1636
[643]1637    return hal_user_syscall( SYS_FBF,
[657]1638                             (reg_t)FBF_DIRECT_WRITE,
[643]1639                             (reg_t)buffer,
1640                             (reg_t)length,                           
1641                             (reg_t)offset );   
1642}
1643
[678]1644//////////////////////////////////////
1645int fbf_create_window( int     l_zero,
1646                       int     p_zero,
1647                       int     nlines,
1648                       int     npixels,
1649                       void ** buffer )
[657]1650{
1651    return hal_user_syscall( SYS_FBF,
1652                             (reg_t)FBF_CREATE_WINDOW,
1653                             (reg_t)((l_zero << 16) | p_zero),
1654                             (reg_t)((nlines << 16) | npixels),
1655                             (reg_t)buffer );
1656}
[643]1657
[678]1658///////////////////////////////
1659int fbf_active_window( int wid,
1660                       int active )
[657]1661{
[678]1662    return hal_user_syscall( SYS_FBF, 
1663                             (reg_t)FBF_ACTIVE_WINDOW,
1664                             (reg_t)wid,
1665                             (reg_t)active, 0 );
1666}
1667
1668/////////////////////////////////
1669int fbf_delete_window( int  wid )
1670{
[657]1671    return hal_user_syscall( SYS_FBF,
1672                             (reg_t)FBF_DELETE_WINDOW,
1673                             (reg_t)wid, 0, 0 );
1674}
1675
[678]1676//////////////////////////////
1677int fbf_move_window( int  wid,
1678                     int  l_zero,
1679                     int  p_zero )
[657]1680{
1681    return hal_user_syscall( SYS_FBF,
1682                             (reg_t)FBF_MOVE_WINDOW,
1683                             (reg_t)wid,
1684                             (reg_t)l_zero,
1685                             (reg_t)p_zero );
1686}
1687
[678]1688////////////////////////////////
1689int fbf_resize_window( int  wid,
1690                       int  width,
1691                       int  height )
[657]1692{
1693    return hal_user_syscall( SYS_FBF,
1694                             (reg_t)FBF_RESIZE_WINDOW,
1695                             (reg_t)wid,
1696                             (reg_t)width,
1697                             (reg_t)height );
1698}
1699
[678]1700/////////////////////////////////
1701int fbf_refresh_window( int  wid,
1702                        int  line_first,
1703                        int  line_last )
[657]1704{
1705    return hal_user_syscall( SYS_FBF,
1706                             (reg_t)FBF_REFRESH_WINDOW,
1707                             (reg_t)wid,
1708                             (reg_t)line_first,
1709                             (reg_t)line_last );
1710}
1711
[678]1712/////////////////////////////////
1713int fbf_front_window( int   wid )
1714{
1715    return hal_user_syscall( SYS_FBF,
1716                             (reg_t)FBF_FRONT_WINDOW,
1717                             (reg_t)wid, 0, 0 );
1718}
[657]1719
[445]1720// Local Variables:
1721// tab-width: 4
1722// c-basic-offset: 4
1723// c-file-offsets:((innamespace . 0)(inline-open . 0))
1724// indent-tabs-mode: nil
1725// End:
1726// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1727
1728
1729
Note: See TracBrowser for help on using the repository browser.