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

Last change on this file since 641 was 641, checked in by alain, 3 years ago
  • Fix several bugs.
  • Introduce the "stat" command in KSH.

This almos-mkh version sucessfully executed the FFT application
(65536 complex points) on the TSAR architecture from 1 to 64 cores.

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