Ignore:
Timestamp:
Oct 1, 2015, 4:20:46 PM (9 years ago)
Author:
alain
Message:

Major release: Change the task model to implement the POSIX threads API.

  • The shell "exec" and "kill" commands can be used to activate/de-activate the applications.
  • The "pause", "resume", and "context" commands can be used to stop, restart, a single thtead or to display the thread context.

This version has been tested on the following multi-threaded applications,
that have been modified to use the POSIX threads:

  • classif
  • convol
  • transpose
  • gameoflife
  • raycast
File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/giet_kernel/sys_handler.c

    r707 r709  
    2626#include <io.h>
    2727
     28#if !defined(X_SIZE)
     29# error: You must define X_SIZE in the hard_config.h file
     30#endif
     31
     32#if !defined(Y_SIZE)
     33# error: You must define Y_SIZE in the hard_config.h file
     34#endif
     35
     36#if !defined(NB_PROCS_MAX)
     37# error: You must define NB_PROCS_MAX in the hard_config.h file
     38#endif
     39
    2840#if !defined(SEG_BOOT_MAPPING_BASE)
    2941# error: You must define SEG_BOOT_MAPPING_BASE in the hard_config.h file
     
    7587extern unsigned int   _coproc_mode[X_SIZE*Y_SIZE];
    7688extern unsigned int   _coproc_error[X_SIZE*Y_SIZE];
    77 extern unsigned int   _coproc_gtid[X_SIZE*Y_SIZE];
    78 
     89extern unsigned int   _coproc_trdid[X_SIZE*Y_SIZE];
    7990
    8091// allocated in tty_driver.c file.
    81 extern unsigned int _tty_rx_full[NB_TTY_CHANNELS];
    82 extern unsigned int _tty_rx_buf[NB_TTY_CHANNELS];
     92extern tty_fifo_t   _tty_rx_fifo[NB_TTY_CHANNELS];
    8393
    8494// allocated in kernel_init.c file
    8595extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
    8696
    87 ////////////////////////////////////////////////////////////////////////////
    88 //     Channel allocators for peripherals
    89 //     (TTY[0] is reserved for kernel)
    90 ////////////////////////////////////////////////////////////////////////////
    91 
     97////////////////////////////////////////////////////////////////////////////////
     98//     Channel allocators for multi-channels peripherals
     99// - The array _***_channel_allocator[channel] defines the number of user
     100//   threads for a dynamically allocated channel of peripheral ***.
     101// - The array _***_channel_wti[channel] defines the WTI index and the
     102//   processor coordinates for the processor receiving the channel WTI.
     103////////////////////////////////////////////////////////////////////////////////
     104
     105#if NB_TTY_CHANNELS
    92106__attribute__((section(".kdata")))
    93 unsigned int _tty_channel[NB_TTY_CHANNELS]  = {1};
     107unsigned int _tty_channel_alloc[NB_TTY_CHANNELS] = {0};
    94108
    95109__attribute__((section(".kdata")))
    96 unsigned int _tim_channel_allocator    = 0;
    97 
     110unsigned int _tty_channel_wti[NB_TTY_CHANNELS];
     111#endif
     112
     113#if NB_TIM_CHANNELS
    98114__attribute__((section(".kdata")))
    99 unsigned int _cma_channel[NB_CMA_CHANNELS] = {0};
     115unsigned int _tim_channel_alloc[NB_TIM_CHANNELS] = {0};
    100116
    101117__attribute__((section(".kdata")))
    102 unsigned int _nic_rx_channel_allocator = 0;
    103 
     118unsigned int _tim_channel_wti[NB_TIM_CHANNELS];
     119#endif
     120
     121#if NB_CMA_CHANNELS
    104122__attribute__((section(".kdata")))
    105 unsigned int _nic_tx_channel_allocator = 0;
     123unsigned int _cma_channel_alloc[NB_CMA_CHANNELS] = {0};
     124
     125__attribute__((section(".kdata")))
     126unsigned int _cma_channel_wti[NB_CMA_CHANNELS];
     127#endif
     128
     129#if NB_NIC_CHANNELS
     130__attribute__((section(".kdata")))
     131unsigned int _nic_rx_channel_alloc[NB_NIC_CHANNELS] = {0};
     132
     133__attribute__((section(".kdata")))
     134unsigned int _nic_rx_channel_wti[NB_NIC_CHANNELS];
     135
     136__attribute__((section(".kdata")))
     137unsigned int _nic_tx_channel_alloc[NB_NIC_CHANNELS] = {0};
     138
     139__attribute__((section(".kdata")))
     140unsigned int _nic_tx_channel_wti[NB_NIC_CHANNELS];
     141#endif
    106142
    107143////////////////////////////////////////////////////////////////////////////
     
    140176    &_sys_proc_xyp,                  /* 0x00 */
    141177    &_get_proctime,                  /* 0x01 */
    142     &_sys_tty_write,                 /* 0x02 */
    143     &_sys_tty_read,                  /* 0x03 */
    144     &_sys_tty_alloc,                 /* 0x04 */
    145     &_sys_tasks_status,              /* 0x05 */
     178    &_sys_procs_number,              /* 0x02 */
     179    &_sys_xy_from_ptr,               /* 0x03 */
     180    &_sys_ukn,                       /* 0x04 */
     181    &_sys_ukn,                       /* 0x05 */
    146182    &_sys_ukn,                       /* 0x06 */
    147183    &_sys_heap_info,                 /* 0x07 */
    148     &_sys_local_task_id,             /* 0x08 */
    149     &_sys_global_task_id,            /* 0x09 */
     184    &_sys_vseg_get_vbase,            /* 0x08 */
     185    &_sys_vseg_get_length,           /* 0x09 */
    150186    &_sys_fbf_cma_alloc,             /* 0x0A */
    151187    &_sys_fbf_cma_init_buf,          /* 0x0B */
     
    153189    &_sys_fbf_cma_display,           /* 0x0D */
    154190    &_sys_fbf_cma_stop,              /* 0x0E */
    155     &_sys_task_exit,                 /* 0x0F */
    156 
    157     &_sys_procs_number,              /* 0x10 */
     191    &_sys_ukn,                       /* 0x0F */
     192
     193    &_sys_applications_status,       /* 0x10 */
    158194    &_sys_fbf_sync_write,            /* 0x11 */
    159195    &_sys_fbf_sync_read,             /* 0x12 */
    160     &_sys_thread_id,                 /* 0x13 */
     196    &_sys_ukn,                       /* 0x13 */
    161197    &_sys_tim_alloc,                 /* 0x14 */
    162198    &_sys_tim_start,                 /* 0x15 */
     
    164200    &_sys_kill_application,          /* 0x17 */
    165201    &_sys_exec_application,          /* 0x18 */   
    166     &_sys_context_switch,            /* 0x19 */
    167     &_sys_vseg_get_vbase,            /* 0x1A */
    168     &_sys_vseg_get_length,           /* 0x1B */
    169     &_sys_xy_from_ptr,               /* 0x1C */
    170     &_sys_ukn,                       /* 0x1D */
    171     &_sys_ukn,                       /* 0x1E */
    172     &_sys_ukn,                       /* 0x1F */
     202    &_sys_ukn,                       /* 0x19 */
     203    &_sys_pthread_control,           /* 0x1A */
     204    &_sys_pthread_yield,             /* 0x1B */
     205    &_sys_pthread_kill,              /* 0x1C */
     206    &_sys_pthread_create,            /* 0x1D */
     207    &_sys_pthread_join,              /* 0x1E */
     208    &_sys_pthread_exit,              /* 0x1F */
    173209
    174210    &_fat_open,                      /* 0x20 */
    175     &_sys_fat_read,                  /* 0x21 */
     211    &_fat_read,                      /* 0x21 */
    176212    &_fat_write,                     /* 0x22 */
    177213    &_fat_lseek,                     /* 0x23 */
     
    195231    &_sys_nic_stats,                 /* 0x34 */
    196232    &_sys_nic_clear,                 /* 0x35 */
    197     &_sys_ukn,                       /* 0x36 */
    198     &_sys_ukn,                       /* 0x37 */
    199     &_sys_ukn,                       /* 0x38 */   
     233    &_sys_tty_write,                 /* 0x36 */
     234    &_sys_tty_read,                  /* 0x37 */
     235    &_sys_tty_alloc,                 /* 0x38 */
    200236    &_sys_ukn,                       /* 0x39 */
    201237    &_sys_ukn,                       /* 0x3A */
     
    207243};
    208244
     245
     246//////////////////////////////////////////////////////////////////////////////
     247//           Applications related syscall handlers
     248//////////////////////////////////////////////////////////////////////////////
     249
     250////////////////////////////////////////////////////////////////////////
     251// This function is called by the _sys_exec_application function
     252// to reload all data segments contained in an application.elf file.
    209253////////////////////////////////////////////////////////////////////////
    210254static unsigned int _load_writable_segments( mapping_vspace_t*  vspace )
    211255{
    212 #if GIET_DEBUG_SWITCH
     256
     257#if GIET_DEBUG_EXEC 
    213258unsigned int gpid       = _get_procid();
    214259unsigned int cluster_xy = gpid >> P_WIDTH;
     
    216261unsigned int x          = cluster_xy >> Y_WIDTH;
    217262unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
    218 if ( _get_proctime() > GIET_DEBUG_SWITCH )
    219 _printf("\n[DEBUG SWITCH] P[%d,%d,%d] _load_writable_segments() : enters for %s\n",
    220         x , y , p , vspace->name );
     263if ( _get_proctime() > GIET_DEBUG_EXEC )
     264_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
     265        "enters for %s\n", x , y , p , vspace->name );
    221266#endif
    222267
     
    224269    mapping_vseg_t*    vseg    = _get_vseg_base(header);
    225270
    226     // buffer to store one cluster
    227     char  buf[4096];
    228 
    229     // open the .elf file associated to vspace
    230     unsigned int      vseg_id;
    231     unsigned int      fd = 0;
    232 
     271    unsigned int vseg_id;        // vseg index in mapping
     272    char         buf[4096];      // buffer to store one cluster
     273    unsigned int fd = 0;         // file descriptor
     274
     275    // first scan on vsegs in vspace to find the .elf pathname
    233276    for (vseg_id = vspace->vseg_offset;
    234277         vseg_id < (vspace->vseg_offset + vspace->vsegs);
    235278         vseg_id++)
    236279    {
    237         if(vseg[vseg_id].type == VSEG_TYPE_ELF)
     280        if( vseg[vseg_id].type == VSEG_TYPE_ELF )
    238281        {
     282            // open the .elf file associated to vspace
    239283            fd = _fat_open( vseg[vseg_id].binpath , O_RDONLY );
    240 
    241 #if GIET_DEBUG_SWITCH
    242 if ( _get_proctime() > GIET_DEBUG_SWITCH )
    243 _printf("\n[DEBUG SWITCH] P[%d,%d,%d] _load_writable_segments() : open %s / fd = %d\n",
    244         x , y , p , vseg[vseg_id].binpath , fd );
    245 #endif
    246 
    247284            if ( fd < 0 ) return 1;
    248285            break;
     286
     287#if GIET_DEBUG_EXEC
     288if ( _get_proctime() > GIET_DEBUG_EXEC )
     289_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
     290        "open %s / fd = %d\n", x , y , p , vseg[vseg_id].binpath , fd );
     291#endif
    249292        }
    250293    }
    251 
     294 
    252295    // load Elf-Header into buffer from .elf file
    253     if ( _fat_lseek( fd, 0, SEEK_SET ) < 0 ) return 1;
    254     if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 ) return 1;
    255 
    256 #if GIET_DEBUG_SWITCH
    257 if ( _get_proctime() > GIET_DEBUG_SWITCH )
    258 _printf("\n[DEBUG SWITCH] P[%d,%d,%d] _load_writable_segments() : load Elf-Header\n",
    259         x , y , p );
     296    if ( _fat_lseek( fd, 0, SEEK_SET ) < 0 )
     297    {
     298        _fat_close( fd );
     299        return 1;
     300    }
     301    if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 )
     302    {
     303        _fat_close( fd );
     304        return 1;
     305    }
     306
     307#if GIET_DEBUG_EXEC
     308if ( _get_proctime() > GIET_DEBUG_EXEC )
     309_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
     310        "loaded Elf-Header\n", x , y , p );
    260311#endif
    261312
     
    266317
    267318    // load Program-Header-Table from .elf file
    268     if ( _fat_lseek( fd, offset, SEEK_SET ) < 0 ) return 1;
    269     if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 ) return 1;
    270 
    271 #if GIET_DEBUG_SWITCH
    272 if ( _get_proctime() > GIET_DEBUG_SWITCH )
    273 _printf("\n[DEBUG SWITCH] P[%d,%d,%d] _load_writable_segments() : "
    274         "load Program-Header-Table\n", x , y , p );
     319    if ( _fat_lseek( fd, offset, SEEK_SET ) < 0 )
     320    {
     321        _fat_close( fd );
     322        return 1;
     323    }
     324    if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 )
     325    {
     326        _fat_close( fd );
     327        return 1;
     328    }
     329
     330#if GIET_DEBUG_EXEC
     331if ( _get_proctime() > GIET_DEBUG_EXEC )
     332_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
     333        "loaded Program-Header-Table\n", x , y , p );
    275334#endif
    276335
     
    278337    Elf32_Phdr*  elf_pht_ptr = (Elf32_Phdr*)buf;
    279338
    280     // scan segments to  load all loadable & writable segments
    281     unsigned int seg_id;
    282     for (seg_id = 0 ; seg_id < nsegments ; seg_id++)
    283     {
    284         if ( (elf_pht_ptr[seg_id].p_type == PT_LOAD) &&    // loadable
    285              (elf_pht_ptr[seg_id].p_flags & PF_W) )        // writable
     339    // second scan on vsegs in vspace to load the seg_data segments :
     340    // - type == VSEG_TYPE_ELF
     341    // - non eXecutable
     342    for (vseg_id = vspace->vseg_offset;
     343         vseg_id < (vspace->vseg_offset + vspace->vsegs);
     344         vseg_id++)
     345    {
     346        if( (vseg[vseg_id].type == VSEG_TYPE_ELF) &&   // type ELF
     347            ((vseg[vseg_id].mode & 0x4) == 0) )        // non executable
    286348        {
    287             // Get segment attributes
    288             paddr_t      seg_paddr  = vseg[vseg_id].pbase;
    289             unsigned int seg_offset = elf_pht_ptr[seg_id].p_offset;
    290             unsigned int seg_size   = elf_pht_ptr[seg_id].p_filesz;
    291 
    292             // load the segment
    293             if ( _fat_lseek( fd, seg_offset, SEEK_SET ) < 0 ) return 1;
    294             if ( _fat_read( fd, seg_paddr, seg_size, 1 ) < 0 ) return 1;
    295 
    296 #if GIET_DEBUG_SWITCH
    297 if ( _get_proctime() > GIET_DEBUG_SWITCH )
    298 _printf("\n[DEBUG SWITCH] P[%d,%d,%d] _load_writable_segments() : load segment %x\n",
    299         x , y , p , seg_vaddr );
     349            // get vbase and pbase
     350            paddr_t      pbase = vseg[vseg_id].pbase;
     351            unsigned int vbase = vseg[vseg_id].vbase;
     352
     353            // scan segments in Progam-Header-Table to find match
     354            // No match checking as the segment was previously found
     355            unsigned int seg;
     356            for (seg = 0 ; seg < nsegments ; seg++)
     357            {
     358                if ( (elf_pht_ptr[seg].p_type == PT_LOAD) &&    // loadable
     359                     (elf_pht_ptr[seg].p_flags & PF_W)    &&    // writable
     360                     (elf_pht_ptr[seg].p_vaddr == vbase) )      // matching
     361                {
     362                    // Get segment offset and size in .elf file
     363                    unsigned int seg_offset = elf_pht_ptr[seg].p_offset;
     364                    unsigned int seg_size   = elf_pht_ptr[seg].p_filesz;
     365
     366                    // compute destination address and extension for _fat_read()
     367                    unsigned int dest   = (unsigned int)pbase;
     368                    unsigned int extend = (unsigned int)(pbase>>32) | 0xFFFF0000;
     369
     370                    // load the segment
     371                    if ( _fat_lseek( fd, seg_offset, SEEK_SET ) < 0 )
     372                    {
     373                        _fat_close( fd );
     374                        return 1;
     375                    }
     376                    if ( _fat_read( fd, dest, seg_size, extend ) < 0 )
     377                    {
     378                        _fat_close( fd );
     379                        return 1;
     380                    }
     381                }
     382            }
     383
     384#if GIET_DEBUG_EXEC
     385if ( _get_proctime() > GIET_DEBUG_EXEC )
     386_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
     387        "loaded segment %x\n", x , y , p , vbase );
    300388#endif
    301389        }
     
    308396}  // end load_writable_segments()
    309397
    310 //////////////////////////////////////////////////////////////////////////////
    311 //           Applications related syscall handlers
    312 //////////////////////////////////////////////////////////////////////////////
     398
     399
     400///////////////////////////////////////
     401int _sys_exec_application( char* name )
     402{
     403    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     404    mapping_vspace_t * vspace  = _get_vspace_base(header);
     405    mapping_thread_t * thread  = _get_thread_base(header);
     406    mapping_vseg_t   * vseg    = _get_vseg_base(header);
     407
     408    unsigned int vspace_id;
     409    unsigned int thread_id;
     410
     411#if GIET_DEBUG_EXEC
     412unsigned int gpid       = _get_procid();
     413unsigned int cluster_xy = gpid >> P_WIDTH;
     414unsigned int p          = gpid & ((1<<P_WIDTH)-1);
     415unsigned int x          = cluster_xy >> Y_WIDTH;
     416unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
     417if ( _get_proctime() > GIET_DEBUG_EXEC )
     418_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
     419        "enters for %s at cycle %d\n", x, y, p, name, _get_proctime() );
     420#endif
     421
     422    unsigned int y_size = header->y_size;
     423
     424    // scan vspaces to find matching vspace name
     425    for (vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++)
     426    {
     427        if ( _strcmp( vspace[vspace_id].name, name ) == 0 )  // vspace found
     428        {
     429
     430#if GIET_DEBUG_EXEC
     431if ( _get_proctime() > GIET_DEBUG_EXEC )
     432_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
     433        "found vspace %s at cycle  %d\n", x, y, p, name, _get_proctime() );
     434#endif
     435            // reload writable segments
     436            if ( _load_writable_segments( &vspace[vspace_id] ) )
     437            {
     438                _printf("[GIET ERROR] _sys_exec_application() : "
     439                        "can't load data segment for vspace %s\n", name );
     440                return GIET_SYSCALL_CANNOT_LOAD_DATA_SEGMENT;
     441            }
     442 
     443#if GIET_DEBUG_EXEC
     444if ( _get_proctime() > GIET_DEBUG_EXEC )
     445_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
     446        "load segments for vspace %s at cycle  %d\n", x, y, p, name, _get_proctime() );
     447#endif
     448            // scan threads in vspace with three goals :
     449            // - check all threads desactivated
     450            // - re-initialise all threads contexts
     451            // - find main thread
     452            unsigned int        main_found  = 0;
     453            unsigned int        main_ltid   = 0;
     454            static_scheduler_t* main_psched = NULL;
     455            unsigned int        min         = vspace[vspace_id].thread_offset;
     456            unsigned int        max         = min + vspace[vspace_id].threads;
     457            for ( thread_id = min ; thread_id < max ; thread_id++ )
     458            {
     459                // get thread identifiers : [x,y,p,ltid]
     460                unsigned int cid   = thread[thread_id].clusterid;
     461                unsigned int x     = cid / y_size;
     462                unsigned int y     = cid % y_size;
     463                unsigned int p     = thread[thread_id].proclocid;
     464                unsigned int ltid  = thread[thread_id].ltid;
     465                unsigned int vsid  = thread[thread_id].stack_vseg_id;
     466
     467                // get scheduler pointer
     468                static_scheduler_t* psched = _schedulers[x][y][p];
     469
     470                // check thread non active
     471                if ( psched->context[ltid].slot[CTX_NORUN_ID] == 0 )  // runnable !!!
     472                {
     473                    _printf("\n[GIET ERROR] in _sys_exec_application() : "
     474                            "thread %s already active in vspace %s\n",
     475                            thread[thread_id].name, name );
     476                    return GIET_SYSCALL_THREAD_ALREADY_ACTIVE;
     477                }
     478               
     479                // initialise thread context
     480                unsigned int ctx_epc = psched->context[ltid].slot[CTX_ENTRY_ID];
     481                unsigned int ctx_sp  = vseg[vsid].vbase + vseg[vsid].length;
     482                unsigned int ctx_ra  = (unsigned int)&_ctx_eret;
     483                unsigned int ctx_sr  = GIET_SR_INIT_VALUE;
     484
     485                psched->context[ltid].slot[CTX_EPC_ID] = ctx_epc;
     486                psched->context[ltid].slot[CTX_RA_ID]  = ctx_ra;
     487                psched->context[ltid].slot[CTX_SR_ID]  = ctx_sr;
     488                psched->context[ltid].slot[CTX_SP_ID]  = ctx_sp;
     489
     490                // register information required to activate main thread
     491                // actual activation done when threads initialisation is completed
     492                if ( thread[thread_id].is_main )
     493                {
     494                    main_psched = psched;
     495                    main_ltid   = ltid;
     496                    main_found  = 1;
     497                }
     498 
     499#if GIET_DEBUG_EXEC
     500if ( _get_proctime() > GIET_DEBUG_EXEC )
     501_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
     502        "initialise thread %s at cycle  %d\n",
     503        x, y, p, thread[thread_id].name, _get_proctime() );
     504#endif
     505            }  // end loop on vspace threads
     506
     507            // activate main thread
     508            if ( main_found )
     509            {
     510                main_psched->context[main_ltid].slot[CTX_NORUN_ID] = 0;
     511            }
     512            else
     513            {
     514                _printf("\n[GIET ERROR] in _sys_exec_application() : "
     515                        "main not found in vspace %s\n", name );
     516                return GIET_SYSCALL_MAIN_NOT_FOUND;
     517            }
     518             
     519#if GIET_DEBUG_EXEC
     520if ( _get_proctime() > GIET_DEBUG_EXEC )
     521_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
     522        "lauched %s at cycle %d\n", x, y, p, name, _get_proctime() );
     523#endif
     524            return GIET_SYSCALL_OK;
     525        }
     526    }  // end of loop on vspaces
     527
     528    // vspace not found
     529    _printf("\n[GIET ERROR] in _sys_exec_application() : "
     530            "vspace %s not found\n", name );
     531    return GIET_SYSCALL_VSPACE_NOT_FOUND;
     532
     533}  // end _sys_exec_application()
     534   
    313535
    314536///////////////////////////////////////
     
    317539    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
    318540    mapping_vspace_t * vspace  = _get_vspace_base(header);
    319     mapping_task_t   * task    = _get_task_base(header);
     541    mapping_thread_t * thread  = _get_thread_base(header);
    320542
    321543    unsigned int vspace_id;
    322     unsigned int task_id;
    323     unsigned int y_size = header->y_size;
     544    unsigned int thread_id;
    324545
    325546#if GIET_DEBUG_EXEC
     547unsigned int gpid       = _get_procid();
     548unsigned int cluster_xy = gpid >> P_WIDTH;
     549unsigned int p          = gpid & ((1<<P_WIDTH)-1);
     550unsigned int x          = cluster_xy >> Y_WIDTH;
     551unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
    326552if ( _get_proctime() > GIET_DEBUG_EXEC )
    327 _printf("\n[DEBUG EXEC] enters _sys_kill_application() for %s\n", name );
    328 #endif
    329 
    330     // scan vspaces
     553_printf("\n[DEBUG EXEC] _sys_kill_application() P[%d,%d,%d] "
     554        "enters at cycle %d for %s\n", x, y, p, _get_proctime() , name );
     555#endif
     556
     557    // shell cannot be killed
     558    if ( _strcmp( name , "shell" ) == 0 )
     559    {
     560        _printf("\n[GIET ERROR] in _sys_kill_application() : "
     561                "%s application cannot be killed\n", name );
     562        return GIET_SYSCALL_APPLI_CANNOT_BE_KILLED;
     563    }
     564
     565    // scan vspaces to find matching vspace name
    331566    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++)
    332567    {
    333568        if ( _strcmp( vspace[vspace_id].name, name ) == 0 )
    334569        {
    335             // check if application can be killed
    336             if ( vspace[vspace_id].active ) return -2;
    337 
    338             // scan tasks in vspace
    339             for (task_id = vspace[vspace_id].task_offset;
    340                  task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
    341                  task_id++)
     570            // scan threads to send KILL signal to all threads in vspace
     571            unsigned int y_size = header->y_size;
     572            unsigned int min    = vspace[vspace_id].thread_offset;
     573            unsigned int max    = min + vspace[vspace_id].threads;
     574            for ( thread_id = min ; thread_id < max ; thread_id++ )
    342575            {
    343                 unsigned int cid   = task[task_id].clusterid;
     576                unsigned int cid   = thread[thread_id].clusterid;
    344577                unsigned int x     = cid / y_size;
    345578                unsigned int y     = cid % y_size;
    346                 unsigned int p     = task[task_id].proclocid;
    347                 unsigned int ltid  = task[task_id].ltid;
    348 
    349                 // get scheduler pointer for processor running the task
     579                unsigned int p     = thread[thread_id].proclocid;
     580                unsigned int ltid  = thread[thread_id].ltid;
     581
     582                // get scheduler pointer for processor running the thread
    350583                static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
    351584
    352585                // set KILL signal bit
    353                 _atomic_or( &psched->context[ltid][CTX_SIG_ID] , SIG_MASK_KILL );
     586                _atomic_or( &psched->context[ltid].slot[CTX_SIGS_ID] , SIGS_MASK_KILL );
    354587            }
    355588
    356589#if GIET_DEBUG_EXEC
    357590if ( _get_proctime() > GIET_DEBUG_EXEC )
    358 _printf("\n[DEBUG EXEC] exit _sys_kill_application() : %s will be killed\n", name );
    359 #endif
    360 
    361             return 0;
     591_printf("\n[DEBUG EXEC] _sys_kill_application() P[%d,%d,%d] "
     592        "kill %s at cycle %d\n", x, y, p, name, _get_proctime() );
     593#endif
     594
     595            return GIET_SYSCALL_OK;
    362596        }
    363     }
     597    }  // en loop on vspaces
     598
     599    _printf("\n[GIET ERROR] in _sys_kill_application() : "
     600            "application %s not found\n", name );
     601    return GIET_SYSCALL_VSPACE_NOT_FOUND;
     602
     603}  // end _sys_kill_application()
     604   
     605
     606
     607//////////////////////////////
     608int _sys_applications_status()
     609{
     610    mapping_header_t *  header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     611    mapping_thread_t *  thread  = _get_thread_base(header);
     612    mapping_vspace_t *  vspace  = _get_vspace_base(header);
     613    mapping_cluster_t * cluster = _get_cluster_base(header);
     614
     615    unsigned int thread_id;
     616    unsigned int vspace_id;
     617
     618    // scan all vspaces
     619    for( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
     620    {
     621        _user_printf("\n*** vspace %s\n", vspace[vspace_id].name );
     622
     623        // scan all threads in vspace
     624        unsigned int min = vspace[vspace_id].thread_offset ;
     625        unsigned int max = min + vspace[vspace_id].threads ;
     626        for ( thread_id = min ; thread_id < max ; thread_id++ )
     627        {
     628            unsigned int         clusterid = thread[thread_id].clusterid;
     629            unsigned int         p         = thread[thread_id].proclocid;
     630            unsigned int         x         = cluster[clusterid].x;
     631            unsigned int         y         = cluster[clusterid].y;
     632            unsigned int         ltid      = thread[thread_id].ltid;
     633            static_scheduler_t*  psched    = (static_scheduler_t*)_schedulers[x][y][p];
     634            unsigned int         norun     = psched->context[ltid].slot[CTX_NORUN_ID];
     635            unsigned int         tty       = psched->context[ltid].slot[CTX_TTY_ID];
     636            unsigned int         current   = psched->current;
     637
     638            if ( current == ltid )
     639            _user_printf(" - thread %s / P[%d,%d,%d] / ltid = %d / "
     640                         "TTY = %d / norun = %x : running\n",
     641                         thread[thread_id].name, x, y, p, ltid, tty, norun );
     642            else if ( norun == 0 )
     643            _user_printf(" - thread %s / P[%d,%d,%d] / ltid = %d / "
     644                         "TTY = %d / norun = %x : runable\n",
     645                         thread[thread_id].name, x, y, p, ltid, tty, norun);
     646            else
     647            _user_printf(" - thread %s / P[%d,%d,%d] / ltid = %d / "
     648                         "TTY = %d / norun = %x : blocked\n",
     649                         thread[thread_id].name, x, y, p, ltid, tty, norun);
     650        }
     651    }
     652    _user_printf("\n");
     653    return GIET_SYSCALL_OK;
     654}  // end _sys_applications_status()
     655
     656
     657
     658/////////////////////////////////////////////////////////////////////////////
     659//          Threads related syscall handlers
     660/////////////////////////////////////////////////////////////////////////////
     661
     662////////////////////////////////////////////////
     663int _sys_pthread_create( unsigned int*  buffer,
     664                         void*          attr,
     665                         void*          function,
     666                         void*          arg )
     667{
     668    // attr argument not supported
     669    if ( attr != NULL )
     670    {
     671        _printf("\n[GIET ERROR] in _sys_pthread_create() : "
     672                "attr argument not supported\n" );
     673       
     674        return GIET_SYSCALL_PTHREAD_ARGUMENT_NOT_SUPPORTED;
     675    }
     676
     677    // get pointers in mapping
     678    mapping_header_t*    header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     679    mapping_thread_t*    thread   = _get_thread_base(header);
     680    mapping_vspace_t*    vspace   = _get_vspace_base(header);
     681    mapping_cluster_t*   cluster  = _get_cluster_base(header);
     682
     683    // get scheduler for processor running the calling thread
     684    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
     685
     686    // get calling thread local index in scheduler
     687    unsigned int  current = psched->current;
     688
     689    // get vspace index
     690    unsigned int  vspace_id = psched->context[current].slot[CTX_VSID_ID];
    364691
    365692#if GIET_DEBUG_EXEC
    366693if ( _get_proctime() > GIET_DEBUG_EXEC )
    367 _printf("\n[DEBUG EXEC] exit _sys_kill_application() : %s not found\n", name );
    368 #endif
    369 
    370     return -1;    // not found
    371 
    372 }  // end _sys_kill_application()
     694_printf("\n[DEBUG EXEC] _sys_pthread_create() : enters at cycle %d"
     695        " for vspace %s / entry = %x\n",
     696        _get_proctime() , vspace[vspace_id].name , (unsigned int)function );
     697#endif
     698
     699    unsigned int thread_id;        // searched thread : local index in mapping
     700    unsigned int clusterid;        // searched thread : cluster index
     701    unsigned int lpid;             // searched thread : processor local index
     702    unsigned int ltid;             // searched thread : scheduler thread index
     703    unsigned int cx;               // searched thread : X coordinate for searched thread
     704    unsigned int cy;               // searched thread : Y coordinate for searched thread
     705    unsigned int entry;            // searched thread : entry point
     706    unsigned int norun;            // searched thread : norun vector
     707    unsigned int trdid;            // searched thread : thread identifier
     708
     709    // scan threads in vspace to find an inactive thread matching function
     710    unsigned int min   = vspace[vspace_id].thread_offset;
     711    unsigned int max   = min + vspace[vspace_id].threads;
     712    unsigned int found = 0;
     713    for ( thread_id = min ; (thread_id < max) && (found == 0) ; thread_id++ )
     714    {
     715        // get thread coordinates [cx,cy,lpid] and ltid from mapping
     716        ltid       = thread[thread_id].ltid;
     717        clusterid  = thread[thread_id].clusterid;
     718        lpid       = thread[thread_id].proclocid;
     719        cx = cluster[clusterid].x;
     720        cy = cluster[clusterid].y;
     721
     722        // get thread scheduler pointer
     723        psched = _schedulers[cx][cy][lpid];
     724
     725        // get thread entry-point, norun-vector, and trdid from context
     726        entry = psched->context[ltid].slot[CTX_ENTRY_ID];
     727        norun = psched->context[ltid].slot[CTX_NORUN_ID];
     728        trdid = psched->context[ltid].slot[CTX_TRDID_ID];
     729
     730        // check matching
     731        if ( ((unsigned int)function == entry ) &&
     732             (norun & NORUN_MASK_THREAD)  ) found = 1;
     733
     734    }  // end loop on threads
     735
     736    if ( found )  // one matching inactive thread has been found
     737    {
     738        // set argument value in thread context
     739        if ( arg != NULL ) psched->context[ltid].slot[CTX_A0_ID] = (unsigned int)arg;
     740
     741        // activate thread
     742        psched->context[ltid].slot[CTX_NORUN_ID] = 0;
     743
     744        // return launched thead global identifier
     745        *buffer   = trdid;
     746               
     747#if GIET_DEBUG_EXEC
     748if ( _get_proctime() > GIET_DEBUG_EXEC )
     749_printf("\n[DEBUG EXEC] exit _sys_pthread_create() at cycle %d : thread %x launched\n",
     750        _get_proctime() , trdid);
     751#endif
     752        return GIET_SYSCALL_OK;
     753    }
     754    else         // no matching thread found
     755    {
     756        _printf("\n[GIET ERROR] in _sys_pthread_create() : "
     757                "no matching thread for entry = %x in vspace %s\n",
     758                (unsigned int)function , vspace[vspace_id].name );
     759       
     760        return GIET_SYSCALL_THREAD_NOT_FOUND;
     761    }
     762
     763} // end _sys_pthread_create()
     764
     765
     766///////////////////////////////////////////
     767int _sys_pthread_join( unsigned int  trdid,
     768                       void*         ptr )
     769{
     770    // ptr argument not supported
     771    if ( ptr != NULL )
     772    {
     773        _printf("\n[GIET ERROR] in _sys_pthread_join() : "
     774                "ptr argument not supported, must be NULL\n" );
     775       
     776        return GIET_SYSCALL_PTHREAD_ARGUMENT_NOT_SUPPORTED;
     777    }
     778
     779               
     780#if GIET_DEBUG_EXEC
     781if ( _get_proctime() > GIET_DEBUG_EXEC )
     782_printf("\n[DEBUG EXEC] enters _sys_pthread_join() at cycle %d for thread %x\n",
     783        _get_proctime() , trdid );
     784#endif
     785
     786    // get calling thread vspace
     787    unsigned int  caller_vspace = _get_context_slot( CTX_VSID_ID );
     788
     789    // get and check target thread indexes from trdid
     790    unsigned int cx   = (trdid>>24) & 0xFF;
     791    unsigned int cy   = (trdid>>16) & 0xFF;
     792    unsigned int lpid = (trdid>>8 ) & 0xFF;
     793    unsigned int ltid = (trdid    ) & 0xFF;
     794
     795    // get target thread scheduler, vspace and registered trdid
     796    static_scheduler_t*  psched   = _schedulers[cx][cy][lpid];
     797    unsigned int target_vspace    = psched->context[ltid].slot[CTX_VSID_ID];
     798    unsigned int registered_trdid = psched->context[ltid].slot[CTX_TRDID_ID];
     799
     800    // check trdid
     801    if ( trdid != registered_trdid )
     802    {
     803       _printf("\nerror in _sys_pthread_join() : "
     804               "trdid = %x / registered_trdid = %x\n",
     805               trdid , registered_trdid );
     806
     807       return GIET_SYSCALL_UNCOHERENT_THREAD_CONTEXT;
     808    }
     809   
     810    // check calling thread and target thread in same vspace
     811    if ( caller_vspace != target_vspace )
     812    {
     813       _printf("\n[GIET ERROR] in _sys_pthread_join() : "
     814               " calling thread and target thread not in same vspace\n");
     815
     816       return GIET_SYSCALL_NOT_IN_SAME_VSPACE;
     817    }
     818
     819    // get target thread state
     820    unsigned int* pnorun = &psched->context[ltid].slot[CTX_NORUN_ID];
     821
     822    asm volatile ( "2000:                      \n"                         
     823                   "move  $11,  %0             \n"   /* $11 <= ptr           */
     824                   "lw    $11,  0($11)         \n"   /* $11 <= M[ptr]        */
     825                   "andi  $11,  $11,    1      \n"   /* $11 <= norun & 0x1   */
     826                   "beqz  $11,  2000b          \n"   
     827                   :
     828                   : "r" (pnorun)
     829                   : "$11" );
     830
     831    return GIET_SYSCALL_OK;
     832
     833}  // end _sys_pthread_join()
     834                       
     835
     836////////////////////////////////////////
     837int _sys_pthread_kill( pthread_t  trdid,
     838                       int        signal )
     839{
     840    // get calling thread vspace
     841    unsigned int  caller_vspace = _get_context_slot( CTX_VSID_ID );
     842
     843    // get and check target thread indexes from trdid
     844    unsigned int cx   = (trdid>>24) & 0xFF;
     845    unsigned int cy   = (trdid>>16) & 0xFF;
     846    unsigned int lpid = (trdid>>8 ) & 0xFF;
     847    unsigned int ltid = (trdid    ) & 0xFF;
     848
     849    // get target thread scheduler, vspace and registered trdid
     850    static_scheduler_t*  psched       = _schedulers[cx][cy][lpid];
     851    unsigned int target_vspace        = psched->context[ltid].slot[CTX_VSID_ID];
     852    unsigned int registered_trdid = psched->context[ltid].slot[CTX_TRDID_ID];
     853
     854    // check trdid
     855    if ( trdid != registered_trdid )
     856    {
     857       _printf("\n[GIET ERROR] in _sys_pthread_kill() : trdid = %x"
     858               " / registered_trdid = %x\n", trdid , registered_trdid );
     859       return GIET_SYSCALL_UNCOHERENT_THREAD_CONTEXT;
     860    }
     861   
     862    // check calling thread and target thread in same vspace
     863    if ( caller_vspace != target_vspace )
     864    {
     865       _printf("\n[GIET ERROR] in _sys_pthread_kill() : not in same vspace\n");
     866       return GIET_SYSCALL_NOT_IN_SAME_VSPACE;
     867    }
     868
     869    // register KILL signal in target thread context if required
     870    if ( signal )
     871    {
     872        _atomic_or( &psched->context[ltid].slot[CTX_SIGS_ID] , SIGS_MASK_KILL );
     873    }
     874
     875    return GIET_SYSCALL_OK;
     876
     877}  // end _sys_pthread_kill()
     878
     879
     880/////////////////////////////////////
     881int _sys_pthread_exit( void* string )
     882{
     883    unsigned int date       = _get_proctime();
     884
     885    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     886    mapping_vspace_t * vspace  = _get_vspace_base(header);
     887
     888    unsigned int ltid       = _get_context_slot(CTX_LTID_ID);
     889    unsigned int trdid      = _get_context_slot(CTX_TRDID_ID);
     890    unsigned int vsid       = _get_context_slot(CTX_VSID_ID);
     891
     892    // print exit message
     893    if ( string == NULL )
     894    {
     895        _printf("\n[GIET WARNING] Exit thread %x in vspace %s at cycle %d\n",
     896                trdid , vspace[vsid].name , date );
     897    }
     898    else
     899    {
     900        _printf("\n[GIET WARNING] Exit thread %x in vspace %s at cycle %d\n"
     901                "               Cause : %s\n\n",
     902                trdid , vspace[vsid].name , date , (char*) string );
     903    }
    373904   
    374 ///////////////////////////////////////
    375 int _sys_exec_application( char* name )
    376 {
    377     mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
    378     mapping_vseg_t   * vseg    = _get_vseg_base(header);
    379     mapping_vspace_t * vspace  = _get_vspace_base(header);
    380     mapping_task_t   * task    = _get_task_base(header);
    381 
    382     unsigned int vspace_id;
    383     unsigned int task_id;
    384     unsigned int y_size = header->y_size;
    385 
    386 #if GIET_DEBUG_EXEC
     905    // get scheduler pointer for calling thread
     906    static_scheduler_t*  psched = (static_scheduler_t*)_get_sched();
     907
     908    // register KILL signal in calling thread context (suicid request)
     909    _atomic_or( &psched->context[ltid].slot[CTX_SIGS_ID] , SIGS_MASK_KILL );
     910
     911    // deschedule calling thread
     912    unsigned int save_sr; 
     913    _it_disable( &save_sr );
     914
     915    _ctx_switch();
     916
     917    return GIET_SYSCALL_OK;
     918
     919}  // end _sys_pthread_exit()
     920
     921////////////////////////
     922int _sys_pthread_yield()
     923{
     924    unsigned int save_sr;
     925
     926    _it_disable( &save_sr );
     927    _ctx_switch();
     928    _it_restore( &save_sr );
     929
     930    return GIET_SYSCALL_OK;
     931}
     932
     933//////////////////////////////////////////////////
     934int _sys_pthread_control( unsigned  int  command,
     935                          char*     vspace_name,
     936                          char*     thread_name )
     937{
     938
     939#if GIET_DEBUG_EXEC
    387940if ( _get_proctime() > GIET_DEBUG_EXEC )
    388 _printf("\n[DEBUG EXEC] enters _sys_exec_application() at cycle %d for %s\n",
    389          _get_proctime() , name );
    390 #endif
    391 
    392     // find vspace
    393     for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
    394     {
    395         if ( _strcmp( vspace[vspace_id].name, name ) == 0 )
     941_printf("\n[DEBUG EXEC] _sys_pthread_control() at cycle %d : "
     942        "enter for vspace %s / thread %s / command = %d\n",
     943        _get_proctime() , vspace_name, thread_name, command );
     944#endif
     945
     946    // get pointers in mapping
     947    mapping_header_t*    header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     948    mapping_thread_t*    thread   = _get_thread_base(header);
     949    mapping_vspace_t*    vspace   = _get_vspace_base(header);
     950    mapping_cluster_t*   cluster  = _get_cluster_base(header);
     951
     952    unsigned int found;
     953
     954    // search vspace name to get vspace index: vsid
     955    found = 0;
     956    unsigned int   vsid;
     957    for( vsid = 0 ; vsid < header->vspaces ; vsid++ )
     958    {
     959        if ( _strcmp( vspace[vsid].name, vspace_name ) == 0 )
     960        {
     961            found = 1;
    396962            break;
    397     }
    398 
    399     if ( vspace_id == header->vspaces )
    400     {
    401         _printf("\n[GIET ERROR] _sys_exec_application() : %s not found\n", name );
    402         return -1;
    403     }
    404 
    405     // scan tasks in vspace
    406     for (task_id = vspace[vspace_id].task_offset;
    407          task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
    408          task_id++)
    409     {
    410         unsigned int cid   = task[task_id].clusterid;
    411         unsigned int x     = cid / y_size;
    412         unsigned int y     = cid % y_size;
    413         unsigned int p     = task[task_id].proclocid;
    414         unsigned int ltid  = task[task_id].ltid;
    415 
    416         // get scheduler pointer for processor running the task
    417         static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
    418 
    419         // check if an application task is runnable
    420         if ( psched->context[ltid][CTX_NORUN_ID] == 0 )
     963        }
     964    }
     965
     966    if ( found == 0 ) return GIET_SYSCALL_VSPACE_NOT_FOUND;
     967
     968    // search thread name in vspace to get thread index: tid
     969    found = 0;
     970    unsigned int   tid;
     971    unsigned int   min = vspace[vsid].thread_offset;
     972    unsigned int   max = min + vspace[vsid].threads;
     973    for( tid = min ; tid < max ; tid++ )
     974    {
     975        if ( _strcmp( thread[tid].name, thread_name ) == 0 )
    421976        {
    422             _printf( "\n[GIET ERROR] _sys_exec_application() : %s already executed\n", name );
    423             return -2;
     977            found = 1;
     978            break;
    424979        }
    425980    }
    426981
    427     // reload writable segments
    428     if ( _load_writable_segments( &vspace[vspace_id] ) )
    429     {
    430          _printf("[GIET ERROR] _sys_exec_application() : can't load segments for %s\n", name );
    431          return -3;
    432     }
    433 
    434     // scan tasks in vspace
    435     for (task_id = vspace[vspace_id].task_offset;
    436          task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
    437          task_id++)
    438     {
    439         unsigned int cid   = task[task_id].clusterid;
    440         unsigned int x     = cid / y_size;
    441         unsigned int y     = cid % y_size;
    442         unsigned int p     = task[task_id].proclocid;
    443         unsigned int ltid  = task[task_id].ltid;
    444 
    445         // get scheduler pointer for processor running the task
    446         static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
    447 
    448         // reset task context: RA / SR / SP / EPC / NORUN
    449         unsigned int vseg_id       = task[task_id].stack_vseg_id;
    450         unsigned int sp_value      = vseg[vseg_id].vbase + vseg[vseg_id].length;
    451 
    452         psched->context[ltid][CTX_RA_ID]     = (unsigned int)&_ctx_eret;
    453         psched->context[ltid][CTX_SR_ID]     = GIET_SR_INIT_VALUE;
    454         psched->context[ltid][CTX_SP_ID]     = sp_value;
    455         psched->context[ltid][CTX_EPC_ID]    = psched->context[ltid][CTX_ENTRY_ID];
    456         psched->context[ltid][CTX_NORUN_ID]  = 0;
    457     }
    458 
    459 #if GIET_DEBUG_EXEC
    460 if ( _get_proctime() > GIET_DEBUG_EXEC )
    461 _printf("\n[DEBUG EXEC] exit _sys_exec_application() at cycle %d : %s will be executed\n",
    462         _get_proctime() , name );
    463 #endif
    464 
    465     return 0;
    466 }  // end _sys_exec_application()
    467    
     982    if ( found == 0 ) return GIET_SYSCALL_THREAD_NOT_FOUND;
     983
     984    // get thread coordinates
     985    unsigned int cid  = thread[tid].clusterid;
     986    unsigned int x    = cluster[cid].x;
     987    unsigned int y    = cluster[cid].y;
     988    unsigned int p    = thread[tid].proclocid;
     989    unsigned int ltid = thread[tid].ltid;
     990
     991    static_scheduler_t* psched = _schedulers[x][y][p];
     992
     993    // check trdid and vsid
     994    unsigned int trdid = x<<24 | y<<16 | p<<8 | ltid;
     995    if ( (psched->context[ltid].slot[CTX_TRDID_ID] != trdid) ||
     996         (psched->context[ltid].slot[CTX_VSID_ID]  != vsid) )
     997        return GIET_SYSCALL_UNCOHERENT_THREAD_CONTEXT;
     998
     999    // execute command
     1000    if ( command == THREAD_CMD_PAUSE )
     1001    {
     1002        _atomic_or ( &psched->context[ltid].slot[CTX_NORUN_ID],  NORUN_MASK_THREAD );
     1003        return GIET_SYSCALL_OK;
     1004    }
     1005    else if ( command == THREAD_CMD_RESUME )
     1006    {
     1007        _atomic_and( &psched->context[ltid].slot[CTX_NORUN_ID], ~NORUN_MASK_THREAD );
     1008        return GIET_SYSCALL_OK;
     1009    }
     1010    else if ( command == THREAD_CMD_CONTEXT )
     1011    {
     1012        _user_printf( " - CTX_TRDID  = %x\n"
     1013                      " - CTX_VSID   = %x\n"
     1014                      " - CTX_EPC    = %x\n"
     1015                      " - CTX_PTAB   = %x\n"
     1016                      " - CTX_PTPR   = %x\n"
     1017                      " - CTX_SR     = %x\n"
     1018                      " - CTX_RA     = %x\n"
     1019                      " - CTX_SP     = %x\n"
     1020                      " - CTX_ENTRY  = %x\n"
     1021                      " - CTX_NORUN  = %x\n"
     1022                      " - CTX_SIGS   = %x\n"
     1023                      " - CTX_LOCKS  = %x\n"
     1024                      " - CTX_TTY    = %x\n"
     1025                      " - CTX_NIC_RX = %x\n"
     1026                      " - CTX_NIC_TX = %x\n"
     1027                      " - CTX_CMA_RX = %x\n"
     1028                      " - CTX_CMA_TX = %x\n"
     1029                      " - CTX_CMA_FB = %x\n",
     1030                      psched->context[ltid].slot[CTX_TRDID_ID],
     1031                      psched->context[ltid].slot[CTX_VSID_ID],
     1032                      psched->context[ltid].slot[CTX_EPC_ID],
     1033                      psched->context[ltid].slot[CTX_PTAB_ID],
     1034                      psched->context[ltid].slot[CTX_PTPR_ID],
     1035                      psched->context[ltid].slot[CTX_SR_ID],
     1036                      psched->context[ltid].slot[CTX_RA_ID],
     1037                      psched->context[ltid].slot[CTX_SP_ID],
     1038                      psched->context[ltid].slot[CTX_ENTRY_ID],
     1039                      psched->context[ltid].slot[CTX_NORUN_ID],
     1040                      psched->context[ltid].slot[CTX_SIGS_ID],
     1041                      psched->context[ltid].slot[CTX_LOCKS_ID],
     1042                      psched->context[ltid].slot[CTX_TTY_ID],
     1043                      psched->context[ltid].slot[CTX_NIC_RX_ID],
     1044                      psched->context[ltid].slot[CTX_NIC_TX_ID],
     1045                      psched->context[ltid].slot[CTX_CMA_RX_ID],
     1046                      psched->context[ltid].slot[CTX_CMA_TX_ID],
     1047                      psched->context[ltid].slot[CTX_CMA_FB_ID] );
     1048        return GIET_SYSCALL_OK;
     1049    }
     1050    else
     1051    {
     1052        return GIET_SYSCALL_ILLEGAL_THREAD_COMMAND_TYPE;
     1053    }
     1054
     1055} // end _sys_pthread_control()
     1056
     1057
     1058
    4681059
    4691060//////////////////////////////////////////////////////////////////////////////
     
    4761067{
    4771068    // In this implementation, the allocation policy is constrained:
    478     // the coprocessor must be in the same cluster as the calling task,
     1069    // the coprocessor must be in the same cluster as the calling thread,
    4791070    // and there is at most one coprocessor per cluster
    4801071
     
    5191110        *coproc_info = _coproc_info[cluster_id];
    5201111
    521         // register coprocessor coordinates in task context
     1112        // register coprocessor coordinates in thread context
    5221113        unsigned int cluster_xy = (x<<Y_WIDTH) + y;
    5231114        _set_context_slot( CTX_COPROC_ID , cluster_xy );
     
    5281119        x , y , *coproc_info , cluster_xy );
    5291120#endif
    530         return 0;
     1121        return GIET_SYSCALL_OK;
    5311122    }
    5321123    else
     
    5351126                 " with type %d available in cluster[%d,%d]\n",
    5361127                 coproc_type , x , y );
    537         return -1;
     1128        return GIET_SYSCALL_COPROCESSOR_NOT_FOUND;
    5381129    }
    5391130}  // end _sys_coproc_alloc()
     
    5531144    {
    5541145         _printf("\n[GIET_ERROR] in _sys_coproc_release(): "
    555                  "no coprocessor allocated to task running on P[%d,%d,%d]\n",
     1146                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
    5561147                 x , y , p );
    557          return -1;
     1148         return GIET_SYSCALL_COPROCESSOR_NOT_FOUND;
    5581149    }
    5591150
     
    5731164    }
    5741165
    575     // deallocates coprocessor coordinates in task context
     1166    // deallocates coprocessor coordinates in thread context
    5761167    _set_context_slot( CTX_COPROC_ID , 0xFFFFFFFF );
    5771168
     
    5841175#endif
    5851176
    586     return 0;
     1177    return GIET_SYSCALL_OK;
    5871178}  // end _sys_coproc_release()
    5881179
     
    6021193    {
    6031194         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
    604                  "no coprocessor allocated to task running on P[%d,%d,%d]\n",
     1195                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
    6051196                 x , y , p );
    606          return -1;
     1197         return GIET_SYSCALL_COPROCESSOR_NOT_FOUND;
    6071198    }
    6081199
     
    6151206         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
    6161207                 " illegal mode\n");
    617          return -1;
     1208         return GIET_SYSCALL_COPROCESSOR_ILLEGAL_MODE;
    6181209    }
    6191210
     
    6221213 
    6231214    // physical addresses
    624     paddr_t            buffer_paddr;
     1215    unsigned long long buffer_paddr;
    6251216    unsigned int       buffer_lsb;
    6261217    unsigned int       buffer_msb;
    627     paddr_t            mwmr_paddr = 0;
     1218    unsigned long long mwmr_paddr = 0;
    6281219    unsigned int       mwmr_lsb;
    6291220    unsigned int       mwmr_msb;
    630     paddr_t            lock_paddr = 0;
     1221    unsigned long long lock_paddr = 0;
    6311222    unsigned int       lock_lsb;
    6321223    unsigned int       lock_msb;
     
    6741265#endif
    6751266       
    676     return 0;
     1267    return GIET_SYSCALL_OK;
    6771268} // end _sys_coproc_channel_init()
    6781269
     
    6911282    {
    6921283         _printf("\n[GIET_ERROR] in _sys_coproc_run(): "
    693                  "no coprocessor allocated to task running on P[%d,%d,%d]\n",
     1284                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
    6941285                 x , y , p );
    695          return -1;
     1286         return -1111;
    6961287    }
    6971288
     
    7191310            _printf("\n[GIET_ERROR] P[%d,%d,%d] in _sys_coproc_run() for coprocessor[%d,%d]\n"
    7201311                    "  all channels don't have the same mode\n", x , y , p , cx , cy );
    721             return -1;
     1312            return -1111;
    7221313        }
    7231314    }
     
    7451336#endif
    7461337
    747         return 0;
     1338        return GIET_SYSCALL_OK;
    7481339    }
    7491340    ///////////////////////////////////////////////////////////////////////////
    7501341    else                                // mode == MODE_DMA_IRQ => descheduling
    7511342    {
    752         // set _coproc_gtid
    753         unsigned int ltid = _get_current_task_id();
    754         _coproc_gtid[cluster_id] = (procid<<16) + ltid;
     1343        // set _coproc_trdid
     1344        unsigned int ltid = _get_thread_ltid();
     1345        _coproc_trdid[cluster_id] = (x<<24) + (y<<16) + (p<<8) + ltid;
    7551346
    7561347        // enters critical section
     
    7601351        // set NORUN_MASK_COPROC bit
    7611352        static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
    762         unsigned int*       ptr     = &psched->context[ltid][CTX_NORUN_ID];
     1353        unsigned int*       ptr     = &psched->context[ltid].slot[CTX_NORUN_ID];
    7631354        _atomic_or( ptr , NORUN_MASK_COPROC );
    7641355
     
    7711362#endif
    7721363
    773         // deschedule task
     1364        // deschedule thread
    7741365        _ctx_switch();
    7751366
     
    8021393    {
    8031394         _printf("\n[GIET_ERROR] in _sys_coproc_completed(): "
    804                  "no coprocessor allocated to task running on P[%d,%d,%d]\n",
     1395                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
    8051396                 x , y , p );
    806          return -1;
     1397         return -1111;
    8071398    }
    8081399
     
    8791470int _sys_tty_alloc( unsigned int shared )
    8801471{
    881     unsigned int channel;
    882 
     1472    unsigned int channel;    // allocated TTY channel
     1473
     1474    // get trdid and vsid for the calling thread
     1475    unsigned int vsid  = _get_context_slot( CTX_VSID_ID );
     1476    unsigned int trdid = _get_thread_trdid();
     1477
     1478    // check no TTY already allocated to calling thread
    8831479    if ( _get_context_slot( CTX_TTY_ID ) < NB_TTY_CHANNELS )
    8841480    {
    885         _printf("\n[GIET_ERROR] in _sys_tty_alloc() : TTY channel already allocated\n");
    886         return 0;
    887     }
    888 
    889     // get a new TTY channel
     1481        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : "
     1482                "TTY channel already allocated to thread %x\n", trdid );
     1483        return -1111;
     1484    }
     1485
     1486    mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     1487    mapping_vspace_t  *vspace   = _get_vspace_base(header);
     1488    mapping_thread_t  *thread   = _get_thread_base(header);
     1489   
     1490    // compute number of users
     1491    unsigned int users;
     1492    if ( shared )  users = vspace[vsid].threads;
     1493    else           users = 1;
     1494
     1495    // get a TTY channel
    8901496    for ( channel = 0 ; channel < NB_TTY_CHANNELS ; channel++ )
    8911497    {
    892         if ( !_tty_channel[channel] )
    893         {
    894             _tty_channel[channel] = 1;
    895             break;
    896         }
     1498        unsigned int* palloc  = &_tty_channel_alloc[channel];
     1499
     1500        if ( _atomic_test_and_set( palloc , users ) == 0 ) break;
    8971501    }
    8981502    if ( channel >= NB_TTY_CHANNELS )
    8991503    {
    900         _printf("\n[GIET_ERROR] in _sys_tty_alloc() : no TTY channel available\n");
    901         return -1;
    902     }
    903 
    904     // reset kernel buffer for allocated TTY channel
    905     _tty_rx_full[channel] = 0;
     1504        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : "
     1505                "no TTY channel available for thread %x\n", trdid );
     1506        return -1111;
     1507    }
     1508
     1509    // initialise allocated TTY channel
     1510    _tty_init( channel );
    9061511
    9071512    // allocate a WTI mailbox to the calling proc if external IRQ
    908     unsigned int unused;
    909     if ( USE_PIC ) _ext_irq_alloc( ISR_TTY_RX , channel , &unused );
     1513    unsigned int wti_id;
     1514    if ( USE_PIC ) _ext_irq_alloc( ISR_TTY_RX , channel , &wti_id );
     1515
     1516    // register wti_id and coordinates for processor receiving WTI
     1517    unsigned int procid = _get_procid();
     1518    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
     1519    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
     1520    unsigned int p      = procid & ((1<<P_WIDTH)-1);
     1521    _tty_channel_wti[channel] = x<<24 | y<<16 | p<<8 | wti_id;
    9101522   
    9111523    // update CTX_TTY_ID
    912     if ( shared )         // for all tasks in the same vspace
    913     {
    914         unsigned int      vspace_id = _get_context_slot( CTX_VSID_ID );
    915         mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
    916         mapping_vspace_t  *vspace   = _get_vspace_base(header);
    917         mapping_task_t    *task     = _get_task_base(header);
    918 
    919         // scan tasks in vspace
    920         unsigned int task_id;
    921         for (task_id = vspace[vspace_id].task_offset;
    922              task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
    923              task_id++)
     1524    if ( shared )         // for all threads in vspace
     1525    {
     1526        // scan threads in vspace
     1527        unsigned int tid;
     1528        for (tid = vspace[vsid].thread_offset;
     1529             tid < (vspace[vsid].thread_offset + vspace[vsid].threads);
     1530             tid++)
    9241531        {
    9251532            unsigned int y_size        = header->y_size;
    926             unsigned int cid           = task[task_id].clusterid;
     1533            unsigned int cid           = thread[tid].clusterid;
    9271534            unsigned int x             = cid / y_size;
    9281535            unsigned int y             = cid % y_size;
    929             unsigned int p             = task[task_id].proclocid;
    930             unsigned int ltid          = task[task_id].ltid;
     1536            unsigned int p             = thread[tid].proclocid;
     1537            unsigned int ltid          = thread[tid].ltid;
    9311538            static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];
    9321539
    933             // don't overwrite TTY_ID
    934             if ( psched->context[ltid][CTX_TTY_ID] >= NB_TTY_CHANNELS )
    935             {
    936                 psched->context[ltid][CTX_TTY_ID] = channel;
    937             }
     1540            psched->context[ltid].slot[CTX_TTY_ID] = channel;
    9381541        }
    9391542    }
    940     else                  // for calling task only
     1543    else                  // for calling thread only
    9411544    {
    9421545        _set_context_slot( CTX_TTY_ID, channel );
    9431546    }
    9441547
    945     return 0;
    946 }
    947 
    948 /////////////////////////////////////////
    949 // NOTE: not a syscall
    950 int _sys_tty_release()
     1548    return GIET_SYSCALL_OK;
     1549}  // end _sys_tty_alloc()
     1550
     1551//////////////////////
     1552int _sys_tty_release()     // NOTE: not a syscall
    9511553{
    9521554    unsigned int channel = _get_context_slot( CTX_TTY_ID );
     
    9541556    if ( channel == -1 )
    9551557    {
    956         _printf("\n[GIET_ERROR] in _sys_tty_release() : TTY channel already released\n");
    957         return -1;
    958     }
    959 
    960     // release WTI mailbox
    961     if ( USE_PIC ) _ext_irq_release( ISR_TTY_RX , channel );
    962 
    963     // reset CTX_TTY_ID for all tasks in vspace
    964     unsigned int      vspace_id = _get_context_slot( CTX_VSID_ID );
    965     mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
    966     mapping_vspace_t  *vspace   = _get_vspace_base(header);
    967     mapping_task_t    *task     = _get_task_base(header);
    968 
    969     unsigned int task_id;
    970     for (task_id = vspace[vspace_id].task_offset;
    971          task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
    972          task_id++)
    973     {
    974         unsigned int y_size        = header->y_size;
    975         unsigned int cid           = task[task_id].clusterid;
    976         unsigned int x             = cid / y_size;
    977         unsigned int y             = cid % y_size;
    978         unsigned int p             = task[task_id].proclocid;
    979         unsigned int ltid          = task[task_id].ltid;
    980         static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];
    981 
    982         // only clear matching TTY_ID
    983         if ( psched->context[ltid][CTX_TTY_ID] == channel )
    984         {
    985             psched->context[ltid][CTX_TTY_ID] = -1;
    986         }
    987     }
    988 
    989     // release TTY channel
    990     _tty_channel[channel] = 0;
    991 
    992     return 0;
    993 }
    994 
    995 /////////////////////////////////////////////////
     1558        unsigned int trdid = _get_thread_trdid();
     1559        _printf("\n[GIET_ERROR] in _sys_tty_release() : "
     1560                "TTY channel already released for thread %x\n", trdid );
     1561        return -1111;
     1562    }
     1563
     1564    // reset CTX_TTY_ID for the calling thread
     1565    _set_context_slot( CTX_TTY_ID , 0xFFFFFFFF );
     1566
     1567    // atomically decrement the _tty_channel_allocator[] array
     1568    _atomic_increment( &_tty_channel_alloc[channel] , -1 );
     1569
     1570    // release WTI mailbox if TTY channel no more used
     1571    if ( USE_PIC  && (_tty_channel_alloc[channel] == 0) )
     1572    {
     1573        _ext_irq_release( ISR_TTY_RX , channel );
     1574    }
     1575
     1576    return GIET_SYSCALL_OK;
     1577}  // end sys_tty_release()
     1578
     1579////////////////////////////////////////
    9961580int _sys_tty_write( const char*  buffer,   
    9971581                    unsigned int length,    // number of characters
     
    10021586    // compute and check tty channel
    10031587    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
    1004     if( channel >= NB_TTY_CHANNELS ) return -1;
     1588    if( channel >= NB_TTY_CHANNELS ) return -1111;
    10051589
    10061590    // write string to TTY channel
     
    10211605}
    10221606
    1023 ////////////////////////////////////////////////
     1607///////////////////////////////////////
    10241608int _sys_tty_read( char*        buffer,
    10251609                   unsigned int length,    // unused
     
    10281612    // compute and check tty channel
    10291613    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
    1030     if( channel >= NB_TTY_CHANNELS ) return -1;
    1031 
    1032     // read one character from TTY channel
    1033     if (_tty_rx_full[channel] == 0)
    1034     {
    1035         return 0;
    1036     }
    1037     else
    1038     {
    1039         *buffer = _tty_rx_buf[channel];
    1040         _tty_rx_full[channel] = 0;
    1041         return 1;
    1042     }
     1614    if( channel >= NB_TTY_CHANNELS ) return -1111;
     1615
     1616    unsigned int save_sr;
     1617    unsigned int found = 0;
     1618
     1619    // get pointer on TTY_RX FIFO
     1620    tty_fifo_t*  fifo = &_tty_rx_fifo[channel];
     1621
     1622    // try to read one character from FIFO
     1623    // blocked in while loop until success
     1624    while ( found == 0 )
     1625    {
     1626        if ( fifo->sts == 0)   // FIFO empty => deschedule
     1627        {
     1628            // enters critical section
     1629             _it_disable( &save_sr );
     1630
     1631            // set NORUN_MASK_TTY bit for calling thread
     1632            static_scheduler_t* psched  = (static_scheduler_t*)_get_sched();
     1633            unsigned int ltid = psched->current;
     1634            _atomic_or( &psched->context[ltid].slot[CTX_NORUN_ID] , NORUN_MASK_TTY );
     1635
     1636            // register descheduling thread trdid
     1637            fifo->trdid = _get_thread_trdid();
     1638
     1639             // deschedule calling thread
     1640            _ctx_switch();
     1641
     1642            // exit critical section
     1643            _it_restore( &save_sr );
     1644        }
     1645        else                             // FIFO not empty => get one character
     1646        {
     1647            *buffer   = fifo->data[fifo->ptr];
     1648            fifo->sts = fifo->sts - 1;
     1649            fifo->ptr = (fifo->ptr + 1) % TTY_FIFO_DEPTH;
     1650            found     = 1;
     1651        }
     1652    }
     1653
     1654    return 1;
    10431655}
    10441656
    1045 ///////////////////////////////////////////
    1046 int _sys_tty_get_lock( unsigned int   channel,       // unused
    1047                        unsigned int * save_sr_ptr )
    1048 {
    1049     // check tty channel
    1050     if( channel != 0 )  return 1;
    1051 
    1052     _it_disable( save_sr_ptr );
    1053     _sqt_lock_acquire( &_tty0_sqt_lock );
    1054     return 0;
    1055 }
    1056 
    1057 ///////////////////////////////////////////////
    1058 int _sys_tty_release_lock( unsigned int   channel,
    1059                            unsigned int * save_sr_ptr )
    1060 {
    1061     // check tty channel
    1062     if( channel != 0 )  return 1;
    1063 
    1064     _sqt_lock_release( &_tty0_sqt_lock );
    1065     _it_restore( save_sr_ptr );
    1066     return 0;
    1067 }
     1657
    10681658
    10691659//////////////////////////////////////////////////////////////////////////////
    1070 //             TIM related syscall handlers
     1660//             TIMER related syscall handlers
    10711661//////////////////////////////////////////////////////////////////////////////
    10721662
     
    10741664int _sys_tim_alloc()
    10751665{
    1076     // get a new timer index
    1077     unsigned int channel = _atomic_increment( &_tim_channel_allocator, 1 );
    1078 
     1666
     1667#if NB_TIM_CHANNELS
     1668
     1669    unsigned int channel;    // allocated TIMER channel
     1670
     1671    unsigned int trdid = _get_thread_trdid();
     1672
     1673    // check no TIMER already allocated to calling thread
     1674    if ( _get_context_slot( CTX_TIM_ID ) < NB_TIM_CHANNELS )
     1675    {
     1676        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : "
     1677                "TIMER channel already allocated to thread %x\n", trdid );
     1678        return -1111;
     1679    }
     1680
     1681    // get a TIMER channel
     1682    for ( channel = 0 ; channel < NB_TIM_CHANNELS ; channel++ )
     1683    {
     1684        unsigned int* palloc  = &_tim_channel_alloc[channel];
     1685
     1686        if ( _atomic_test_and_set( palloc , 1 ) == 0 ) break;
     1687    }
    10791688    if ( channel >= NB_TIM_CHANNELS )
    10801689    {
    1081         _printf("\n[GIET_ERROR] in _sys_tim_alloc() : not enough TIM channels\n");
    1082         return -1;
    1083     }
    1084     else
    1085     {
    1086         _set_context_slot( CTX_TIM_ID, channel );
    1087         return 0;
    1088     }
    1089 }
    1090 
    1091 ////////////////////
    1092 // NOTE: not a syscall
    1093 int _sys_tim_release()
    1094 {
    1095     // release one timer
    1096     _atomic_increment( &_tim_channel_allocator, 0xFFFFFFFF );
    1097 
    1098     return 0;
    1099 }
     1690        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : "
     1691                "no TIMER channel available for thread %x\n", trdid );
     1692        return -1111;
     1693    }
     1694
     1695    // allocate a WTI mailbox to the calling proc if external IRQ
     1696    unsigned int wti_id;
     1697    if ( USE_PIC ) _ext_irq_alloc( ISR_TIMER , channel , &wti_id );
     1698
     1699    // register wti_id and coordinates for processor receiving WTI
     1700    unsigned int procid = _get_procid();
     1701    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
     1702    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
     1703    unsigned int p      = procid & ((1<<P_WIDTH)-1);
     1704    _tim_channel_wti[channel] = x<<24 | y<<16 | p<<8 | wti_id;
     1705   
     1706    // update CTX_TIM_ID in thread context
     1707    _set_context_slot( CTX_TIM_ID, channel );
     1708
     1709    return GIET_SYSCALL_OK;
     1710
     1711#else
     1712
     1713    _printf("\n[GIET ERROR] in _sys_tim_alloc() : NB_TIM_CHANNELS = 0\n");
     1714    return -1111;
     1715
     1716#endif
     1717}  // end _sys_tim_alloc()
     1718
     1719
     1720//////////////////////
     1721int _sys_tim_release()     // NOTE: not a syscall
     1722{
     1723
     1724#if NB_TIM_CHANNELS
     1725
     1726    unsigned int channel = _get_context_slot( CTX_TIM_ID );
     1727
     1728    if ( channel == -1 )
     1729    {
     1730        unsigned int trdid = _get_thread_trdid();
     1731        _printf("\n[GIET_ERROR] in _sys_tim_release() : "
     1732                "TIMER channel already released for thread %x\n", trdid );
     1733        return -1111;
     1734    }
     1735
     1736    // reset CTX_TIM_ID for the calling thread
     1737    _set_context_slot( CTX_TIM_ID , 0xFFFFFFFF );
     1738
     1739    // reset the _tim_channel_alloc[] array
     1740    _tim_channel_alloc[channel] = 0;
     1741
     1742    // release WTI mailbox if TTY channel no more used
     1743    if ( USE_PIC )
     1744    {
     1745        _ext_irq_release( PERIPH_TYPE_TIM , channel );
     1746    }
     1747
     1748    return GIET_SYSCALL_OK;
     1749
     1750#else
     1751
     1752    _printf("\n[GIET ERROR] in _sys_tim_release() : NB_TIM_CHANNELS = 0\n");
     1753    return -1111;
     1754
     1755#endif
     1756}  // end _sys_tim_release()
    11001757
    11011758/////////////////////////////////////////
    11021759int _sys_tim_start( unsigned int period )
    11031760{
     1761
     1762#if NB_TIM_CHANNELS
     1763
    11041764    // get timer index
    11051765    unsigned int channel = _get_context_slot( CTX_TIM_ID );
     
    11071767    {
    11081768        _printf("\n[GIET_ERROR] in _sys_tim_start() : not enough TIM channels\n");
    1109         return -1;
     1769        return -1111;
    11101770    }
    11111771
     
    11131773    _timer_start( channel, period );
    11141774
    1115     return 0;
     1775    return GIET_SYSCALL_OK;
     1776
     1777#else
     1778
     1779    _printf("\n[GIET ERROR] in _sys_tim_start() : NB_TIM_CHANNELS = 0\n");
     1780    return -1111;
     1781
     1782#endif
    11161783}
    11171784
     
    11191786int _sys_tim_stop()
    11201787{
     1788
     1789#if NB_TIM_CHANNELS
     1790
    11211791    // get timer index
    11221792    unsigned int channel = _get_context_slot( CTX_TIM_ID );
     
    11241794    {
    11251795        _printf("\n[GIET_ERROR] in _sys_tim_stop() : illegal timer index\n");
    1126         return -1;
     1796        return -1111;
    11271797    }
    11281798
     
    11301800    _timer_stop( channel );
    11311801
    1132     return 0;
     1802    return GIET_SYSCALL_OK;
     1803
     1804#else
     1805
     1806    _printf("\n[GIET ERROR] in _sys_tim_stop() : NB_TIM_CHANNELS = 0\n");
     1807    return -1111;
     1808
     1809#endif
    11331810}
     1811
    11341812
    11351813//////////////////////////////////////////////////////////////////////////////
     
    11381816
    11391817#define NIC_CONTAINER_SIZE 4096
     1818
     1819#if NB_NIC_CHANNELS
    11401820
    11411821////////////////////////////////////////
     
    11441824                    unsigned int ymax )
    11451825{
     1826    mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     1827    mapping_vspace_t  *vspace   = _get_vspace_base(header);
     1828    mapping_thread_t  *thread   = _get_thread_base(header);
     1829
     1830    // get calling thread trdid, vspace index, and number of threads
     1831    unsigned int trdid = _get_thread_trdid();
     1832    unsigned int vsid  = _get_context_slot( CTX_VSID_ID );
     1833    unsigned int users = vspace[vsid].threads;
     1834
    11461835    // check xmax / ymax parameters
    1147     if ( xmax > X_SIZE )
    1148     {
    1149         _printf("\n[GIET_ERROR] in _sys_nic_alloc() xmax argument too large\n");
    1150         return -1;
    1151     }
    1152     if ( ymax > Y_SIZE )
    1153     {
    1154         _printf("\n[GIET_ERROR] in _sys_nic_alloc() ymax argument too large\n");
    1155         return -1;
     1836    if ( (xmax > X_SIZE) || (ymax > Y_SIZE) )
     1837    {
     1838        _printf("\n[GIET_ERROR] in _sys_nic_alloc() "
     1839                "xmax or ymax argument too large for thread %x\n", trdid );
     1840        return -1111;
    11561841    }
    11571842
     
    11601845    ////////////////////////////////////////////////////////
    11611846
    1162     // get a NIC_RX or NIC_TX channel index
    1163     unsigned int nic_channel;
    1164     unsigned int cma_channel;
    1165 
    1166     if ( is_rx ) nic_channel = _atomic_increment( &_nic_rx_channel_allocator, 1 );
    1167     else         nic_channel = _atomic_increment( &_nic_tx_channel_allocator, 1 );
    1168 
     1847    unsigned int   nic_channel;
     1848    unsigned int   cma_channel;
     1849    unsigned int*  palloc;
     1850
     1851    // get a NIC_RX or NIC_TX channel
     1852    for ( nic_channel = 0 ; nic_channel < NB_NIC_CHANNELS ; nic_channel++ )
     1853    {
     1854        if ( is_rx ) palloc = &_nic_rx_channel_alloc[nic_channel];
     1855        else         palloc = &_nic_tx_channel_alloc[nic_channel];
     1856
     1857        if ( _atomic_test_and_set( palloc , users ) == 0 ) break;
     1858    }
    11691859    if ( (nic_channel >= NB_NIC_CHANNELS) )
    11701860    {
    1171         _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
    1172         return -1;
    1173     }
    1174 
    1175     // get a CMA channel index
     1861        _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
     1862                "no NIC channel available for thread %x\n", trdid );
     1863        return -1111;
     1864    }
     1865
     1866    // get a CMA channel
    11761867    for ( cma_channel = 0 ; cma_channel < NB_CMA_CHANNELS ; cma_channel++ )
    11771868    {
    1178         if ( !_cma_channel[cma_channel] )
     1869        palloc = &_cma_channel_alloc[cma_channel];
     1870
     1871        if ( _atomic_test_and_set( palloc , users ) == 0 ) break;
     1872    }
     1873    if ( cma_channel >= NB_CMA_CHANNELS )
     1874    {
     1875        _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
     1876                "no CMA channel available for thread %x\n", trdid );
     1877        if ( is_rx )  _nic_rx_channel_alloc[nic_channel] = 0;
     1878        else          _nic_tx_channel_alloc[nic_channel] = 0;
     1879        return -1111;
     1880    }
     1881
     1882#if GIET_DEBUG_NIC
     1883_printf("\n[GIET DEBUG NIC] Thread %d enters sys_nic_alloc() at cycle %d\n"
     1884        "  nic_channel = %d / cma_channel = %d\n",
     1885        trdid , _get_proctime() , nic_channel , cma_channel );
     1886#endif
     1887
     1888    // register nic_index and cma_index in all threads
     1889    // contexts that are in the same vspace
     1890    unsigned int tid;
     1891    for (tid = vspace[vsid].thread_offset;
     1892         tid < (vspace[vsid].thread_offset + vspace[vsid].threads);
     1893         tid++)
     1894    {
     1895        unsigned int y_size        = header->y_size;
     1896        unsigned int cid           = thread[tid].clusterid;
     1897        unsigned int x             = cid / y_size;
     1898        unsigned int y             = cid % y_size;
     1899        unsigned int p             = thread[tid].proclocid;
     1900        unsigned int ltid          = thread[tid].ltid;
     1901        static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];
     1902
     1903        if ( is_rx )
    11791904        {
    1180             _cma_channel[cma_channel] = 1;
    1181             break;
     1905            if ( (psched->context[ltid].slot[CTX_NIC_RX_ID] < NB_NIC_CHANNELS) ||
     1906                 (psched->context[ltid].slot[CTX_CMA_RX_ID] < NB_CMA_CHANNELS) )
     1907            {
     1908                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
     1909                        "NIC_RX or CMA_RX channel already allocated for thread %x\n", trdid );
     1910                _nic_rx_channel_alloc[nic_channel] = 0;
     1911                _cma_channel_alloc[cma_channel]    = 0;
     1912                return -1111;
     1913            }
     1914            else
     1915            {
     1916                psched->context[ltid].slot[CTX_NIC_RX_ID] = nic_channel;
     1917                psched->context[ltid].slot[CTX_CMA_RX_ID] = cma_channel;
     1918            }
    11821919        }
    1183     }
    1184 
    1185     if ( cma_channel >= NB_CMA_CHANNELS )
    1186     {
    1187         _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough CMA channels\n");
    1188         return -1;
    1189     }
    1190 
    1191 #if GIET_DEBUG_NIC
    1192 unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
    1193 _printf("\n[GIET DEBUG NIC] Task %d enters sys_nic_alloc() at cycle %d\n"
    1194         "  nic_channel = %d / cma_channel = %d\n",
    1195         thread , _get_proctime() , nic_channel , cma_channel );
    1196 #endif
    1197 
    1198     // register nic_index and cma_index in task context
    1199     if ( is_rx )
    1200     {
    1201         _set_context_slot( CTX_NIC_RX_ID, nic_channel );
    1202         _set_context_slot( CTX_CMA_RX_ID, cma_channel );
    1203     }
    1204     else
    1205     {
    1206         _set_context_slot( CTX_NIC_TX_ID, nic_channel );
    1207         _set_context_slot( CTX_CMA_TX_ID, cma_channel );
    1208     }
     1920        else // is_tx
     1921        {
     1922            if ( (psched->context[ltid].slot[CTX_NIC_TX_ID] < NB_NIC_CHANNELS) ||
     1923                 (psched->context[ltid].slot[CTX_CMA_TX_ID] < NB_CMA_CHANNELS) )
     1924            {
     1925                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
     1926                        "NIC_TX or CMA_TX channel already allocated for thread %x\n", trdid );
     1927                _nic_tx_channel_alloc[nic_channel] = 0;
     1928                _cma_channel_alloc[cma_channel]    = 0;
     1929                return -1111;
     1930            }
     1931            else
     1932            {
     1933                psched->context[ltid].slot[CTX_NIC_TX_ID] = nic_channel;
     1934                psched->context[ltid].slot[CTX_CMA_TX_ID] = cma_channel;
     1935            }
     1936        }
     1937    }  // end loop on threads
    12091938
    12101939    /////////////////////////////////////////////////////////////////////////////////
     
    12411970            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
    12421971            {
    1243                 _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
    1244                         " in cluster[%d,%d]\n", cx, cy );
    1245                 return -1;
     1972                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
     1973                        "not enough kenel heap in cluster[%d,%d]\n", cx, cy );
     1974                return -1111;
    12461975            }
    12471976
     
    12521981            if ( cont_paddr & 0x3F )
    12531982            {
    1254                 _printf("\n[GIET ERROR] in _sys_nic_alloc() : container address of cluster[%d,%d] not aligned\n",
    1255                         cx, cy);
    1256                 return -1;
     1983                _printf("\n[GIET ERROR] in _sys_nic_alloc() : "
     1984                        "container address of cluster[%d,%d] not aligned\n", cx, cy);
     1985                return -1111;
    12571986            }
    12581987
     
    12701999            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
    12712000            {
    1272                 _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
    1273                         " in cluster[%d,%d]\n", cx, cy );
    1274                 return -1;
     2001                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
     2002                        "not enough kernel heap in cluster[%d,%d]\n", cx, cy );
     2003                return -1111;
    12752004            }
    12762005
     
    12812010            if ( sts_paddr & 0x3F )
    12822011            {
    1283                 _printf("\n[GIET ERROR] in _sys_nic_alloc() : status address of cluster[%d,%d] not aligned\n",
    1284                         cx, cy);
    1285                 return -1;
     2012                _printf("\n[GIET ERROR] in _sys_nic_alloc() : "
     2013                        "status address of cluster[%d,%d] not aligned\n", cx, cy);
     2014                return -1111;
    12862015            }
    12872016
     
    13852114#endif
    13862115
    1387     return nic_channel;
     2116    return GIET_SYSCALL_OK;
    13882117} // end _sys_nic_alloc()
    13892118
    13902119
    1391 ////////////////////////////////////////
    1392 // NOTE: not a syscall
    1393 int _sys_nic_release( unsigned int is_rx )
    1394 {
    1395     if ( is_rx )
    1396         _atomic_increment( &_nic_rx_channel_allocator , 0xFFFFFFFF );
    1397     else
    1398         _atomic_increment( &_nic_tx_channel_allocator , 0xFFFFFFFF );
    1399 
    1400     return 0;
    1401 }
    1402 
    1403 
    1404 ////////////////////////////////////////
    1405 int _sys_nic_start( unsigned int is_rx,
    1406                     unsigned int channel )
    1407 {
     2120//////////////////////////////////////////
     2121int _sys_nic_release( unsigned int is_rx )     // NOTE: not a syscall
     2122{
     2123    unsigned int trdid = _get_thread_trdid();
     2124
    14082125    unsigned int nic_channel;
    14092126    unsigned int cma_channel;
    1410 
    1411     // get NIC channel index and CMA channel index from task context
     2127   
     2128    // update the kernel tables
    14122129    if ( is_rx )
    14132130    {
    14142131        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
    14152132        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
    1416     }
     2133
     2134        if ( (nic_channel >= NB_NIC_CHANNELS) )
     2135        {
     2136            _printf("\n[GIET ERROR] in _sys_nic_release() : "
     2137                    "NIC_RX channel already released for thread %x\n", trdid );
     2138            return -1111;
     2139        }
     2140        if ( (cma_channel >= NB_CMA_CHANNELS) )
     2141        {
     2142            _printf("\n[GIET ERROR] in _sys_nic_release() : "
     2143                    "CMA_RX channel already released for thread %x\n", trdid );
     2144            return -1111;
     2145        }
     2146
     2147        // atomically decrement the NIC and CMA channel allocators
     2148        _atomic_increment( &_nic_rx_channel_alloc[nic_channel] , -1 );
     2149        _atomic_increment( &_cma_channel_alloc[cma_channel] , -1 );
     2150   
     2151        // stop the NIC and CMA peripherals channels if no more users
     2152        if ( (_nic_rx_channel_alloc[nic_channel] == 0) &&
     2153             (_cma_channel_alloc[cma_channel] == 0) )  _sys_nic_stop( 1 );
     2154
     2155        // reset the calling thread context slots
     2156        _set_context_slot( CTX_NIC_RX_ID , 0xFFFFFFFF );
     2157        _set_context_slot( CTX_CMA_RX_ID , 0xFFFFFFFF );
     2158    }         
    14172159    else
    14182160    {
    14192161        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
    14202162        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
     2163
     2164        if ( (nic_channel >= NB_NIC_CHANNELS) )
     2165        {
     2166            _printf("\n[GIET ERROR] in _sys_nic_release() : "
     2167                    "NIC_TX channel already released for thread %x\n", trdid );
     2168            return -1111;
     2169        }
     2170        if ( (cma_channel >= NB_CMA_CHANNELS) )
     2171        {
     2172            _printf("\n[GIET ERROR] in _sys_nic_release() : "
     2173                    "CMA_TX channel already released for thread %x\n", trdid );
     2174            return -1111;
     2175        }
     2176
     2177        // atomically decrement the NIC and CMA channel allocators
     2178        _atomic_increment( &_nic_tx_channel_alloc[nic_channel] , -1 );
     2179        _atomic_increment( &_cma_channel_alloc[cma_channel] , -1 );
     2180   
     2181        // stop the NIC and CMA peripherals channels if no more users
     2182        if ( (_nic_tx_channel_alloc[nic_channel] == 0) &&
     2183             (_cma_channel_alloc[cma_channel] == 0) )  _sys_nic_stop( 0 );
     2184
     2185        // reset the calling thread context slots
     2186        _set_context_slot( CTX_NIC_TX_ID , 0xFFFFFFFF );
     2187        _set_context_slot( CTX_CMA_TX_ID , 0xFFFFFFFF );
     2188    }
     2189
     2190    return GIET_SYSCALL_OK;
     2191}  // end sys_nic_release()
     2192
     2193
     2194////////////////////////////////////////
     2195int _sys_nic_start( unsigned int is_rx )
     2196{
     2197    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
     2198
     2199    unsigned int nic_channel;
     2200    unsigned int cma_channel;
     2201
     2202    // get NIC channel index and CMA channel index from thread context
     2203    if ( is_rx )
     2204    {
     2205        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
     2206        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
     2207    }
     2208    else
     2209    {
     2210        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
     2211        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
    14212212    }
    14222213
    14232214#if GIET_DEBUG_NIC
    1424 unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
    1425 _printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start() at cycle %d\n"
     2215_printf("\n[GIET DEBUG NIC] Thread %x in _sys_nic_start() at cycle %d\n"
    14262216        "  get NIC channel = %d / CMA channel = %d\n",
    1427         thread, _get_proctime(), nic_channel, cma_channel );
     2217        trdid, _get_proctime(), nic_channel, cma_channel );
    14282218#endif
    14292219
    14302220    // check NIC and CMA channels index
    1431     if ( nic_channel != channel )
    1432     {
    1433         _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal NIC channel\n");
    1434         return -1;
     2221    if ( nic_channel >= NB_NIC_CHANNELS )
     2222    {
     2223        _printf("\n[GIET_ERROR] in _sys_nic_start() : "
     2224                "illegal NIC channel for thread %x\n", trdid );
     2225        return -1111;
    14352226    }
    14362227    if ( cma_channel >= NB_CMA_CHANNELS )
    14372228    {
    1438         _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal CMA channel\n");
    1439         return -1;
     2229        _printf("\n[GIET_ERROR] in _sys_nic_start() : "
     2230                "illegal CMA channel for thread %x\n", trdid );
     2231        return -1111;
    14402232    }
    14412233
     
    14502242#if GIET_DEBUG_NIC
    14512243    _printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
    1452             thread , _get_proctime() );
    1453 #endif
    1454 
    1455     return 0;
     2244            trdid , _get_proctime() );
     2245#endif
     2246
     2247    return GIET_SYSCALL_OK;
    14562248}  // end _sys_nic_start()
    14572249
     
    14592251//////////////////////////////////////
    14602252int _sys_nic_move( unsigned int is_rx,
    1461                    unsigned int channel,
    14622253                   void*        buffer )
    14632254{
     2255    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
     2256
     2257    unsigned int channel;
    14642258
    14652259#if GIET_DEBUG_NIC
    1466 unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
    14672260_printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_move() at cycle %d\n",
    1468         thread , _get_proctime() );
    1469 #endif
     2261        trdid , _get_proctime() );
     2262#endif
     2263
     2264    // get NIC channel index from thread context
     2265    if ( is_rx )  channel = _get_context_slot( CTX_NIC_RX_ID );
     2266    else          channel = _get_context_slot( CTX_NIC_TX_ID );
    14702267
    14712268    // check NIC channel index
    14722269    if ( channel >= NB_NIC_CHANNELS )
    14732270    {
    1474         _printf("\n[GIET_ERROR] in _sys_nic_move() : illegal NIC channel index\n");
    1475         return -1;
     2271        _printf("\n[GIET_ERROR] in _sys_nic_move() : "
     2272                "illegal NIC channel index for thread %x\n", trdid );
     2273        return -1111;
    14762274    }
    14772275
     
    14852283    unsigned int ymax = ker_chbuf->ymax;
    14862284
    1487     // get cluster coordinates for the processor running the calling task
     2285    // get cluster coordinates for the processor running the calling thread
    14882286    unsigned int  procid = _get_procid();
    14892287    unsigned int  cx     = procid >> (Y_WIDTH + P_WIDTH);
     
    14952293        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor X coordinate = %d"
    14962294                " / xmax = %d\n", cx , xmax );
    1497         return -1;
     2295        return -1111;
    14982296    }
    14992297    if ( cy >= ymax )
     
    15012299        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor Y coordinate = %d"
    15022300                " / ymax = %d\n", cy , ymax );
    1503         return -1;
     2301        return -1111;
    15042302    }
    15052303   
     
    15182316    {
    15192317        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal user buffer address\n");
    1520         return -1;
     2318        return -1111;
    15212319    }
    15222320
     
    16062404#endif
    16072405
    1608     return 0;
     2406    return GIET_SYSCALL_OK;
    16092407} // end _sys_nic_move()
    16102408
    16112409
    1612 ////////////////////////////////////////
    1613 int _sys_nic_stop( unsigned int is_rx,
    1614                    unsigned int channel )
    1615 {
     2410///////////////////////////////////////
     2411int _sys_nic_stop( unsigned int is_rx )
     2412{
     2413    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
     2414
    16162415    unsigned int nic_channel;
    16172416    unsigned int cma_channel;
     
    16302429
    16312430    // check NIC and CMA channels index
    1632     if ( nic_channel != channel )
    1633     {
    1634         _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal NIC channel\n");
    1635         return -1;
     2431    if ( nic_channel >= NB_NIC_CHANNELS )
     2432    {
     2433        _printf("\n[GIET_ERROR] in _sys_nic_stop() : "
     2434                "illegal NIC channel for thread %x\n", trdid );
     2435        return -1111;
    16362436    }
    16372437    if ( cma_channel >= NB_CMA_CHANNELS )
    16382438    {
    1639         _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal CMA channel\n");
    1640         return -1;
    1641     }
     2439        _printf("\n[GIET_ERROR] in _sys_nic_stop() : "
     2440                "illegal CMA channel for thread %x\n", trdid );
     2441        return -1111;
     2442    }
     2443
     2444    // desactivates the CMA channel
     2445    _cma_set_register( cma_channel, CHBUF_RUN , 0 );
     2446
     2447    // wait until CMA channel IDLE
     2448    unsigned int volatile status;
     2449    do
     2450    {
     2451         status = _cma_get_register( cma_channel, CHBUF_STATUS );
     2452    } while ( status );
    16422453
    16432454    // desactivates the NIC channel
    16442455    _nic_channel_stop( nic_channel, is_rx );
    16452456
    1646     // desactivates the CMA channel
    1647     _cma_set_register( cma_channel, CHBUF_RUN , 0 );
    1648 
    1649     return 0;
     2457    return GIET_SYSCALL_OK;
    16502458}  // end _sys_nic_stop()
    16512459
    16522460////////////////////////////////////////
    1653 int _sys_nic_clear( unsigned int is_rx,
    1654                     unsigned int channel )
    1655 {
    1656     unsigned int nic_channel;
     2461int _sys_nic_clear( unsigned int is_rx )
     2462{
     2463    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
     2464
     2465    unsigned int channel;
    16572466
    16582467    // get NIC channel
    1659     if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
    1660     else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
    1661 
    1662     if ( nic_channel != channel )
    1663     {
    1664         _printf("\n[GIET_ERROR] in _sys_nic_clear(): illegal NIC channel\n");
    1665         return -1;
     2468    if ( is_rx )  channel = _get_context_slot( CTX_NIC_RX_ID );
     2469    else          channel = _get_context_slot( CTX_NIC_TX_ID );
     2470
     2471    if ( channel >= NB_NIC_CHANNELS )
     2472    {
     2473        _printf("\n[GIET_ERROR] in _sys_nic_clear() : "
     2474                "illegal NIC channel for thread %x\n", trdid );
     2475        return -1111;
    16662476    }
    16672477
     
    16882498        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST , 0 );
    16892499    }
    1690     return 0;
     2500    return GIET_SYSCALL_OK;
    16912501}  // en _sys_nic_clear()
    16922502
    16932503////////////////////////////////////////
    1694 int _sys_nic_stats( unsigned int is_rx,
    1695                     unsigned int channel )
    1696 {
     2504int _sys_nic_stats( unsigned int is_rx )
     2505{
     2506    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
     2507
    16972508    unsigned int nic_channel;
    16982509
     
    17012512    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
    17022513
    1703     if ( nic_channel != channel )
    1704     {
    1705         _printf("\n[GIET_ERROR] in _sys_nic_stats(): illegal NIC channel\n");
    1706         return -1;
     2514    if ( nic_channel >= NB_NIC_CHANNELS )
     2515    {
     2516        _printf("\n[GIET_ERROR] in _sys_nic_stats() : "
     2517                "illegal NIC channel for thread %x\n", trdid );
     2518        return -1111;
    17072519    }
    17082520
     
    17592571                broadcast );
    17602572    }
    1761     return 0;
     2573    return GIET_SYSCALL_OK;
    17622574}  // end _sys_nic_stats()
     2575
     2576#endif
    17632577
    17642578/////////////////////////////////////////////////////////////////////////////////////////
     
    17742588    memcpy( fbf_address, buffer, length);
    17752589
    1776     return 0;
     2590    return GIET_SYSCALL_OK;
    17772591}
    17782592
     
    17852599    memcpy( buffer, fbf_address, length);
    17862600
    1787     return 0;
     2601    return GIET_SYSCALL_OK;
    17882602}
    17892603
     
    17912605int _sys_fbf_cma_alloc()
    17922606{
     2607    unsigned int trdid = _get_thread_trdid();
     2608
    17932609    if ( _get_context_slot( CTX_CMA_FB_ID ) < NB_CMA_CHANNELS )
    17942610    {
    1795         _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : CMA channel already allocated\n");
    1796         return 0;
    1797     }
    1798 
    1799     // get a new CMA channel index
     2611        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : "
     2612                "CMA channel already allocated for thread %x\n", trdid );
     2613        return GIET_SYSCALL_OK;
     2614    }
     2615
     2616    // get a CMA channel
    18002617    unsigned int channel;
    1801 
    18022618    for ( channel = 0 ; channel < NB_CMA_CHANNELS ; channel++ )
    18032619    {
    1804         if ( !_cma_channel[channel] )
    1805         {
    1806             _cma_channel[channel] = 1;
    1807             break;
    1808         }
    1809     }
    1810 
     2620        unsigned int*  palloc = &_cma_channel_alloc[channel];
     2621        if ( _atomic_test_and_set( palloc , 1 ) == 0 ) break;
     2622    }
    18112623    if ( channel >= NB_CMA_CHANNELS )
    18122624    {
    18132625        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : no CMA channel available\n");
    1814         return -1;
     2626        return -1111;
    18152627    }
    18162628    else
    18172629    {
    18182630        _set_context_slot( CTX_CMA_FB_ID, channel );
    1819         return 0;
     2631        return GIET_SYSCALL_OK;
    18202632    }
    18212633} // end sys_fbf_cma_alloc()
    18222634
    1823 ////////////////////////
    1824 // NOTE: not a syscall
    1825 int _sys_fbf_cma_release()
     2635//////////////////////////
     2636int _sys_fbf_cma_release()  // Not a syscall
    18262637{
    18272638    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
     2639    unsigned int trdid   = _get_thread_trdid();
    18282640
    18292641    if ( channel >= NB_CMA_CHANNELS )
    18302642    {
    1831         _printf("\n[GIET_ERROR] in _sys_fbf_cma_release() : CMA channel already released\n");
    1832         return -1;
    1833     }
    1834 
    1835     // stop fb
     2643        _printf("\n[GIET_ERROR] in _sys_fbf_cma_release() : "
     2644                "CMA_FB channel already releasedifor thread %x\n", trdid );
     2645        return -1111;
     2646    }
     2647
     2648    // stop CMA transfer
    18362649    _sys_fbf_cma_stop();
    18372650
    1838     // reset CTX_CMA_FB_ID for task
    1839     _set_context_slot( CTX_CMA_FB_ID, -1 );
     2651    // reset CTX_CMA_FB_ID for thread
     2652    _set_context_slot( CTX_CMA_FB_ID, 0xFFFFFFFF );
    18402653
    18412654    // release CMA channel
    1842     _cma_channel[channel] = 0;
    1843 
    1844     return 0;
     2655    _cma_channel_alloc[channel] = 0;
     2656
     2657    return GIET_SYSCALL_OK;
    18452658}
    18462659
     
    18682681    {
    18692682        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : CMA channel index too large\n");
    1870         return -1;
     2683        return -1111;
    18712684    }
    18722685
     
    18902703    {
    18912704        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user buffer not aligned\n");
    1892         return -1;
     2705        return -1111;
    18932706    }
    18942707
     
    18982711    {
    18992712        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user status not aligned\n");
    1900         return -1;
     2713        return -1111;
    19012714    }
    19022715
     
    19172730    {
    19182731        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf0 not in user space\n");
    1919         return -1;
     2732        return -1111;
    19202733    }
    19212734
     
    19252738    {
    19262739        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts0 not in user space\n");
    1927         return -1;
     2740        return -1111;
    19282741    }
    19292742
     
    19382751    {
    19392752        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf1 not in user space\n");
    1940         return -1;
     2753        return -1111;
    19412754    }
    19422755
     
    19462759    {
    19472760        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts1 not in user space\n");
    1948         return -1;
     2761        return -1111;
    19492762    }
    19502763
     
    19742787#endif
    19752788
    1976     return 0;
     2789    return GIET_SYSCALL_OK;
    19772790
    19782791#else
    19792792
    19802793    _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : NB_CMA_CHANNELS = 0\n");
    1981     return -1;
     2794    return -1111;
    19822795
    19832796#endif 
     
    19952808    {
    19962809        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
    1997         return -1;
     2810        return -1111;
    19982811    }
    19992812
     
    20052818        _printf("\n[GIET ERROR] in _sys_fbf_cma_start() :\n"
    20062819                "Buffer initialization has not been done\n");
    2007         return -1;
     2820        return -1111;
    20082821    }
    20092822
     
    20342847    _cma_set_register( channel, CHBUF_RUN      , 1 );
    20352848
    2036     return 0;
     2849    return GIET_SYSCALL_OK;
    20372850
    20382851#else
    20392852
    20402853    _printf("\n[GIET ERROR] in _sys_fbf_cma_start() : NB_CMA_CHANNELS = 0\n");
    2041     return -1;
     2854    return -1111;
    20422855
    20432856#endif
     
    20582871        _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : "
    20592872                "CMA channel index too large\n");
    2060         return -1;
     2873        return -1111;
    20612874    }
    20622875
     
    21382951    _mmc_sync( fbf_sts_paddr, 4 );
    21392952
    2140     return 0;
     2953    return GIET_SYSCALL_OK;
    21412954
    21422955#else
    21432956
    21442957    _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : no CMA channel allocated\n");
    2145     return -1;
     2958    return -1111;
    21462959
    21472960#endif
     
    21592972    {
    21602973        _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : CMA channel index too large\n");
    2161         return -1;
     2974        return -1111;
    21622975    }
    21632976
     
    21652978    _cma_set_register( channel, CHBUF_RUN, 0 );
    21662979
    2167     return 0;
     2980    return GIET_SYSCALL_OK;
    21682981
    21692982#else
    21702983
    21712984    _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : no CMA channel allocated\n");
    2172     return -1;
     2985    return -1111;
    21732986
    21742987#endif
     
    21842997{
    21852998    _printf("\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
    2186     return -1;
     2999    return GIET_SYSCALL_UNDEFINED_SYSTEM_CALL;
    21873000}
    21883001
     
    21983011    *p = gpid & ((1<<P_WIDTH)-1);
    21993012
    2200     return 0;
    2201 }
    2202 
    2203 //////////////////////////////////
    2204 int _sys_task_exit( char* string )
    2205 {
    2206     unsigned int date       = _get_proctime();
    2207 
    2208     unsigned int gpid       = _get_procid();
    2209     unsigned int cluster_xy = gpid >> P_WIDTH;
    2210     unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
    2211     unsigned int x          = cluster_xy >> Y_WIDTH;
    2212     unsigned int p          = gpid & ((1<<P_WIDTH)-1);
    2213 
    2214     unsigned int ltid       = _get_context_slot(CTX_LTID_ID);
    2215 
    2216     // print exit message
    2217     _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d"
    2218             "\n       Cause : %s\n\n",
    2219             ltid, x, y, p, date, string );
    2220 
    2221     // set NORUN_MASK_TASK bit (non runnable state)
    2222     static_scheduler_t*  psched  = (static_scheduler_t*)_schedulers[x][y][p];
    2223     unsigned int*        ptr     = &psched->context[ltid][CTX_NORUN_ID];
    2224     _atomic_or( ptr , NORUN_MASK_TASK );
    2225 
    2226     // deschedule
    2227     _sys_context_switch();
    2228 
    2229     return 0;
    2230 }
    2231 
    2232 /////////////////////////
    2233 int _sys_context_switch()
    2234 {
    2235     unsigned int save_sr;
    2236 
    2237     _it_disable( &save_sr );
    2238     _ctx_switch();
    2239     _it_restore( &save_sr );
    2240 
    2241     return 0;
    2242 }
    2243 
    2244 ////////////////////////
    2245 int _sys_local_task_id()
    2246 {
    2247     return _get_context_slot(CTX_LTID_ID);
    2248 }
    2249 
    2250 /////////////////////////
    2251 int _sys_global_task_id()
    2252 {
    2253     return _get_context_slot(CTX_GTID_ID);
    2254 }
    2255 
    2256 ////////////////////
    2257 int _sys_thread_id()
    2258 {
    2259     return _get_context_slot(CTX_TRDID_ID);
     3013    return GIET_SYSCALL_OK;
    22603014}
    22613015
     
    23123066        *nprocs = 0;
    23133067    }
    2314     return 0;
     3068    return GIET_SYSCALL_OK;
    23153069}
    23163070
     
    23403094                {
    23413095                    *vbase = vseg[vseg_id].vbase;
    2342                     return 0;
     3096                    return GIET_SYSCALL_OK;
    23433097                }
    23443098            }
    23453099        }
    23463100    }
    2347     return -1;    // not found
     3101    return GIET_SYSCALL_VSEG_NOT_FOUND;
    23483102}
    23493103
     
    23733127                {
    23743128                    *length = vseg[vseg_id].length;
    2375                     return 0;
     3129                    return GIET_SYSCALL_OK;
    23763130                }
    23773131            }
    23783132        }
    23793133    }
    2380     return -1;    // not found
     3134    return GIET_SYSCALL_VSEG_NOT_FOUND;
    23813135}
    23823136
     
    23923146    *y = (paddr>>32) & 0xF;
    23933147
    2394     return 0;
     3148    return GIET_SYSCALL_OK;
    23953149}
    23963150
     
    24013155                    unsigned int  y )
    24023156{
     3157    // checking parameters
     3158    if ( (x >= X_SIZE) || (y >= Y_SIZE) ) 
     3159    {
     3160        *vaddr  = 0;
     3161        *length = 0;
     3162        _printf("\n[GIET ERROR] in _sys_heap_info() : "
     3163                "illegal (%d,%d) coordinates\n", x , y );
     3164        return GIET_SYSCALL_ILLEGAL_CLUSTER_COORDINATES;
     3165    }
     3166
    24033167    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
    2404     mapping_task_t *   task    = _get_task_base(header);
     3168    mapping_thread_t * thread  = _get_thread_base(header);
    24053169    mapping_vseg_t *   vseg    = _get_vseg_base(header);
    24063170    mapping_vspace_t * vspace  = _get_vspace_base(header);
    24073171
    2408     unsigned int task_id;
     3172    unsigned int thread_id;
    24093173    unsigned int vspace_id;
    24103174    unsigned int vseg_id = 0xFFFFFFFF;
    24113175
    2412     // searching the heap vseg
    2413     if ( (x < X_SIZE) && (y < Y_SIZE) )  // searching a task in cluster(x,y)
    2414     {
    2415         // get vspace global index
    2416         vspace_id = _get_context_slot(CTX_VSID_ID);
    2417 
    2418         // scan all tasks in vspace
    2419         unsigned int min = vspace[vspace_id].task_offset ;
    2420         unsigned int max = min + vspace[vspace_id].tasks ;
    2421         for ( task_id = min ; task_id < max ; task_id++ )
     3176    // get calling thread vspace index
     3177    vspace_id = _get_context_slot(CTX_VSID_ID);
     3178
     3179    // scan all threads in vspace to find one in clyster[x,y]
     3180    unsigned int min = vspace[vspace_id].thread_offset ;
     3181    unsigned int max = min + vspace[vspace_id].threads ;
     3182    for ( thread_id = min ; thread_id < max ; thread_id++ )
     3183    {
     3184        if ( thread[thread_id].clusterid == (x * Y_SIZE + y) )
    24223185        {
    2423             if ( task[task_id].clusterid == (x * Y_SIZE + y) )
    2424             {
    2425                 vseg_id = task[task_id].heap_vseg_id;
    2426                 if ( vseg_id != 0xFFFFFFFF ) break;
    2427             }
     3186            vseg_id = thread[thread_id].heap_vseg_id;
     3187            break;
    24283188        }
    2429     }
    2430     else                                // searching in the calling task
    2431     {
    2432         task_id = _get_context_slot(CTX_GTID_ID);
    2433         vseg_id = task[task_id].heap_vseg_id;
    24343189    }
    24353190
     
    24393194        *vaddr  = vseg[vseg_id].vbase;
    24403195        *length = vseg[vseg_id].length;
    2441         return 0;
    24423196    }
    24433197    else
     
    24453199        *vaddr  = 0;
    24463200        *length = 0;
    2447         return -1;
    2448     }
     3201        _printf("error in _sys_heap_info() : no heap in cluster (%d,%d)\n", x , y );
     3202    }
     3203    return GIET_SYSCALL_OK;
    24493204}  // end _sys_heap_info()
    2450 
    2451 
    2452 ///////////////////////
    2453 int _sys_tasks_status()
    2454 {
    2455     mapping_header_t *  header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
    2456     mapping_task_t *    task    = _get_task_base(header);
    2457     mapping_vspace_t *  vspace  = _get_vspace_base(header);
    2458     mapping_cluster_t * cluster = _get_cluster_base(header);
    2459 
    2460     unsigned int task_id;
    2461     unsigned int vspace_id;
    2462 
    2463     // scan all vspaces
    2464     for( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
    2465     {
    2466         _printf("\n*** vspace %s\n", vspace[vspace_id].name );
    2467 
    2468         // scan all tasks in vspace
    2469         unsigned int min = vspace[vspace_id].task_offset ;
    2470         unsigned int max = min + vspace[vspace_id].tasks ;
    2471         for ( task_id = min ; task_id < max ; task_id++ )
    2472         {
    2473             unsigned int         clusterid = task[task_id].clusterid;
    2474             unsigned int         p         = task[task_id].proclocid;
    2475             unsigned int         x         = cluster[clusterid].x;
    2476             unsigned int         y         = cluster[clusterid].y;
    2477             unsigned int         ltid      = task[task_id].ltid;
    2478             static_scheduler_t*  psched    = (static_scheduler_t*)_schedulers[x][y][p];
    2479             unsigned int         norun     = psched->context[ltid][CTX_NORUN_ID];
    2480             unsigned int         current   = psched->current;
    2481 
    2482             if ( current == ltid )
    2483             _printf(" - task %s on P[%d,%d,%d] : running\n", task[task_id].name, x, y, p );
    2484             else if ( norun == 0 )
    2485             _printf(" - task %s on P[%d,%d,%d] : runable\n", task[task_id].name, x, y, p );
    2486             else
    2487             _printf(" - task %s on P[%d,%d,%d] : blocked\n", task[task_id].name, x, y, p );
    2488         }
    2489     }
    2490     return 0;
    2491 }  // end _sys_tasks_status()
    2492 
    2493 int _sys_fat_read( unsigned int fd_id,
    2494                    unsigned int buffer,
    2495                    unsigned int count )
    2496 {
    2497     return _fat_read(fd_id, buffer, count, 0);
    2498 }
    2499 
    25003205
    25013206
Note: See TracChangeset for help on using the changeset viewer.