source: trunk/libs/libalmosmkh/almosmkh.c

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

Introduce the display_socket() function.

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