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

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

Introduce the display_socket() function.

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