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

Last change on this file since 661 was 661, checked in by alain, 4 years ago

Introduce the non-standatd display_socket() syscall.
Improve the non-standard get_string() syscall.

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