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

Last change on this file since 678 was 678, checked in by alain, 18 months ago

Introduce the fget_string() function.

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