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

Last change on this file since 657 was 657, checked in by alain, 23 months ago

Introduce remote_buf.c/.h & socket.c/.h files.
Update dev_nic.c/.h files.

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