Index: soft/giet_vm/giet_kernel/sys_handler.c
===================================================================
--- soft/giet_vm/giet_kernel/sys_handler.c	(revision 707)
+++ soft/giet_vm/giet_kernel/sys_handler.c	(revision 709)
@@ -26,4 +26,16 @@
 #include <io.h>
 
+#if !defined(X_SIZE) 
+# error: You must define X_SIZE in the hard_config.h file
+#endif
+
+#if !defined(Y_SIZE) 
+# error: You must define Y_SIZE in the hard_config.h file
+#endif
+
+#if !defined(NB_PROCS_MAX)
+# error: You must define NB_PROCS_MAX in the hard_config.h file
+#endif
+
 #if !defined(SEG_BOOT_MAPPING_BASE) 
 # error: You must define SEG_BOOT_MAPPING_BASE in the hard_config.h file
@@ -75,33 +87,57 @@
 extern unsigned int   _coproc_mode[X_SIZE*Y_SIZE];
 extern unsigned int   _coproc_error[X_SIZE*Y_SIZE];
-extern unsigned int   _coproc_gtid[X_SIZE*Y_SIZE];
-
+extern unsigned int   _coproc_trdid[X_SIZE*Y_SIZE];
 
 // allocated in tty_driver.c file.
-extern unsigned int _tty_rx_full[NB_TTY_CHANNELS];
-extern unsigned int _tty_rx_buf[NB_TTY_CHANNELS];
+extern tty_fifo_t   _tty_rx_fifo[NB_TTY_CHANNELS];
 
 // allocated in kernel_init.c file
 extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
 
-////////////////////////////////////////////////////////////////////////////
-//     Channel allocators for peripherals
-//     (TTY[0] is reserved for kernel)
-////////////////////////////////////////////////////////////////////////////
-
+////////////////////////////////////////////////////////////////////////////////
+//     Channel allocators for multi-channels peripherals
+// - The array _***_channel_allocator[channel] defines the number of user
+//   threads for a dynamically allocated channel of peripheral ***.
+// - The array _***_channel_wti[channel] defines the WTI index and the 
+//   processor coordinates for the processor receiving the channel WTI.
+////////////////////////////////////////////////////////////////////////////////
+
+#if NB_TTY_CHANNELS
 __attribute__((section(".kdata")))
-unsigned int _tty_channel[NB_TTY_CHANNELS]  = {1};
+unsigned int _tty_channel_alloc[NB_TTY_CHANNELS] = {0};
 
 __attribute__((section(".kdata")))
-unsigned int _tim_channel_allocator    = 0;
-
+unsigned int _tty_channel_wti[NB_TTY_CHANNELS];
+#endif
+
+#if NB_TIM_CHANNELS
 __attribute__((section(".kdata")))
-unsigned int _cma_channel[NB_CMA_CHANNELS]  = {0};
+unsigned int _tim_channel_alloc[NB_TIM_CHANNELS] = {0};
 
 __attribute__((section(".kdata")))
-unsigned int _nic_rx_channel_allocator = 0;
-
+unsigned int _tim_channel_wti[NB_TIM_CHANNELS];
+#endif
+
+#if NB_CMA_CHANNELS
 __attribute__((section(".kdata")))
-unsigned int _nic_tx_channel_allocator = 0;
+unsigned int _cma_channel_alloc[NB_CMA_CHANNELS] = {0};
+
+__attribute__((section(".kdata")))
+unsigned int _cma_channel_wti[NB_CMA_CHANNELS];
+#endif
+
+#if NB_NIC_CHANNELS
+__attribute__((section(".kdata")))
+unsigned int _nic_rx_channel_alloc[NB_NIC_CHANNELS] = {0};
+
+__attribute__((section(".kdata")))
+unsigned int _nic_rx_channel_wti[NB_NIC_CHANNELS];
+
+__attribute__((section(".kdata")))
+unsigned int _nic_tx_channel_alloc[NB_NIC_CHANNELS] = {0};
+
+__attribute__((section(".kdata")))
+unsigned int _nic_tx_channel_wti[NB_NIC_CHANNELS];
+#endif
 
 ////////////////////////////////////////////////////////////////////////////
@@ -140,12 +176,12 @@
     &_sys_proc_xyp,                  /* 0x00 */
     &_get_proctime,                  /* 0x01 */
-    &_sys_tty_write,                 /* 0x02 */
-    &_sys_tty_read,                  /* 0x03 */
-    &_sys_tty_alloc,                 /* 0x04 */
-    &_sys_tasks_status,              /* 0x05 */
+    &_sys_procs_number,              /* 0x02 */
+    &_sys_xy_from_ptr,               /* 0x03 */
+    &_sys_ukn,                       /* 0x04 */
+    &_sys_ukn,                       /* 0x05 */
     &_sys_ukn,                       /* 0x06 */
     &_sys_heap_info,                 /* 0x07 */
-    &_sys_local_task_id,             /* 0x08 */
-    &_sys_global_task_id,            /* 0x09 */ 
+    &_sys_vseg_get_vbase,            /* 0x08 */
+    &_sys_vseg_get_length,           /* 0x09 */ 
     &_sys_fbf_cma_alloc,             /* 0x0A */
     &_sys_fbf_cma_init_buf,          /* 0x0B */
@@ -153,10 +189,10 @@
     &_sys_fbf_cma_display,           /* 0x0D */
     &_sys_fbf_cma_stop,              /* 0x0E */
-    &_sys_task_exit,                 /* 0x0F */
-
-    &_sys_procs_number,              /* 0x10 */
+    &_sys_ukn,                       /* 0x0F */
+
+    &_sys_applications_status,       /* 0x10 */
     &_sys_fbf_sync_write,            /* 0x11 */
     &_sys_fbf_sync_read,             /* 0x12 */
-    &_sys_thread_id,                 /* 0x13 */
+    &_sys_ukn,                       /* 0x13 */
     &_sys_tim_alloc,                 /* 0x14 */
     &_sys_tim_start,                 /* 0x15 */ 
@@ -164,14 +200,14 @@
     &_sys_kill_application,          /* 0x17 */
     &_sys_exec_application,          /* 0x18 */   
-    &_sys_context_switch,            /* 0x19 */
-    &_sys_vseg_get_vbase,            /* 0x1A */
-    &_sys_vseg_get_length,           /* 0x1B */
-    &_sys_xy_from_ptr,               /* 0x1C */
-    &_sys_ukn,                       /* 0x1D */
-    &_sys_ukn,                       /* 0x1E */
-    &_sys_ukn,                       /* 0x1F */
+    &_sys_ukn,                       /* 0x19 */
+    &_sys_pthread_control,           /* 0x1A */
+    &_sys_pthread_yield,             /* 0x1B */
+    &_sys_pthread_kill,              /* 0x1C */
+    &_sys_pthread_create,            /* 0x1D */
+    &_sys_pthread_join,              /* 0x1E */
+    &_sys_pthread_exit,              /* 0x1F */
 
     &_fat_open,                      /* 0x20 */
-    &_sys_fat_read,                  /* 0x21 */
+    &_fat_read,                      /* 0x21 */
     &_fat_write,                     /* 0x22 */
     &_fat_lseek,                     /* 0x23 */
@@ -195,7 +231,7 @@
     &_sys_nic_stats,                 /* 0x34 */
     &_sys_nic_clear,                 /* 0x35 */ 
-    &_sys_ukn,                       /* 0x36 */
-    &_sys_ukn,                       /* 0x37 */
-    &_sys_ukn,                       /* 0x38 */   
+    &_sys_tty_write,                 /* 0x36 */
+    &_sys_tty_read,                  /* 0x37 */
+    &_sys_tty_alloc,                 /* 0x38 */
     &_sys_ukn,                       /* 0x39 */
     &_sys_ukn,                       /* 0x3A */
@@ -207,8 +243,17 @@
 };
 
+
+//////////////////////////////////////////////////////////////////////////////
+//           Applications related syscall handlers 
+//////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+// This function is called by the _sys_exec_application function
+// to reload all data segments contained in an application.elf file.
 ////////////////////////////////////////////////////////////////////////
 static unsigned int _load_writable_segments( mapping_vspace_t*  vspace )
 {
-#if GIET_DEBUG_SWITCH
+
+#if GIET_DEBUG_EXEC  
 unsigned int gpid       = _get_procid();
 unsigned int cluster_xy = gpid >> P_WIDTH;
@@ -216,7 +261,7 @@
 unsigned int x          = cluster_xy >> Y_WIDTH;
 unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
-if ( _get_proctime() > GIET_DEBUG_SWITCH )
-_printf("\n[DEBUG SWITCH] P[%d,%d,%d] _load_writable_segments() : enters for %s\n",
-        x , y , p , vspace->name );
+if ( _get_proctime() > GIET_DEBUG_EXEC )
+_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
+        "enters for %s\n", x , y , p , vspace->name );
 #endif
 
@@ -224,38 +269,44 @@
     mapping_vseg_t*    vseg    = _get_vseg_base(header);
 
-    // buffer to store one cluster
-    char  buf[4096];
-
-    // open the .elf file associated to vspace
-    unsigned int      vseg_id;
-    unsigned int      fd = 0;
-
+    unsigned int vseg_id;        // vseg index in mapping
+    char         buf[4096];      // buffer to store one cluster
+    unsigned int fd = 0;         // file descriptor
+
+    // first scan on vsegs in vspace to find the .elf pathname
     for (vseg_id = vspace->vseg_offset;
          vseg_id < (vspace->vseg_offset + vspace->vsegs);
          vseg_id++)
     {
-        if(vseg[vseg_id].type == VSEG_TYPE_ELF)
+        if( vseg[vseg_id].type == VSEG_TYPE_ELF )
         {
+            // open the .elf file associated to vspace
             fd = _fat_open( vseg[vseg_id].binpath , O_RDONLY );
-
-#if GIET_DEBUG_SWITCH
-if ( _get_proctime() > GIET_DEBUG_SWITCH )
-_printf("\n[DEBUG SWITCH] P[%d,%d,%d] _load_writable_segments() : open %s / fd = %d\n",
-        x , y , p , vseg[vseg_id].binpath , fd );
-#endif
-
             if ( fd < 0 ) return 1;
             break;
+
+#if GIET_DEBUG_EXEC
+if ( _get_proctime() > GIET_DEBUG_EXEC )
+_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
+        "open %s / fd = %d\n", x , y , p , vseg[vseg_id].binpath , fd );
+#endif
         }
     }
-
+ 
     // load Elf-Header into buffer from .elf file
-    if ( _fat_lseek( fd, 0, SEEK_SET ) < 0 ) return 1;
-    if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 ) return 1;
-
-#if GIET_DEBUG_SWITCH
-if ( _get_proctime() > GIET_DEBUG_SWITCH )
-_printf("\n[DEBUG SWITCH] P[%d,%d,%d] _load_writable_segments() : load Elf-Header\n",
-        x , y , p );
+    if ( _fat_lseek( fd, 0, SEEK_SET ) < 0 )
+    {
+        _fat_close( fd );
+        return 1;
+    }
+    if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 )
+    {
+        _fat_close( fd );
+        return 1;
+    }
+
+#if GIET_DEBUG_EXEC
+if ( _get_proctime() > GIET_DEBUG_EXEC )
+_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
+        "loaded Elf-Header\n", x , y , p );
 #endif
 
@@ -266,11 +317,19 @@
 
     // load Program-Header-Table from .elf file
-    if ( _fat_lseek( fd, offset, SEEK_SET ) < 0 ) return 1;
-    if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 ) return 1;
-
-#if GIET_DEBUG_SWITCH
-if ( _get_proctime() > GIET_DEBUG_SWITCH )
-_printf("\n[DEBUG SWITCH] P[%d,%d,%d] _load_writable_segments() : "
-        "load Program-Header-Table\n", x , y , p );
+    if ( _fat_lseek( fd, offset, SEEK_SET ) < 0 )
+    {
+        _fat_close( fd );
+        return 1;
+    }
+    if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 )
+    {
+        _fat_close( fd );
+        return 1;
+    }
+
+#if GIET_DEBUG_EXEC
+if ( _get_proctime() > GIET_DEBUG_EXEC )
+_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
+        "loaded Program-Header-Table\n", x , y , p );
 #endif
 
@@ -278,24 +337,53 @@
     Elf32_Phdr*  elf_pht_ptr = (Elf32_Phdr*)buf;
 
-    // scan segments to  load all loadable & writable segments
-    unsigned int seg_id;
-    for (seg_id = 0 ; seg_id < nsegments ; seg_id++)
-    {
-        if ( (elf_pht_ptr[seg_id].p_type == PT_LOAD) &&    // loadable
-             (elf_pht_ptr[seg_id].p_flags & PF_W) )        // writable
+    // second scan on vsegs in vspace to load the seg_data segments :
+    // - type == VSEG_TYPE_ELF
+    // - non eXecutable
+    for (vseg_id = vspace->vseg_offset;
+         vseg_id < (vspace->vseg_offset + vspace->vsegs);
+         vseg_id++)
+    {
+        if( (vseg[vseg_id].type == VSEG_TYPE_ELF) &&   // type ELF
+            ((vseg[vseg_id].mode & 0x4) == 0) )        // non executable 
         {
-            // Get segment attributes
-            paddr_t      seg_paddr  = vseg[vseg_id].pbase;
-            unsigned int seg_offset = elf_pht_ptr[seg_id].p_offset;
-            unsigned int seg_size   = elf_pht_ptr[seg_id].p_filesz;
-
-            // load the segment
-            if ( _fat_lseek( fd, seg_offset, SEEK_SET ) < 0 ) return 1;
-            if ( _fat_read( fd, seg_paddr, seg_size, 1 ) < 0 ) return 1;
-
-#if GIET_DEBUG_SWITCH
-if ( _get_proctime() > GIET_DEBUG_SWITCH )
-_printf("\n[DEBUG SWITCH] P[%d,%d,%d] _load_writable_segments() : load segment %x\n",
-        x , y , p , seg_vaddr );
+            // get vbase and pbase
+            paddr_t      pbase = vseg[vseg_id].pbase; 
+            unsigned int vbase = vseg[vseg_id].vbase;
+
+            // scan segments in Progam-Header-Table to find match
+            // No match checking as the segment was previously found
+            unsigned int seg;
+            for (seg = 0 ; seg < nsegments ; seg++)
+            {
+                if ( (elf_pht_ptr[seg].p_type == PT_LOAD) &&    // loadable
+                     (elf_pht_ptr[seg].p_flags & PF_W)    &&    // writable
+                     (elf_pht_ptr[seg].p_vaddr == vbase) )      // matching
+                {
+                    // Get segment offset and size in .elf file
+                    unsigned int seg_offset = elf_pht_ptr[seg].p_offset;
+                    unsigned int seg_size   = elf_pht_ptr[seg].p_filesz;
+
+                    // compute destination address and extension for _fat_read()
+                    unsigned int dest   = (unsigned int)pbase;
+                    unsigned int extend = (unsigned int)(pbase>>32) | 0xFFFF0000;
+
+                    // load the segment
+                    if ( _fat_lseek( fd, seg_offset, SEEK_SET ) < 0 ) 
+                    {
+                        _fat_close( fd );
+                        return 1;
+                    }
+                    if ( _fat_read( fd, dest, seg_size, extend ) < 0 )
+                    {
+                        _fat_close( fd );
+                        return 1;
+                    }
+                }
+            }
+
+#if GIET_DEBUG_EXEC
+if ( _get_proctime() > GIET_DEBUG_EXEC )
+_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
+        "loaded segment %x\n", x , y , p , vbase );
 #endif
         }
@@ -308,7 +396,141 @@
 }  // end load_writable_segments()
 
-//////////////////////////////////////////////////////////////////////////////
-//           Applications related syscall handlers 
-//////////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////
+int _sys_exec_application( char* name )
+{
+    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
+    mapping_vspace_t * vspace  = _get_vspace_base(header);
+    mapping_thread_t * thread  = _get_thread_base(header);
+    mapping_vseg_t   * vseg    = _get_vseg_base(header);
+
+    unsigned int vspace_id;
+    unsigned int thread_id;
+
+#if GIET_DEBUG_EXEC 
+unsigned int gpid       = _get_procid();
+unsigned int cluster_xy = gpid >> P_WIDTH;
+unsigned int p          = gpid & ((1<<P_WIDTH)-1);
+unsigned int x          = cluster_xy >> Y_WIDTH;
+unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
+if ( _get_proctime() > GIET_DEBUG_EXEC )
+_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
+        "enters for %s at cycle %d\n", x, y, p, name, _get_proctime() );
+#endif
+
+    unsigned int y_size = header->y_size;
+
+    // scan vspaces to find matching vspace name
+    for (vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++) 
+    {
+        if ( _strcmp( vspace[vspace_id].name, name ) == 0 )  // vspace found
+        {
+
+#if GIET_DEBUG_EXEC 
+if ( _get_proctime() > GIET_DEBUG_EXEC )
+_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
+        "found vspace %s at cycle  %d\n", x, y, p, name, _get_proctime() );
+#endif
+            // reload writable segments
+            if ( _load_writable_segments( &vspace[vspace_id] ) )
+            {
+                _printf("[GIET ERROR] _sys_exec_application() : "
+                        "can't load data segment for vspace %s\n", name );
+                return GIET_SYSCALL_CANNOT_LOAD_DATA_SEGMENT;
+            }
+ 
+#if GIET_DEBUG_EXEC 
+if ( _get_proctime() > GIET_DEBUG_EXEC )
+_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
+        "load segments for vspace %s at cycle  %d\n", x, y, p, name, _get_proctime() );
+#endif
+            // scan threads in vspace with three goals :
+            // - check all threads desactivated
+            // - re-initialise all threads contexts
+            // - find main thread
+            unsigned int        main_found  = 0;
+            unsigned int        main_ltid   = 0;
+            static_scheduler_t* main_psched = NULL;
+            unsigned int        min         = vspace[vspace_id].thread_offset; 
+            unsigned int        max         = min + vspace[vspace_id].threads; 
+            for ( thread_id = min ; thread_id < max ; thread_id++ ) 
+            {
+                // get thread identifiers : [x,y,p,ltid]
+                unsigned int cid   = thread[thread_id].clusterid;
+                unsigned int x     = cid / y_size;
+                unsigned int y     = cid % y_size;
+                unsigned int p     = thread[thread_id].proclocid;
+                unsigned int ltid  = thread[thread_id].ltid;
+                unsigned int vsid  = thread[thread_id].stack_vseg_id;
+
+                // get scheduler pointer
+                static_scheduler_t* psched = _schedulers[x][y][p];
+
+                // check thread non active
+                if ( psched->context[ltid].slot[CTX_NORUN_ID] == 0 )  // runnable !!!
+                {
+                    _printf("\n[GIET ERROR] in _sys_exec_application() : "
+                            "thread %s already active in vspace %s\n",
+                            thread[thread_id].name, name );
+                    return GIET_SYSCALL_THREAD_ALREADY_ACTIVE;
+                }
+                
+                // initialise thread context
+                unsigned int ctx_epc = psched->context[ltid].slot[CTX_ENTRY_ID];
+                unsigned int ctx_sp  = vseg[vsid].vbase + vseg[vsid].length;
+                unsigned int ctx_ra  = (unsigned int)&_ctx_eret;
+                unsigned int ctx_sr  = GIET_SR_INIT_VALUE;
+
+                psched->context[ltid].slot[CTX_EPC_ID] = ctx_epc;
+                psched->context[ltid].slot[CTX_RA_ID]  = ctx_ra;
+                psched->context[ltid].slot[CTX_SR_ID]  = ctx_sr;
+                psched->context[ltid].slot[CTX_SP_ID]  = ctx_sp;
+
+                // register information required to activate main thread
+                // actual activation done when threads initialisation is completed
+                if ( thread[thread_id].is_main ) 
+                {
+                    main_psched = psched;
+                    main_ltid   = ltid;
+                    main_found  = 1;
+                }
+ 
+#if GIET_DEBUG_EXEC 
+if ( _get_proctime() > GIET_DEBUG_EXEC )
+_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
+        "initialise thread %s at cycle  %d\n",
+        x, y, p, thread[thread_id].name, _get_proctime() );
+#endif
+            }  // end loop on vspace threads
+
+            // activate main thread
+            if ( main_found )
+            {
+                main_psched->context[main_ltid].slot[CTX_NORUN_ID] = 0;
+            }
+            else
+            {
+                _printf("\n[GIET ERROR] in _sys_exec_application() : "
+                        "main not found in vspace %s\n", name );
+                return GIET_SYSCALL_MAIN_NOT_FOUND;
+            }
+             
+#if GIET_DEBUG_EXEC 
+if ( _get_proctime() > GIET_DEBUG_EXEC )
+_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
+        "lauched %s at cycle %d\n", x, y, p, name, _get_proctime() );
+#endif
+            return GIET_SYSCALL_OK;
+        }
+    }  // end of loop on vspaces
+
+    // vspace not found
+    _printf("\n[GIET ERROR] in _sys_exec_application() : "
+            "vspace %s not found\n", name );
+    return GIET_SYSCALL_VSPACE_NOT_FOUND;
+
+}  // end _sys_exec_application()
+    
 
 ///////////////////////////////////////
@@ -317,153 +539,522 @@
     mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
     mapping_vspace_t * vspace  = _get_vspace_base(header);
-    mapping_task_t   * task    = _get_task_base(header);
+    mapping_thread_t * thread  = _get_thread_base(header);
 
     unsigned int vspace_id;
-    unsigned int task_id;
-    unsigned int y_size = header->y_size;
+    unsigned int thread_id;
 
 #if GIET_DEBUG_EXEC
+unsigned int gpid       = _get_procid();
+unsigned int cluster_xy = gpid >> P_WIDTH;
+unsigned int p          = gpid & ((1<<P_WIDTH)-1);
+unsigned int x          = cluster_xy >> Y_WIDTH;
+unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
 if ( _get_proctime() > GIET_DEBUG_EXEC )
-_printf("\n[DEBUG EXEC] enters _sys_kill_application() for %s\n", name );
-#endif
-
-    // scan vspaces
+_printf("\n[DEBUG EXEC] _sys_kill_application() P[%d,%d,%d] "
+        "enters at cycle %d for %s\n", x, y, p, _get_proctime() , name );
+#endif
+
+    // shell cannot be killed
+    if ( _strcmp( name , "shell" ) == 0 )
+    {
+        _printf("\n[GIET ERROR] in _sys_kill_application() : "
+                "%s application cannot be killed\n", name );
+        return GIET_SYSCALL_APPLI_CANNOT_BE_KILLED;
+    }
+
+    // scan vspaces to find matching vspace name
     for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
     {
         if ( _strcmp( vspace[vspace_id].name, name ) == 0 ) 
         {
-            // check if application can be killed
-            if ( vspace[vspace_id].active ) return -2;
-
-            // scan tasks in vspace
-            for (task_id = vspace[vspace_id].task_offset; 
-                 task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks); 
-                 task_id++) 
+            // scan threads to send KILL signal to all threads in vspace
+            unsigned int y_size = header->y_size;
+            unsigned int min    = vspace[vspace_id].thread_offset; 
+            unsigned int max    = min + vspace[vspace_id].threads; 
+            for ( thread_id = min ; thread_id < max ; thread_id++ ) 
             {
-                unsigned int cid   = task[task_id].clusterid;
+                unsigned int cid   = thread[thread_id].clusterid;
                 unsigned int x     = cid / y_size;
                 unsigned int y     = cid % y_size;
-                unsigned int p     = task[task_id].proclocid;
-                unsigned int ltid  = task[task_id].ltid;
-
-                // get scheduler pointer for processor running the task
+                unsigned int p     = thread[thread_id].proclocid;
+                unsigned int ltid  = thread[thread_id].ltid;
+
+                // get scheduler pointer for processor running the thread
                 static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
 
                 // set KILL signal bit
-                _atomic_or( &psched->context[ltid][CTX_SIG_ID] , SIG_MASK_KILL );
+                _atomic_or( &psched->context[ltid].slot[CTX_SIGS_ID] , SIGS_MASK_KILL );
             } 
 
 #if GIET_DEBUG_EXEC 
 if ( _get_proctime() > GIET_DEBUG_EXEC )
-_printf("\n[DEBUG EXEC] exit _sys_kill_application() : %s will be killed\n", name );
-#endif
-
-            return 0;
+_printf("\n[DEBUG EXEC] _sys_kill_application() P[%d,%d,%d] "
+        "kill %s at cycle %d\n", x, y, p, name, _get_proctime() );
+#endif
+
+            return GIET_SYSCALL_OK;
         }
-    } 
+    }  // en loop on vspaces
+
+    _printf("\n[GIET ERROR] in _sys_kill_application() : "
+            "application %s not found\n", name );
+    return GIET_SYSCALL_VSPACE_NOT_FOUND;
+
+}  // end _sys_kill_application()
+    
+
+
+//////////////////////////////
+int _sys_applications_status()
+{
+    mapping_header_t *  header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
+    mapping_thread_t *  thread  = _get_thread_base(header);
+    mapping_vspace_t *  vspace  = _get_vspace_base(header);
+    mapping_cluster_t * cluster = _get_cluster_base(header);
+
+    unsigned int thread_id;
+    unsigned int vspace_id;
+
+    // scan all vspaces
+    for( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
+    {
+        _user_printf("\n*** vspace %s\n", vspace[vspace_id].name );
+
+        // scan all threads in vspace
+        unsigned int min = vspace[vspace_id].thread_offset ;
+        unsigned int max = min + vspace[vspace_id].threads ;
+        for ( thread_id = min ; thread_id < max ; thread_id++ )
+        {
+            unsigned int         clusterid = thread[thread_id].clusterid;
+            unsigned int         p         = thread[thread_id].proclocid;
+            unsigned int         x         = cluster[clusterid].x;
+            unsigned int         y         = cluster[clusterid].y;
+            unsigned int         ltid      = thread[thread_id].ltid;
+            static_scheduler_t*  psched    = (static_scheduler_t*)_schedulers[x][y][p];
+            unsigned int         norun     = psched->context[ltid].slot[CTX_NORUN_ID];
+            unsigned int         tty       = psched->context[ltid].slot[CTX_TTY_ID];
+            unsigned int         current   = psched->current;
+
+            if ( current == ltid )
+            _user_printf(" - thread %s / P[%d,%d,%d] / ltid = %d / "
+                         "TTY = %d / norun = %x : running\n", 
+                         thread[thread_id].name, x, y, p, ltid, tty, norun );
+            else if ( norun == 0 )
+            _user_printf(" - thread %s / P[%d,%d,%d] / ltid = %d / "
+                         "TTY = %d / norun = %x : runable\n", 
+                         thread[thread_id].name, x, y, p, ltid, tty, norun);
+            else
+            _user_printf(" - thread %s / P[%d,%d,%d] / ltid = %d / "
+                         "TTY = %d / norun = %x : blocked\n", 
+                         thread[thread_id].name, x, y, p, ltid, tty, norun);
+        }
+    }
+    _user_printf("\n");
+    return GIET_SYSCALL_OK;
+}  // end _sys_applications_status()
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//          Threads related syscall handlers
+/////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////
+int _sys_pthread_create( unsigned int*  buffer,
+                         void*          attr,
+                         void*          function,
+                         void*          arg )
+{
+    // attr argument not supported
+    if ( attr != NULL )
+    {
+        _printf("\n[GIET ERROR] in _sys_pthread_create() : "
+                "attr argument not supported\n" );
+        
+        return GIET_SYSCALL_PTHREAD_ARGUMENT_NOT_SUPPORTED;
+    }
+
+    // get pointers in mapping
+    mapping_header_t*    header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
+    mapping_thread_t*    thread   = _get_thread_base(header);
+    mapping_vspace_t*    vspace   = _get_vspace_base(header);
+    mapping_cluster_t*   cluster  = _get_cluster_base(header);
+
+    // get scheduler for processor running the calling thread
+    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
+
+    // get calling thread local index in scheduler
+    unsigned int  current = psched->current;
+
+    // get vspace index
+    unsigned int  vspace_id = psched->context[current].slot[CTX_VSID_ID];
 
 #if GIET_DEBUG_EXEC 
 if ( _get_proctime() > GIET_DEBUG_EXEC )
-_printf("\n[DEBUG EXEC] exit _sys_kill_application() : %s not found\n", name );
-#endif
-
-    return -1;    // not found 
-
-}  // end _sys_kill_application()
+_printf("\n[DEBUG EXEC] _sys_pthread_create() : enters at cycle %d"
+        " for vspace %s / entry = %x\n",
+        _get_proctime() , vspace[vspace_id].name , (unsigned int)function );
+#endif
+
+    unsigned int thread_id;        // searched thread : local index in mapping
+    unsigned int clusterid;        // searched thread : cluster index
+    unsigned int lpid;             // searched thread : processor local index
+    unsigned int ltid;             // searched thread : scheduler thread index
+    unsigned int cx;               // searched thread : X coordinate for searched thread
+    unsigned int cy;               // searched thread : Y coordinate for searched thread
+    unsigned int entry;            // searched thread : entry point
+    unsigned int norun;            // searched thread : norun vector
+    unsigned int trdid;            // searched thread : thread identifier
+
+    // scan threads in vspace to find an inactive thread matching function
+    unsigned int min   = vspace[vspace_id].thread_offset;
+    unsigned int max   = min + vspace[vspace_id].threads;
+    unsigned int found = 0;
+    for ( thread_id = min ; (thread_id < max) && (found == 0) ; thread_id++ )
+    {
+        // get thread coordinates [cx,cy,lpid] and ltid from mapping
+        ltid       = thread[thread_id].ltid;
+        clusterid  = thread[thread_id].clusterid; 
+        lpid       = thread[thread_id].proclocid;
+        cx = cluster[clusterid].x;
+        cy = cluster[clusterid].y;
+
+        // get thread scheduler pointer
+        psched = _schedulers[cx][cy][lpid];
+
+        // get thread entry-point, norun-vector, and trdid from context
+        entry = psched->context[ltid].slot[CTX_ENTRY_ID];
+        norun = psched->context[ltid].slot[CTX_NORUN_ID];
+        trdid = psched->context[ltid].slot[CTX_TRDID_ID];
+
+        // check matching
+        if ( ((unsigned int)function == entry ) && 
+             (norun & NORUN_MASK_THREAD)  ) found = 1;
+
+    }  // end loop on threads
+
+    if ( found )  // one matching inactive thread has been found
+    {
+        // set argument value in thread context
+        if ( arg != NULL ) psched->context[ltid].slot[CTX_A0_ID] = (unsigned int)arg;
+
+        // activate thread
+        psched->context[ltid].slot[CTX_NORUN_ID] = 0;
+
+        // return launched thead global identifier
+        *buffer   = trdid;
+                
+#if GIET_DEBUG_EXEC 
+if ( _get_proctime() > GIET_DEBUG_EXEC )
+_printf("\n[DEBUG EXEC] exit _sys_pthread_create() at cycle %d : thread %x launched\n",
+        _get_proctime() , trdid);
+#endif
+        return GIET_SYSCALL_OK;
+    }
+    else         // no matching thread found
+    {
+        _printf("\n[GIET ERROR] in _sys_pthread_create() : "
+                "no matching thread for entry = %x in vspace %s\n",
+                (unsigned int)function , vspace[vspace_id].name );
+        
+        return GIET_SYSCALL_THREAD_NOT_FOUND;
+    }
+
+} // end _sys_pthread_create()
+
+
+///////////////////////////////////////////
+int _sys_pthread_join( unsigned int  trdid,
+                       void*         ptr )
+{
+    // ptr argument not supported
+    if ( ptr != NULL )
+    {
+        _printf("\n[GIET ERROR] in _sys_pthread_join() : "
+                "ptr argument not supported, must be NULL\n" );
+        
+        return GIET_SYSCALL_PTHREAD_ARGUMENT_NOT_SUPPORTED;
+    }
+
+                
+#if GIET_DEBUG_EXEC 
+if ( _get_proctime() > GIET_DEBUG_EXEC )
+_printf("\n[DEBUG EXEC] enters _sys_pthread_join() at cycle %d for thread %x\n",
+        _get_proctime() , trdid );
+#endif
+
+    // get calling thread vspace
+    unsigned int  caller_vspace = _get_context_slot( CTX_VSID_ID );
+
+    // get and check target thread indexes from trdid
+    unsigned int cx   = (trdid>>24) & 0xFF;
+    unsigned int cy   = (trdid>>16) & 0xFF;
+    unsigned int lpid = (trdid>>8 ) & 0xFF;
+    unsigned int ltid = (trdid    ) & 0xFF;
+
+    // get target thread scheduler, vspace and registered trdid
+    static_scheduler_t*  psched   = _schedulers[cx][cy][lpid];
+    unsigned int target_vspace    = psched->context[ltid].slot[CTX_VSID_ID];
+    unsigned int registered_trdid = psched->context[ltid].slot[CTX_TRDID_ID];
+
+    // check trdid
+    if ( trdid != registered_trdid )
+    {
+       _printf("\nerror in _sys_pthread_join() : "
+               "trdid = %x / registered_trdid = %x\n",
+               trdid , registered_trdid );
+
+       return GIET_SYSCALL_UNCOHERENT_THREAD_CONTEXT;
+    }
+   
+    // check calling thread and target thread in same vspace
+    if ( caller_vspace != target_vspace )
+    {
+       _printf("\n[GIET ERROR] in _sys_pthread_join() : "
+               " calling thread and target thread not in same vspace\n");
+
+       return GIET_SYSCALL_NOT_IN_SAME_VSPACE;
+    }
+
+    // get target thread state
+    unsigned int* pnorun = &psched->context[ltid].slot[CTX_NORUN_ID];
+
+    asm volatile ( "2000:                      \n"                         
+                   "move  $11,  %0             \n"   /* $11 <= ptr           */
+                   "lw    $11,  0($11)         \n"   /* $11 <= M[ptr]        */
+                   "andi  $11,  $11,    1      \n"   /* $11 <= norun & 0x1   */
+                   "beqz  $11,  2000b          \n"   
+                   :
+                   : "r" (pnorun)
+                   : "$11" );
+
+    return GIET_SYSCALL_OK;
+
+}  // end _sys_pthread_join()
+                       
+
+////////////////////////////////////////
+int _sys_pthread_kill( pthread_t  trdid,
+                       int        signal )
+{
+    // get calling thread vspace
+    unsigned int  caller_vspace = _get_context_slot( CTX_VSID_ID );
+
+    // get and check target thread indexes from trdid
+    unsigned int cx   = (trdid>>24) & 0xFF;
+    unsigned int cy   = (trdid>>16) & 0xFF;
+    unsigned int lpid = (trdid>>8 ) & 0xFF;
+    unsigned int ltid = (trdid    ) & 0xFF;
+
+    // get target thread scheduler, vspace and registered trdid
+    static_scheduler_t*  psched       = _schedulers[cx][cy][lpid];
+    unsigned int target_vspace        = psched->context[ltid].slot[CTX_VSID_ID];
+    unsigned int registered_trdid = psched->context[ltid].slot[CTX_TRDID_ID];
+
+    // check trdid
+    if ( trdid != registered_trdid )
+    {
+       _printf("\n[GIET ERROR] in _sys_pthread_kill() : trdid = %x"
+               " / registered_trdid = %x\n", trdid , registered_trdid );
+       return GIET_SYSCALL_UNCOHERENT_THREAD_CONTEXT;
+    }
+   
+    // check calling thread and target thread in same vspace
+    if ( caller_vspace != target_vspace )
+    {
+       _printf("\n[GIET ERROR] in _sys_pthread_kill() : not in same vspace\n");
+       return GIET_SYSCALL_NOT_IN_SAME_VSPACE;
+    }
+
+    // register KILL signal in target thread context if required
+    if ( signal )
+    {
+        _atomic_or( &psched->context[ltid].slot[CTX_SIGS_ID] , SIGS_MASK_KILL );
+    }
+
+    return GIET_SYSCALL_OK;
+
+}  // end _sys_pthread_kill()
+
+
+/////////////////////////////////////
+int _sys_pthread_exit( void* string ) 
+{
+    unsigned int date       = _get_proctime();
+
+    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
+    mapping_vspace_t * vspace  = _get_vspace_base(header);
+
+    unsigned int ltid       = _get_context_slot(CTX_LTID_ID);
+    unsigned int trdid      = _get_context_slot(CTX_TRDID_ID);
+    unsigned int vsid       = _get_context_slot(CTX_VSID_ID);
+
+    // print exit message
+    if ( string == NULL )
+    {
+        _printf("\n[GIET WARNING] Exit thread %x in vspace %s at cycle %d\n",
+                trdid , vspace[vsid].name , date );
+    }
+    else
+    {
+        _printf("\n[GIET WARNING] Exit thread %x in vspace %s at cycle %d\n"
+                "               Cause : %s\n\n",
+                trdid , vspace[vsid].name , date , (char*) string );
+    }
     
-///////////////////////////////////////
-int _sys_exec_application( char* name )
-{
-    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
-    mapping_vseg_t   * vseg    = _get_vseg_base(header);
-    mapping_vspace_t * vspace  = _get_vspace_base(header);
-    mapping_task_t   * task    = _get_task_base(header);
-
-    unsigned int vspace_id;
-    unsigned int task_id;
-    unsigned int y_size = header->y_size;
-
-#if GIET_DEBUG_EXEC
+    // get scheduler pointer for calling thread
+    static_scheduler_t*  psched = (static_scheduler_t*)_get_sched();
+
+    // register KILL signal in calling thread context (suicid request)
+    _atomic_or( &psched->context[ltid].slot[CTX_SIGS_ID] , SIGS_MASK_KILL );
+
+    // deschedule calling thread
+    unsigned int save_sr;  
+    _it_disable( &save_sr );
+
+    _ctx_switch();
+
+    return GIET_SYSCALL_OK;
+
+}  // end _sys_pthread_exit()
+
+////////////////////////
+int _sys_pthread_yield() 
+{
+    unsigned int save_sr;
+
+    _it_disable( &save_sr );
+    _ctx_switch();
+    _it_restore( &save_sr );
+
+    return GIET_SYSCALL_OK;
+}
+
+//////////////////////////////////////////////////
+int _sys_pthread_control( unsigned  int  command,
+                          char*     vspace_name,
+                          char*     thread_name )
+{
+
+#if GIET_DEBUG_EXEC 
 if ( _get_proctime() > GIET_DEBUG_EXEC )
-_printf("\n[DEBUG EXEC] enters _sys_exec_application() at cycle %d for %s\n",
-         _get_proctime() , name );
-#endif
-
-    // find vspace
-    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
-    {
-        if ( _strcmp( vspace[vspace_id].name, name ) == 0 )
+_printf("\n[DEBUG EXEC] _sys_pthread_control() at cycle %d : "
+        "enter for vspace %s / thread %s / command = %d\n",
+        _get_proctime() , vspace_name, thread_name, command );
+#endif
+
+    // get pointers in mapping
+    mapping_header_t*    header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
+    mapping_thread_t*    thread   = _get_thread_base(header);
+    mapping_vspace_t*    vspace   = _get_vspace_base(header);
+    mapping_cluster_t*   cluster  = _get_cluster_base(header);
+
+    unsigned int found;
+
+    // search vspace name to get vspace index: vsid
+    found = 0;
+    unsigned int   vsid;
+    for( vsid = 0 ; vsid < header->vspaces ; vsid++ )
+    {
+        if ( _strcmp( vspace[vsid].name, vspace_name ) == 0 )
+        {
+            found = 1;
             break;
-    }
-
-    if ( vspace_id == header->vspaces )
-    {
-        _printf("\n[GIET ERROR] _sys_exec_application() : %s not found\n", name );
-        return -1;
-    }
-
-    // scan tasks in vspace
-    for (task_id = vspace[vspace_id].task_offset;
-         task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
-         task_id++)
-    {
-        unsigned int cid   = task[task_id].clusterid;
-        unsigned int x     = cid / y_size;
-        unsigned int y     = cid % y_size;
-        unsigned int p     = task[task_id].proclocid;
-        unsigned int ltid  = task[task_id].ltid;
-
-        // get scheduler pointer for processor running the task
-        static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
-
-        // check if an application task is runnable
-        if ( psched->context[ltid][CTX_NORUN_ID] == 0 )
+        }
+    }
+
+    if ( found == 0 ) return GIET_SYSCALL_VSPACE_NOT_FOUND;
+
+    // search thread name in vspace to get thread index: tid
+    found = 0;
+    unsigned int   tid;
+    unsigned int   min = vspace[vsid].thread_offset;
+    unsigned int   max = min + vspace[vsid].threads;
+    for( tid = min ; tid < max ; tid++ )
+    {
+        if ( _strcmp( thread[tid].name, thread_name ) == 0 )
         {
-            _printf( "\n[GIET ERROR] _sys_exec_application() : %s already executed\n", name );
-            return -2;
+            found = 1;
+            break;
         }
     }
 
-    // reload writable segments
-    if ( _load_writable_segments( &vspace[vspace_id] ) )
-    {
-         _printf("[GIET ERROR] _sys_exec_application() : can't load segments for %s\n", name );
-         return -3;
-    }
-
-    // scan tasks in vspace
-    for (task_id = vspace[vspace_id].task_offset;
-         task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
-         task_id++)
-    {
-        unsigned int cid   = task[task_id].clusterid;
-        unsigned int x     = cid / y_size;
-        unsigned int y     = cid % y_size;
-        unsigned int p     = task[task_id].proclocid;
-        unsigned int ltid  = task[task_id].ltid;
-
-        // get scheduler pointer for processor running the task
-        static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
-
-        // reset task context: RA / SR / SP / EPC / NORUN
-        unsigned int vseg_id       = task[task_id].stack_vseg_id;
-        unsigned int sp_value      = vseg[vseg_id].vbase + vseg[vseg_id].length;
-
-        psched->context[ltid][CTX_RA_ID]     = (unsigned int)&_ctx_eret;
-        psched->context[ltid][CTX_SR_ID]     = GIET_SR_INIT_VALUE;
-        psched->context[ltid][CTX_SP_ID]     = sp_value;
-        psched->context[ltid][CTX_EPC_ID]    = psched->context[ltid][CTX_ENTRY_ID];
-        psched->context[ltid][CTX_NORUN_ID]  = 0;
-    }
-
-#if GIET_DEBUG_EXEC
-if ( _get_proctime() > GIET_DEBUG_EXEC )
-_printf("\n[DEBUG EXEC] exit _sys_exec_application() at cycle %d : %s will be executed\n",
-        _get_proctime() , name );
-#endif
-
-    return 0;
-}  // end _sys_exec_application()
-    
+    if ( found == 0 ) return GIET_SYSCALL_THREAD_NOT_FOUND;
+
+    // get thread coordinates
+    unsigned int cid  = thread[tid].clusterid;
+    unsigned int x    = cluster[cid].x;
+    unsigned int y    = cluster[cid].y;
+    unsigned int p    = thread[tid].proclocid;
+    unsigned int ltid = thread[tid].ltid;
+
+    static_scheduler_t* psched = _schedulers[x][y][p];
+
+    // check trdid and vsid
+    unsigned int trdid = x<<24 | y<<16 | p<<8 | ltid;
+    if ( (psched->context[ltid].slot[CTX_TRDID_ID] != trdid) ||
+         (psched->context[ltid].slot[CTX_VSID_ID]  != vsid) )
+        return GIET_SYSCALL_UNCOHERENT_THREAD_CONTEXT;
+
+    // execute command
+    if ( command == THREAD_CMD_PAUSE ) 
+    {
+        _atomic_or ( &psched->context[ltid].slot[CTX_NORUN_ID],  NORUN_MASK_THREAD );
+        return GIET_SYSCALL_OK;
+    }
+    else if ( command == THREAD_CMD_RESUME )
+    {
+        _atomic_and( &psched->context[ltid].slot[CTX_NORUN_ID], ~NORUN_MASK_THREAD );
+        return GIET_SYSCALL_OK;
+    }
+    else if ( command == THREAD_CMD_CONTEXT )
+    {
+        _user_printf( " - CTX_TRDID  = %x\n"
+                      " - CTX_VSID   = %x\n"
+                      " - CTX_EPC    = %x\n"
+                      " - CTX_PTAB   = %x\n"
+                      " - CTX_PTPR   = %x\n"
+                      " - CTX_SR     = %x\n"
+                      " - CTX_RA     = %x\n"
+                      " - CTX_SP     = %x\n"
+                      " - CTX_ENTRY  = %x\n"
+                      " - CTX_NORUN  = %x\n"
+                      " - CTX_SIGS   = %x\n"
+                      " - CTX_LOCKS  = %x\n"
+                      " - CTX_TTY    = %x\n"
+                      " - CTX_NIC_RX = %x\n"
+                      " - CTX_NIC_TX = %x\n"
+                      " - CTX_CMA_RX = %x\n"
+                      " - CTX_CMA_TX = %x\n"
+                      " - CTX_CMA_FB = %x\n",
+                      psched->context[ltid].slot[CTX_TRDID_ID], 
+                      psched->context[ltid].slot[CTX_VSID_ID], 
+                      psched->context[ltid].slot[CTX_EPC_ID], 
+                      psched->context[ltid].slot[CTX_PTAB_ID], 
+                      psched->context[ltid].slot[CTX_PTPR_ID], 
+                      psched->context[ltid].slot[CTX_SR_ID], 
+                      psched->context[ltid].slot[CTX_RA_ID], 
+                      psched->context[ltid].slot[CTX_SP_ID], 
+                      psched->context[ltid].slot[CTX_ENTRY_ID], 
+                      psched->context[ltid].slot[CTX_NORUN_ID],
+                      psched->context[ltid].slot[CTX_SIGS_ID],
+                      psched->context[ltid].slot[CTX_LOCKS_ID],
+                      psched->context[ltid].slot[CTX_TTY_ID],
+                      psched->context[ltid].slot[CTX_NIC_RX_ID],
+                      psched->context[ltid].slot[CTX_NIC_TX_ID],
+                      psched->context[ltid].slot[CTX_CMA_RX_ID],
+                      psched->context[ltid].slot[CTX_CMA_TX_ID],
+                      psched->context[ltid].slot[CTX_CMA_FB_ID] );
+        return GIET_SYSCALL_OK;
+    }
+    else
+    {
+        return GIET_SYSCALL_ILLEGAL_THREAD_COMMAND_TYPE;
+    }
+
+} // end _sys_pthread_control()
+
+
+
 
 //////////////////////////////////////////////////////////////////////////////
@@ -476,5 +1067,5 @@
 {
     // In this implementation, the allocation policy is constrained:
-    // the coprocessor must be in the same cluster as the calling task,
+    // the coprocessor must be in the same cluster as the calling thread,
     // and there is at most one coprocessor per cluster
 
@@ -519,5 +1110,5 @@
         *coproc_info = _coproc_info[cluster_id];
 
-        // register coprocessor coordinates in task context
+        // register coprocessor coordinates in thread context
         unsigned int cluster_xy = (x<<Y_WIDTH) + y;
         _set_context_slot( CTX_COPROC_ID , cluster_xy );
@@ -528,5 +1119,5 @@
         x , y , *coproc_info , cluster_xy );
 #endif
-        return 0;
+        return GIET_SYSCALL_OK;
     }
     else
@@ -535,5 +1126,5 @@
                  " with type %d available in cluster[%d,%d]\n",
                  coproc_type , x , y );
-        return -1;
+        return GIET_SYSCALL_COPROCESSOR_NOT_FOUND;
     }
 }  // end _sys_coproc_alloc()
@@ -553,7 +1144,7 @@
     {
          _printf("\n[GIET_ERROR] in _sys_coproc_release(): "
-                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
+                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
                  x , y , p ); 
-         return -1;
+         return GIET_SYSCALL_COPROCESSOR_NOT_FOUND;
     }
 
@@ -573,5 +1164,5 @@
     }
 
-    // deallocates coprocessor coordinates in task context
+    // deallocates coprocessor coordinates in thread context
     _set_context_slot( CTX_COPROC_ID , 0xFFFFFFFF );
 
@@ -584,5 +1175,5 @@
 #endif
 
-    return 0;
+    return GIET_SYSCALL_OK;
 }  // end _sys_coproc_release()
 
@@ -602,7 +1193,7 @@
     {
          _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
-                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
+                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
                  x , y , p ); 
-         return -1;
+         return GIET_SYSCALL_COPROCESSOR_NOT_FOUND;
     }
 
@@ -615,5 +1206,5 @@
          _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
                  " illegal mode\n");
-         return -1;
+         return GIET_SYSCALL_COPROCESSOR_ILLEGAL_MODE;
     }
 
@@ -622,11 +1213,11 @@
  
     // physical addresses
-    paddr_t            buffer_paddr;
+    unsigned long long buffer_paddr;
     unsigned int       buffer_lsb;
     unsigned int       buffer_msb;
-    paddr_t            mwmr_paddr = 0;
+    unsigned long long mwmr_paddr = 0;
     unsigned int       mwmr_lsb;
     unsigned int       mwmr_msb;
-    paddr_t            lock_paddr = 0;
+    unsigned long long lock_paddr = 0;
     unsigned int       lock_lsb;
     unsigned int       lock_msb;
@@ -674,5 +1265,5 @@
 #endif
         
-    return 0;
+    return GIET_SYSCALL_OK;
 } // end _sys_coproc_channel_init()
 
@@ -691,7 +1282,7 @@
     {
          _printf("\n[GIET_ERROR] in _sys_coproc_run(): "
-                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
+                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
                  x , y , p ); 
-         return -1;
+         return -1111;
     }
 
@@ -719,5 +1310,5 @@
             _printf("\n[GIET_ERROR] P[%d,%d,%d] in _sys_coproc_run() for coprocessor[%d,%d]\n"
                     "  all channels don't have the same mode\n", x , y , p , cx , cy );
-            return -1;
+            return -1111;
         }
     }
@@ -745,12 +1336,12 @@
 #endif
 
-        return 0;
+        return GIET_SYSCALL_OK;
     }
     ///////////////////////////////////////////////////////////////////////////
     else                                // mode == MODE_DMA_IRQ => descheduling
     {
-        // set _coproc_gtid 
-        unsigned int ltid = _get_current_task_id();
-        _coproc_gtid[cluster_id] = (procid<<16) + ltid;
+        // set _coproc_trdid 
+        unsigned int ltid = _get_thread_ltid();
+        _coproc_trdid[cluster_id] = (x<<24) + (y<<16) + (p<<8) + ltid;
 
         // enters critical section
@@ -760,5 +1351,5 @@
         // set NORUN_MASK_COPROC bit
         static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
-        unsigned int*       ptr     = &psched->context[ltid][CTX_NORUN_ID];
+        unsigned int*       ptr     = &psched->context[ltid].slot[CTX_NORUN_ID];
         _atomic_or( ptr , NORUN_MASK_COPROC );
 
@@ -771,5 +1362,5 @@
 #endif
 
-        // deschedule task
+        // deschedule thread
         _ctx_switch(); 
 
@@ -802,7 +1393,7 @@
     {
          _printf("\n[GIET_ERROR] in _sys_coproc_completed(): "
-                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
+                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
                  x , y , p ); 
-         return -1;
+         return -1111;
     }
 
@@ -879,74 +1470,85 @@
 int _sys_tty_alloc( unsigned int shared )
 {
-    unsigned int channel;
-
+    unsigned int channel;    // allocated TTY channel
+
+    // get trdid and vsid for the calling thread
+    unsigned int vsid  = _get_context_slot( CTX_VSID_ID );
+    unsigned int trdid = _get_thread_trdid();
+
+    // check no TTY already allocated to calling thread
     if ( _get_context_slot( CTX_TTY_ID ) < NB_TTY_CHANNELS )
     {
-        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : TTY channel already allocated\n");
-        return 0;
-    }
-
-    // get a new TTY channel
+        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : "
+                "TTY channel already allocated to thread %x\n", trdid );
+        return -1111;
+    }
+
+    mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
+    mapping_vspace_t  *vspace   = _get_vspace_base(header);
+    mapping_thread_t  *thread   = _get_thread_base(header);
+    
+    // compute number of users
+    unsigned int users;
+    if ( shared )  users = vspace[vsid].threads;
+    else           users = 1;
+
+    // get a TTY channel 
     for ( channel = 0 ; channel < NB_TTY_CHANNELS ; channel++ )
     {
-        if ( !_tty_channel[channel] )
-        {
-            _tty_channel[channel] = 1;
-            break;
-        }
+        unsigned int* palloc  = &_tty_channel_alloc[channel];
+
+        if ( _atomic_test_and_set( palloc , users ) == 0 ) break;
     }
     if ( channel >= NB_TTY_CHANNELS )
     {
-        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : no TTY channel available\n");
-        return -1;
-    }
-
-    // reset kernel buffer for allocated TTY channel
-    _tty_rx_full[channel] = 0;
+        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : "
+                "no TTY channel available for thread %x\n", trdid );
+        return -1111;
+    }
+
+    // initialise allocated TTY channel
+    _tty_init( channel );
 
     // allocate a WTI mailbox to the calling proc if external IRQ
-    unsigned int unused;
-    if ( USE_PIC ) _ext_irq_alloc( ISR_TTY_RX , channel , &unused ); 
+    unsigned int wti_id;
+    if ( USE_PIC ) _ext_irq_alloc( ISR_TTY_RX , channel , &wti_id ); 
+
+    // register wti_id and coordinates for processor receiving WTI
+    unsigned int procid = _get_procid();
+    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
+    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
+    unsigned int p      = procid & ((1<<P_WIDTH)-1);
+    _tty_channel_wti[channel] = x<<24 | y<<16 | p<<8 | wti_id;
    
     // update CTX_TTY_ID 
-    if ( shared )         // for all tasks in the same vspace
-    {
-        unsigned int      vspace_id = _get_context_slot( CTX_VSID_ID );
-        mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
-        mapping_vspace_t  *vspace   = _get_vspace_base(header);
-        mapping_task_t    *task     = _get_task_base(header);
-
-        // scan tasks in vspace
-        unsigned int task_id;
-        for (task_id = vspace[vspace_id].task_offset;
-             task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
-             task_id++)
+    if ( shared )         // for all threads in vspace
+    {
+        // scan threads in vspace
+        unsigned int tid;
+        for (tid = vspace[vsid].thread_offset;
+             tid < (vspace[vsid].thread_offset + vspace[vsid].threads);
+             tid++)
         {
             unsigned int y_size        = header->y_size;
-            unsigned int cid           = task[task_id].clusterid;
+            unsigned int cid           = thread[tid].clusterid;
             unsigned int x             = cid / y_size;
             unsigned int y             = cid % y_size;
-            unsigned int p             = task[task_id].proclocid;
-            unsigned int ltid          = task[task_id].ltid;
+            unsigned int p             = thread[tid].proclocid;
+            unsigned int ltid          = thread[tid].ltid;
             static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];
 
-            // don't overwrite TTY_ID
-            if ( psched->context[ltid][CTX_TTY_ID] >= NB_TTY_CHANNELS )
-            {
-                psched->context[ltid][CTX_TTY_ID] = channel;
-            }
+            psched->context[ltid].slot[CTX_TTY_ID] = channel;
         }
     }
-    else                  // for calling task only
+    else                  // for calling thread only
     {
         _set_context_slot( CTX_TTY_ID, channel );
     }
 
-    return 0;
-}
-
-/////////////////////////////////////////
-// NOTE: not a syscall
-int _sys_tty_release()
+    return GIET_SYSCALL_OK;
+}  // end _sys_tty_alloc()
+
+//////////////////////
+int _sys_tty_release()     // NOTE: not a syscall
 {
     unsigned int channel = _get_context_slot( CTX_TTY_ID );
@@ -954,44 +1556,26 @@
     if ( channel == -1 )
     {
-        _printf("\n[GIET_ERROR] in _sys_tty_release() : TTY channel already released\n");
-        return -1;
-    }
-
-    // release WTI mailbox
-    if ( USE_PIC ) _ext_irq_release( ISR_TTY_RX , channel );
-
-    // reset CTX_TTY_ID for all tasks in vspace
-    unsigned int      vspace_id = _get_context_slot( CTX_VSID_ID );
-    mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
-    mapping_vspace_t  *vspace   = _get_vspace_base(header);
-    mapping_task_t    *task     = _get_task_base(header);
-
-    unsigned int task_id;
-    for (task_id = vspace[vspace_id].task_offset;
-         task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
-         task_id++)
-    {
-        unsigned int y_size        = header->y_size;
-        unsigned int cid           = task[task_id].clusterid;
-        unsigned int x             = cid / y_size;
-        unsigned int y             = cid % y_size;
-        unsigned int p             = task[task_id].proclocid;
-        unsigned int ltid          = task[task_id].ltid;
-        static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];
-
-        // only clear matching TTY_ID
-        if ( psched->context[ltid][CTX_TTY_ID] == channel )
-        {
-            psched->context[ltid][CTX_TTY_ID] = -1;
-        }
-    }
-
-    // release TTY channel
-    _tty_channel[channel] = 0;
-
-    return 0;
-}
-
-/////////////////////////////////////////////////
+        unsigned int trdid = _get_thread_trdid();
+        _printf("\n[GIET_ERROR] in _sys_tty_release() : "
+                "TTY channel already released for thread %x\n", trdid );
+        return -1111;
+    }
+
+    // reset CTX_TTY_ID for the calling thread
+    _set_context_slot( CTX_TTY_ID , 0xFFFFFFFF );
+
+    // atomically decrement the _tty_channel_allocator[] array
+    _atomic_increment( &_tty_channel_alloc[channel] , -1 );
+
+    // release WTI mailbox if TTY channel no more used
+    if ( USE_PIC  && (_tty_channel_alloc[channel] == 0) ) 
+    {
+        _ext_irq_release( ISR_TTY_RX , channel );
+    }
+
+    return GIET_SYSCALL_OK;
+}  // end sys_tty_release()
+
+////////////////////////////////////////
 int _sys_tty_write( const char*  buffer,    
                     unsigned int length,    // number of characters
@@ -1002,5 +1586,5 @@
     // compute and check tty channel
     if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
-    if( channel >= NB_TTY_CHANNELS ) return -1;
+    if( channel >= NB_TTY_CHANNELS ) return -1111;
 
     // write string to TTY channel
@@ -1021,5 +1605,5 @@
 }
 
-////////////////////////////////////////////////
+///////////////////////////////////////
 int _sys_tty_read( char*        buffer, 
                    unsigned int length,    // unused
@@ -1028,45 +1612,51 @@
     // compute and check tty channel
     if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
-    if( channel >= NB_TTY_CHANNELS ) return -1;
-
-    // read one character from TTY channel
-    if (_tty_rx_full[channel] == 0) 
-    {
-        return 0;
-    }
-    else 
-    {
-        *buffer = _tty_rx_buf[channel];
-        _tty_rx_full[channel] = 0;
-        return 1;
-    }
+    if( channel >= NB_TTY_CHANNELS ) return -1111;
+
+    unsigned int save_sr;
+    unsigned int found = 0;
+
+    // get pointer on TTY_RX FIFO
+    tty_fifo_t*  fifo = &_tty_rx_fifo[channel];
+
+    // try to read one character from FIFO
+    // blocked in while loop until success
+    while ( found == 0 )
+    {
+        if ( fifo->sts == 0)   // FIFO empty => deschedule
+        {
+            // enters critical section
+             _it_disable( &save_sr );
+
+            // set NORUN_MASK_TTY bit for calling thread
+            static_scheduler_t* psched  = (static_scheduler_t*)_get_sched();
+            unsigned int ltid = psched->current;
+            _atomic_or( &psched->context[ltid].slot[CTX_NORUN_ID] , NORUN_MASK_TTY );
+
+            // register descheduling thread trdid
+            fifo->trdid = _get_thread_trdid();
+
+             // deschedule calling thread
+            _ctx_switch();
+
+            // exit critical section
+            _it_restore( &save_sr );
+        }
+        else                             // FIFO not empty => get one character
+        {
+            *buffer   = fifo->data[fifo->ptr];
+            fifo->sts = fifo->sts - 1;
+            fifo->ptr = (fifo->ptr + 1) % TTY_FIFO_DEPTH;
+            found     = 1;
+        }
+    }
+
+    return 1;
 }
 
-///////////////////////////////////////////
-int _sys_tty_get_lock( unsigned int   channel,       // unused
-                       unsigned int * save_sr_ptr )
-{
-    // check tty channel
-    if( channel != 0 )  return 1;
-
-    _it_disable( save_sr_ptr );
-    _sqt_lock_acquire( &_tty0_sqt_lock );
-    return 0;
-}
-
-///////////////////////////////////////////////
-int _sys_tty_release_lock( unsigned int   channel,
-                           unsigned int * save_sr_ptr )
-{
-    // check tty channel
-    if( channel != 0 )  return 1;
-
-    _sqt_lock_release( &_tty0_sqt_lock );
-    _it_restore( save_sr_ptr );
-    return 0;
-}
+
 
 //////////////////////////////////////////////////////////////////////////////
-//             TIM related syscall handlers 
+//             TIMER related syscall handlers 
 //////////////////////////////////////////////////////////////////////////////
 
@@ -1074,32 +1664,102 @@
 int _sys_tim_alloc()
 {
-    // get a new timer index 
-    unsigned int channel = _atomic_increment( &_tim_channel_allocator, 1 );
-
+
+#if NB_TIM_CHANNELS
+
+    unsigned int channel;    // allocated TIMER channel
+
+    unsigned int trdid = _get_thread_trdid();
+
+    // check no TIMER already allocated to calling thread
+    if ( _get_context_slot( CTX_TIM_ID ) < NB_TIM_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : "
+                "TIMER channel already allocated to thread %x\n", trdid );
+        return -1111;
+    }
+
+    // get a TIMER channel
+    for ( channel = 0 ; channel < NB_TIM_CHANNELS ; channel++ )
+    {
+        unsigned int* palloc  = &_tim_channel_alloc[channel];
+
+        if ( _atomic_test_and_set( palloc , 1 ) == 0 ) break;
+    }
     if ( channel >= NB_TIM_CHANNELS )
     {
-        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : not enough TIM channels\n");
-        return -1;
-    }
-    else
-    {
-        _set_context_slot( CTX_TIM_ID, channel );
-        return 0;
-    }
-}
-
-////////////////////
-// NOTE: not a syscall
-int _sys_tim_release()
-{
-    // release one timer
-    _atomic_increment( &_tim_channel_allocator, 0xFFFFFFFF );
-
-    return 0;
-}
+        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : "
+                "no TIMER channel available for thread %x\n", trdid );
+        return -1111;
+    }
+
+    // allocate a WTI mailbox to the calling proc if external IRQ
+    unsigned int wti_id;
+    if ( USE_PIC ) _ext_irq_alloc( ISR_TIMER , channel , &wti_id ); 
+
+    // register wti_id and coordinates for processor receiving WTI
+    unsigned int procid = _get_procid();
+    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
+    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
+    unsigned int p      = procid & ((1<<P_WIDTH)-1);
+    _tim_channel_wti[channel] = x<<24 | y<<16 | p<<8 | wti_id;
+   
+    // update CTX_TIM_ID in thread context
+    _set_context_slot( CTX_TIM_ID, channel );
+
+    return GIET_SYSCALL_OK;
+
+#else
+
+    _printf("\n[GIET ERROR] in _sys_tim_alloc() : NB_TIM_CHANNELS = 0\n");
+    return -1111;
+
+#endif
+}  // end _sys_tim_alloc()
+
+
+//////////////////////
+int _sys_tim_release()     // NOTE: not a syscall
+{
+
+#if NB_TIM_CHANNELS
+
+    unsigned int channel = _get_context_slot( CTX_TIM_ID );
+
+    if ( channel == -1 )
+    {
+        unsigned int trdid = _get_thread_trdid();
+        _printf("\n[GIET_ERROR] in _sys_tim_release() : "
+                "TIMER channel already released for thread %x\n", trdid );
+        return -1111;
+    }
+
+    // reset CTX_TIM_ID for the calling thread
+    _set_context_slot( CTX_TIM_ID , 0xFFFFFFFF );
+
+    // reset the _tim_channel_alloc[] array
+    _tim_channel_alloc[channel] = 0;
+
+    // release WTI mailbox if TTY channel no more used
+    if ( USE_PIC ) 
+    {
+        _ext_irq_release( PERIPH_TYPE_TIM , channel );
+    }
+
+    return GIET_SYSCALL_OK;
+
+#else
+
+    _printf("\n[GIET ERROR] in _sys_tim_release() : NB_TIM_CHANNELS = 0\n");
+    return -1111;
+
+#endif
+}  // end _sys_tim_release()
 
 /////////////////////////////////////////
 int _sys_tim_start( unsigned int period )
 {
+
+#if NB_TIM_CHANNELS
+
     // get timer index
     unsigned int channel = _get_context_slot( CTX_TIM_ID );
@@ -1107,5 +1767,5 @@
     {
         _printf("\n[GIET_ERROR] in _sys_tim_start() : not enough TIM channels\n");
-        return -1;
+        return -1111;
     }
 
@@ -1113,5 +1773,12 @@
     _timer_start( channel, period );
 
-    return 0;
+    return GIET_SYSCALL_OK;
+
+#else
+
+    _printf("\n[GIET ERROR] in _sys_tim_start() : NB_TIM_CHANNELS = 0\n");
+    return -1111;
+
+#endif
 }
 
@@ -1119,4 +1786,7 @@
 int _sys_tim_stop()
 {
+
+#if NB_TIM_CHANNELS
+
     // get timer index
     unsigned int channel = _get_context_slot( CTX_TIM_ID );
@@ -1124,5 +1794,5 @@
     {
         _printf("\n[GIET_ERROR] in _sys_tim_stop() : illegal timer index\n");
-        return -1;
+        return -1111;
     }
 
@@ -1130,6 +1800,14 @@
     _timer_stop( channel );
 
-    return 0;
+    return GIET_SYSCALL_OK;
+
+#else
+
+    _printf("\n[GIET ERROR] in _sys_tim_stop() : NB_TIM_CHANNELS = 0\n");
+    return -1111;
+
+#endif
 }
+
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1138,4 +1816,6 @@
 
 #define NIC_CONTAINER_SIZE 4096
+
+#if NB_NIC_CHANNELS
 
 ////////////////////////////////////////
@@ -1144,14 +1824,19 @@
                     unsigned int ymax )
 {
+    mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
+    mapping_vspace_t  *vspace   = _get_vspace_base(header);
+    mapping_thread_t  *thread   = _get_thread_base(header);
+
+    // get calling thread trdid, vspace index, and number of threads
+    unsigned int trdid = _get_thread_trdid();
+    unsigned int vsid  = _get_context_slot( CTX_VSID_ID );
+    unsigned int users = vspace[vsid].threads;
+
     // check xmax / ymax parameters
-    if ( xmax > X_SIZE )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_alloc() xmax argument too large\n");
-        return -1;
-    }
-    if ( ymax > Y_SIZE )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_alloc() ymax argument too large\n");
-        return -1;
+    if ( (xmax > X_SIZE) || (ymax > Y_SIZE) )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_alloc() "
+                "xmax or ymax argument too large for thread %x\n", trdid );
+        return -1111;
     }
 
@@ -1160,51 +1845,95 @@
     ////////////////////////////////////////////////////////
 
-    // get a NIC_RX or NIC_TX channel index 
-    unsigned int nic_channel;
-    unsigned int cma_channel;
-
-    if ( is_rx ) nic_channel = _atomic_increment( &_nic_rx_channel_allocator, 1 );
-    else         nic_channel = _atomic_increment( &_nic_tx_channel_allocator, 1 );
-
+    unsigned int   nic_channel;
+    unsigned int   cma_channel;
+    unsigned int*  palloc;
+
+    // get a NIC_RX or NIC_TX channel 
+    for ( nic_channel = 0 ; nic_channel < NB_NIC_CHANNELS ; nic_channel++ )
+    {
+        if ( is_rx ) palloc = &_nic_rx_channel_alloc[nic_channel];
+        else         palloc = &_nic_tx_channel_alloc[nic_channel];
+
+        if ( _atomic_test_and_set( palloc , users ) == 0 ) break;
+    }
     if ( (nic_channel >= NB_NIC_CHANNELS) )
     {
-        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
-        return -1;
-    }
-
-    // get a CMA channel index
+        _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
+                "no NIC channel available for thread %x\n", trdid );
+        return -1111;
+    }
+
+    // get a CMA channel 
     for ( cma_channel = 0 ; cma_channel < NB_CMA_CHANNELS ; cma_channel++ )
     {
-        if ( !_cma_channel[cma_channel] )
+        palloc = &_cma_channel_alloc[cma_channel];
+
+        if ( _atomic_test_and_set( palloc , users ) == 0 ) break;
+    }
+    if ( cma_channel >= NB_CMA_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
+                "no CMA channel available for thread %x\n", trdid );
+        if ( is_rx )  _nic_rx_channel_alloc[nic_channel] = 0;
+        else          _nic_tx_channel_alloc[nic_channel] = 0;
+        return -1111;
+    }
+
+#if GIET_DEBUG_NIC
+_printf("\n[GIET DEBUG NIC] Thread %d enters sys_nic_alloc() at cycle %d\n"
+        "  nic_channel = %d / cma_channel = %d\n",
+        trdid , _get_proctime() , nic_channel , cma_channel );
+#endif
+
+    // register nic_index and cma_index in all threads
+    // contexts that are in the same vspace
+    unsigned int tid;
+    for (tid = vspace[vsid].thread_offset;
+         tid < (vspace[vsid].thread_offset + vspace[vsid].threads);
+         tid++)
+    {
+        unsigned int y_size        = header->y_size;
+        unsigned int cid           = thread[tid].clusterid;
+        unsigned int x             = cid / y_size;
+        unsigned int y             = cid % y_size;
+        unsigned int p             = thread[tid].proclocid;
+        unsigned int ltid          = thread[tid].ltid;
+        static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];
+
+        if ( is_rx )
         {
-            _cma_channel[cma_channel] = 1;
-            break;
+            if ( (psched->context[ltid].slot[CTX_NIC_RX_ID] < NB_NIC_CHANNELS) ||
+                 (psched->context[ltid].slot[CTX_CMA_RX_ID] < NB_CMA_CHANNELS) )
+            {
+                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
+                        "NIC_RX or CMA_RX channel already allocated for thread %x\n", trdid );
+                _nic_rx_channel_alloc[nic_channel] = 0;
+                _cma_channel_alloc[cma_channel]    = 0;
+                return -1111;
+            }
+            else
+            {
+                psched->context[ltid].slot[CTX_NIC_RX_ID] = nic_channel;
+                psched->context[ltid].slot[CTX_CMA_RX_ID] = cma_channel;
+            }
         }
-    }
-
-    if ( cma_channel >= NB_CMA_CHANNELS )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough CMA channels\n");
-        return -1;
-    }
-
-#if GIET_DEBUG_NIC
-unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
-_printf("\n[GIET DEBUG NIC] Task %d enters sys_nic_alloc() at cycle %d\n"
-        "  nic_channel = %d / cma_channel = %d\n",
-        thread , _get_proctime() , nic_channel , cma_channel );
-#endif
-
-    // register nic_index and cma_index in task context
-    if ( is_rx )
-    {
-        _set_context_slot( CTX_NIC_RX_ID, nic_channel );
-        _set_context_slot( CTX_CMA_RX_ID, cma_channel );
-    }
-    else
-    {
-        _set_context_slot( CTX_NIC_TX_ID, nic_channel );
-        _set_context_slot( CTX_CMA_TX_ID, cma_channel );
-    }
+        else // is_tx
+        {
+            if ( (psched->context[ltid].slot[CTX_NIC_TX_ID] < NB_NIC_CHANNELS) ||
+                 (psched->context[ltid].slot[CTX_CMA_TX_ID] < NB_CMA_CHANNELS) )
+            {
+                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
+                        "NIC_TX or CMA_TX channel already allocated for thread %x\n", trdid );
+                _nic_tx_channel_alloc[nic_channel] = 0;
+                _cma_channel_alloc[cma_channel]    = 0;
+                return -1111;
+            }
+            else
+            {
+                psched->context[ltid].slot[CTX_NIC_TX_ID] = nic_channel;
+                psched->context[ltid].slot[CTX_CMA_TX_ID] = cma_channel;
+            }
+        }
+    }  // end loop on threads
 
     /////////////////////////////////////////////////////////////////////////////////
@@ -1241,7 +1970,7 @@
             if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
             {
-                _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
-                        " in cluster[%d,%d]\n", cx, cy );
-                return -1;
+                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
+                        "not enough kenel heap in cluster[%d,%d]\n", cx, cy );
+                return -1111;
             }
 
@@ -1252,7 +1981,7 @@
             if ( cont_paddr & 0x3F )
             {
-                _printf("\n[GIET ERROR] in _sys_nic_alloc() : container address of cluster[%d,%d] not aligned\n",
-                        cx, cy);
-                return -1;
+                _printf("\n[GIET ERROR] in _sys_nic_alloc() : "
+                        "container address of cluster[%d,%d] not aligned\n", cx, cy);
+                return -1111;
             }
 
@@ -1270,7 +1999,7 @@
             if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
             {
-                _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
-                        " in cluster[%d,%d]\n", cx, cy );
-                return -1;
+                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
+                        "not enough kernel heap in cluster[%d,%d]\n", cx, cy );
+                return -1111;
             }
 
@@ -1281,7 +2010,7 @@
             if ( sts_paddr & 0x3F )
             {
-                _printf("\n[GIET ERROR] in _sys_nic_alloc() : status address of cluster[%d,%d] not aligned\n",
-                        cx, cy);
-                return -1;
+                _printf("\n[GIET ERROR] in _sys_nic_alloc() : "
+                        "status address of cluster[%d,%d] not aligned\n", cx, cy);
+                return -1111;
             }
 
@@ -1385,57 +2114,120 @@
 #endif
 
-    return nic_channel;
+    return GIET_SYSCALL_OK;
 } // end _sys_nic_alloc()
 
 
-////////////////////////////////////////
-// NOTE: not a syscall
-int _sys_nic_release( unsigned int is_rx )
-{
-    if ( is_rx )
-        _atomic_increment( &_nic_rx_channel_allocator , 0xFFFFFFFF );
-    else
-        _atomic_increment( &_nic_tx_channel_allocator , 0xFFFFFFFF );
-
-    return 0;
-}
-
-
-////////////////////////////////////////
-int _sys_nic_start( unsigned int is_rx,
-                    unsigned int channel )
-{
+//////////////////////////////////////////
+int _sys_nic_release( unsigned int is_rx )     // NOTE: not a syscall
+{
+    unsigned int trdid = _get_thread_trdid();
+
     unsigned int nic_channel;
     unsigned int cma_channel;
-
-    // get NIC channel index and CMA channel index from task context
+    
+    // update the kernel tables 
     if ( is_rx )
     {
         nic_channel = _get_context_slot( CTX_NIC_RX_ID );
         cma_channel = _get_context_slot( CTX_CMA_RX_ID );
-    }
+
+        if ( (nic_channel >= NB_NIC_CHANNELS) )
+        {
+            _printf("\n[GIET ERROR] in _sys_nic_release() : "
+                    "NIC_RX channel already released for thread %x\n", trdid );
+            return -1111;
+        }
+        if ( (cma_channel >= NB_CMA_CHANNELS) )
+        {
+            _printf("\n[GIET ERROR] in _sys_nic_release() : "
+                    "CMA_RX channel already released for thread %x\n", trdid );
+            return -1111;
+        }
+
+        // atomically decrement the NIC and CMA channel allocators
+        _atomic_increment( &_nic_rx_channel_alloc[nic_channel] , -1 );
+        _atomic_increment( &_cma_channel_alloc[cma_channel] , -1 );
+    
+        // stop the NIC and CMA peripherals channels if no more users
+        if ( (_nic_rx_channel_alloc[nic_channel] == 0) &&
+             (_cma_channel_alloc[cma_channel] == 0) )  _sys_nic_stop( 1 );
+
+        // reset the calling thread context slots
+        _set_context_slot( CTX_NIC_RX_ID , 0xFFFFFFFF );
+        _set_context_slot( CTX_CMA_RX_ID , 0xFFFFFFFF );
+    }         
     else
     {
         nic_channel = _get_context_slot( CTX_NIC_TX_ID );
         cma_channel = _get_context_slot( CTX_CMA_TX_ID );
+
+        if ( (nic_channel >= NB_NIC_CHANNELS) )
+        {
+            _printf("\n[GIET ERROR] in _sys_nic_release() : "
+                    "NIC_TX channel already released for thread %x\n", trdid );
+            return -1111;
+        }
+        if ( (cma_channel >= NB_CMA_CHANNELS) )
+        {
+            _printf("\n[GIET ERROR] in _sys_nic_release() : "
+                    "CMA_TX channel already released for thread %x\n", trdid );
+            return -1111;
+        }
+
+        // atomically decrement the NIC and CMA channel allocators
+        _atomic_increment( &_nic_tx_channel_alloc[nic_channel] , -1 );
+        _atomic_increment( &_cma_channel_alloc[cma_channel] , -1 );
+    
+        // stop the NIC and CMA peripherals channels if no more users
+        if ( (_nic_tx_channel_alloc[nic_channel] == 0) &&
+             (_cma_channel_alloc[cma_channel] == 0) )  _sys_nic_stop( 0 );
+
+        // reset the calling thread context slots
+        _set_context_slot( CTX_NIC_TX_ID , 0xFFFFFFFF );
+        _set_context_slot( CTX_CMA_TX_ID , 0xFFFFFFFF );
+    }
+
+    return GIET_SYSCALL_OK;
+}  // end sys_nic_release()
+
+
+////////////////////////////////////////
+int _sys_nic_start( unsigned int is_rx )
+{
+    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
+
+    unsigned int nic_channel;
+    unsigned int cma_channel;
+
+    // get NIC channel index and CMA channel index from thread context
+    if ( is_rx )
+    {
+        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
+        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
+    }
+    else
+    {
+        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
+        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
     }
 
 #if GIET_DEBUG_NIC
-unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
-_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start() at cycle %d\n"
+_printf("\n[GIET DEBUG NIC] Thread %x in _sys_nic_start() at cycle %d\n"
         "  get NIC channel = %d / CMA channel = %d\n",
-        thread, _get_proctime(), nic_channel, cma_channel );
+        trdid, _get_proctime(), nic_channel, cma_channel );
 #endif
 
     // check NIC and CMA channels index
-    if ( nic_channel != channel )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal NIC channel\n");
-        return -1;
+    if ( nic_channel >= NB_NIC_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_start() : "
+                "illegal NIC channel for thread %x\n", trdid );
+        return -1111;
     }
     if ( cma_channel >= NB_CMA_CHANNELS )
     {
-        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal CMA channel\n");
-        return -1;
+        _printf("\n[GIET_ERROR] in _sys_nic_start() : "
+                "illegal CMA channel for thread %x\n", trdid );
+        return -1111;
     }
 
@@ -1450,8 +2242,8 @@
 #if GIET_DEBUG_NIC
     _printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
-            thread , _get_proctime() );
-#endif
-
-    return 0;
+            trdid , _get_proctime() );
+#endif
+
+    return GIET_SYSCALL_OK;
 }  // end _sys_nic_start()
 
@@ -1459,19 +2251,25 @@
 //////////////////////////////////////
 int _sys_nic_move( unsigned int is_rx,
-                   unsigned int channel,
                    void*        buffer )
 {
+    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
+
+    unsigned int channel;
 
 #if GIET_DEBUG_NIC
-unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
 _printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_move() at cycle %d\n",
-        thread , _get_proctime() );
-#endif
+        trdid , _get_proctime() );
+#endif
+
+    // get NIC channel index from thread context
+    if ( is_rx )  channel = _get_context_slot( CTX_NIC_RX_ID );
+    else          channel = _get_context_slot( CTX_NIC_TX_ID );
 
     // check NIC channel index
     if ( channel >= NB_NIC_CHANNELS )
     {
-        _printf("\n[GIET_ERROR] in _sys_nic_move() : illegal NIC channel index\n");
-        return -1;
+        _printf("\n[GIET_ERROR] in _sys_nic_move() : "
+                "illegal NIC channel index for thread %x\n", trdid );
+        return -1111;
     }
 
@@ -1485,5 +2283,5 @@
     unsigned int ymax = ker_chbuf->ymax;
 
-    // get cluster coordinates for the processor running the calling task
+    // get cluster coordinates for the processor running the calling thread
     unsigned int  procid = _get_procid();
     unsigned int  cx     = procid >> (Y_WIDTH + P_WIDTH);
@@ -1495,5 +2293,5 @@
         _printf("\n[GIET_ERROR] in _sys_nic_move() : processor X coordinate = %d"
                 " / xmax = %d\n", cx , xmax );
-        return -1;
+        return -1111;
     }
     if ( cy >= ymax )
@@ -1501,5 +2299,5 @@
         _printf("\n[GIET_ERROR] in _sys_nic_move() : processor Y coordinate = %d"
                 " / ymax = %d\n", cy , ymax );
-        return -1;
+        return -1111;
     }
     
@@ -1518,5 +2316,5 @@
     {
         _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal user buffer address\n");
-        return -1;
+        return -1111;
     }
 
@@ -1606,12 +2404,13 @@
 #endif
 
-    return 0;
+    return GIET_SYSCALL_OK;
 } // end _sys_nic_move()
 
 
-////////////////////////////////////////
-int _sys_nic_stop( unsigned int is_rx,
-                   unsigned int channel )
-{
+///////////////////////////////////////
+int _sys_nic_stop( unsigned int is_rx )
+{
+    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
+
     unsigned int nic_channel;
     unsigned int cma_channel;
@@ -1630,38 +2429,49 @@
 
     // check NIC and CMA channels index
-    if ( nic_channel != channel )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal NIC channel\n");
-        return -1;
+    if ( nic_channel >= NB_NIC_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_stop() : " 
+                "illegal NIC channel for thread %x\n", trdid );
+        return -1111;
     }
     if ( cma_channel >= NB_CMA_CHANNELS )
     {
-        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal CMA channel\n");
-        return -1;
-    }
+        _printf("\n[GIET_ERROR] in _sys_nic_stop() : "
+                "illegal CMA channel for thread %x\n", trdid );
+        return -1111;
+    }
+
+    // desactivates the CMA channel
+    _cma_set_register( cma_channel, CHBUF_RUN , 0 );
+
+    // wait until CMA channel IDLE
+    unsigned int volatile status;
+    do
+    {
+         status = _cma_get_register( cma_channel, CHBUF_STATUS );
+    } while ( status ); 
 
     // desactivates the NIC channel
     _nic_channel_stop( nic_channel, is_rx );
 
-    // desactivates the CMA channel
-    _cma_set_register( cma_channel, CHBUF_RUN , 0 );
-
-    return 0;
+    return GIET_SYSCALL_OK;
 }  // end _sys_nic_stop()
 
 ////////////////////////////////////////
-int _sys_nic_clear( unsigned int is_rx,
-                    unsigned int channel )
-{
-    unsigned int nic_channel;
+int _sys_nic_clear( unsigned int is_rx )
+{
+    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
+
+    unsigned int channel;
 
     // get NIC channel 
-    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
-    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
-
-    if ( nic_channel != channel )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_clear(): illegal NIC channel\n");
-        return -1;
+    if ( is_rx )  channel = _get_context_slot( CTX_NIC_RX_ID );
+    else          channel = _get_context_slot( CTX_NIC_TX_ID );
+
+    if ( channel >= NB_NIC_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_clear() : "
+                "illegal NIC channel for thread %x\n", trdid );
+        return -1111;
     }
 
@@ -1688,11 +2498,12 @@
         _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST , 0 );
     }
-    return 0;
+    return GIET_SYSCALL_OK;
 }  // en _sys_nic_clear()
 
 ////////////////////////////////////////
-int _sys_nic_stats( unsigned int is_rx,
-                    unsigned int channel )
-{
+int _sys_nic_stats( unsigned int is_rx )
+{
+    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
+
     unsigned int nic_channel;
 
@@ -1701,8 +2512,9 @@
     else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
 
-    if ( nic_channel != channel )
-    {
-        _printf("\n[GIET_ERROR] in _sys_nic_stats(): illegal NIC channel\n");
-        return -1;
+    if ( nic_channel >= NB_NIC_CHANNELS )
+    {
+        _printf("\n[GIET_ERROR] in _sys_nic_stats() : "
+                "illegal NIC channel for thread %x\n", trdid );
+        return -1111;
     }
 
@@ -1759,6 +2571,8 @@
                 broadcast );
     }
-    return 0;
+    return GIET_SYSCALL_OK;
 }  // end _sys_nic_stats()
+
+#endif
 
 /////////////////////////////////////////////////////////////////////////////////////////
@@ -1774,5 +2588,5 @@
     memcpy( fbf_address, buffer, length);
 
-    return 0;
+    return GIET_SYSCALL_OK;
 }
 
@@ -1785,5 +2599,5 @@
     memcpy( buffer, fbf_address, length);
 
-    return 0;
+    return GIET_SYSCALL_OK;
 }
 
@@ -1791,56 +2605,55 @@
 int _sys_fbf_cma_alloc()
 {
+    unsigned int trdid = _get_thread_trdid();
+
     if ( _get_context_slot( CTX_CMA_FB_ID ) < NB_CMA_CHANNELS )
     {
-        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : CMA channel already allocated\n");
-        return 0;
-    }
-
-    // get a new CMA channel index
+        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : "
+                "CMA channel already allocated for thread %x\n", trdid );
+        return GIET_SYSCALL_OK;
+    }
+
+    // get a CMA channel
     unsigned int channel;
-
     for ( channel = 0 ; channel < NB_CMA_CHANNELS ; channel++ )
     {
-        if ( !_cma_channel[channel] )
-        {
-            _cma_channel[channel] = 1;
-            break;
-        }
-    }
-
+        unsigned int*  palloc = &_cma_channel_alloc[channel];
+        if ( _atomic_test_and_set( palloc , 1 ) == 0 ) break;
+    }
     if ( channel >= NB_CMA_CHANNELS )
     {
         _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : no CMA channel available\n");
-        return -1;
+        return -1111;
     }
     else
     {
         _set_context_slot( CTX_CMA_FB_ID, channel );
-        return 0;
+        return GIET_SYSCALL_OK;
     }
 } // end sys_fbf_cma_alloc()
 
-////////////////////////
-// NOTE: not a syscall
-int _sys_fbf_cma_release()
+//////////////////////////
+int _sys_fbf_cma_release()  // Not a syscall
 {
     unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
+    unsigned int trdid   = _get_thread_trdid();
 
     if ( channel >= NB_CMA_CHANNELS )
     {
-        _printf("\n[GIET_ERROR] in _sys_fbf_cma_release() : CMA channel already released\n");
-        return -1;
-    }
-
-    // stop fb
+        _printf("\n[GIET_ERROR] in _sys_fbf_cma_release() : "
+                "CMA_FB channel already releasedifor thread %x\n", trdid );
+        return -1111;
+    }
+
+    // stop CMA transfer
     _sys_fbf_cma_stop();
 
-    // reset CTX_CMA_FB_ID for task
-    _set_context_slot( CTX_CMA_FB_ID, -1 );
+    // reset CTX_CMA_FB_ID for thread
+    _set_context_slot( CTX_CMA_FB_ID, 0xFFFFFFFF );
 
     // release CMA channel
-    _cma_channel[channel] = 0;
-
-    return 0;
+    _cma_channel_alloc[channel] = 0;
+
+    return GIET_SYSCALL_OK;
 }
 
@@ -1868,5 +2681,5 @@
     {
         _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : CMA channel index too large\n");
-        return -1;
+        return -1111;
     }
 
@@ -1890,5 +2703,5 @@
     {
         _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user buffer not aligned\n");
-        return -1;
+        return -1111;
     }
 
@@ -1898,5 +2711,5 @@
     {
         _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user status not aligned\n");
-        return -1;
+        return -1111;
     }
 
@@ -1917,5 +2730,5 @@
     {
         _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf0 not in user space\n");
-        return -1;
+        return -1111;
     }
 
@@ -1925,5 +2738,5 @@
     {
         _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts0 not in user space\n");
-        return -1;
+        return -1111;
     }
 
@@ -1938,5 +2751,5 @@
     {
         _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf1 not in user space\n");
-        return -1;
+        return -1111;
     }
 
@@ -1946,5 +2759,5 @@
     {
         _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts1 not in user space\n");
-        return -1;
+        return -1111;
     }
 
@@ -1974,10 +2787,10 @@
 #endif
 
-    return 0;
+    return GIET_SYSCALL_OK;
 
 #else
 
     _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : NB_CMA_CHANNELS = 0\n");
-    return -1;
+    return -1111;
 
 #endif  
@@ -1995,5 +2808,5 @@
     {
         _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
-        return -1;
+        return -1111;
     }
 
@@ -2005,5 +2818,5 @@
         _printf("\n[GIET ERROR] in _sys_fbf_cma_start() :\n"
                 "Buffer initialization has not been done\n");
-        return -1;
+        return -1111;
     }
 
@@ -2034,10 +2847,10 @@
     _cma_set_register( channel, CHBUF_RUN      , 1 );
 
-    return 0;
+    return GIET_SYSCALL_OK;
 
 #else
 
     _printf("\n[GIET ERROR] in _sys_fbf_cma_start() : NB_CMA_CHANNELS = 0\n");
-    return -1;
+    return -1111;
 
 #endif
@@ -2058,5 +2871,5 @@
         _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : "
                 "CMA channel index too large\n");
-        return -1;
+        return -1111;
     }
 
@@ -2138,10 +2951,10 @@
     _mmc_sync( fbf_sts_paddr, 4 );
 
-    return 0;
+    return GIET_SYSCALL_OK;
 
 #else
 
     _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : no CMA channel allocated\n");
-    return -1;
+    return -1111;
 
 #endif
@@ -2159,5 +2972,5 @@
     {
         _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : CMA channel index too large\n");
-        return -1;
+        return -1111;
     }
 
@@ -2165,10 +2978,10 @@
     _cma_set_register( channel, CHBUF_RUN, 0 );
 
-    return 0;
+    return GIET_SYSCALL_OK;
 
 #else
 
     _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : no CMA channel allocated\n");
-    return -1;
+    return -1111;
 
 #endif
@@ -2184,5 +2997,5 @@
 {
     _printf("\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
-    return -1;
+    return GIET_SYSCALL_UNDEFINED_SYSTEM_CALL;
 }
 
@@ -2198,64 +3011,5 @@
     *p = gpid & ((1<<P_WIDTH)-1);
 
-    return 0;
-}
-
-//////////////////////////////////
-int _sys_task_exit( char* string ) 
-{
-    unsigned int date       = _get_proctime();
-
-    unsigned int gpid       = _get_procid();
-    unsigned int cluster_xy = gpid >> P_WIDTH;
-    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
-    unsigned int x          = cluster_xy >> Y_WIDTH;
-    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
-
-    unsigned int ltid       = _get_context_slot(CTX_LTID_ID);
-
-    // print exit message
-    _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d"
-            "\n       Cause : %s\n\n",
-            ltid, x, y, p, date, string );
-
-    // set NORUN_MASK_TASK bit (non runnable state)
-    static_scheduler_t*  psched  = (static_scheduler_t*)_schedulers[x][y][p];
-    unsigned int*        ptr     = &psched->context[ltid][CTX_NORUN_ID];
-    _atomic_or( ptr , NORUN_MASK_TASK );
-
-    // deschedule
-    _sys_context_switch();
-
-    return 0;
-} 
-
-/////////////////////////
-int _sys_context_switch() 
-{
-    unsigned int save_sr;
-
-    _it_disable( &save_sr );
-    _ctx_switch();
-    _it_restore( &save_sr );
-
-    return 0;
-}
-
-////////////////////////
-int _sys_local_task_id()
-{
-    return _get_context_slot(CTX_LTID_ID);
-}
-
-/////////////////////////
-int _sys_global_task_id()
-{
-    return _get_context_slot(CTX_GTID_ID);
-}
-
-////////////////////
-int _sys_thread_id()
-{
-    return _get_context_slot(CTX_TRDID_ID);
+    return GIET_SYSCALL_OK;
 }
 
@@ -2312,5 +3066,5 @@
         *nprocs = 0;
     }
-    return 0;
+    return GIET_SYSCALL_OK;
 }
 
@@ -2340,10 +3094,10 @@
                 {
                     *vbase = vseg[vseg_id].vbase;
-                    return 0;
+                    return GIET_SYSCALL_OK;
                 }
             } 
         }
     } 
-    return -1;    // not found 
+    return GIET_SYSCALL_VSEG_NOT_FOUND;
 }
 
@@ -2373,10 +3127,10 @@
                 {
                     *length = vseg[vseg_id].length;
-                    return 0;
+                    return GIET_SYSCALL_OK;
                 }
             } 
         }
     } 
-    return -1;    // not found 
+    return GIET_SYSCALL_VSEG_NOT_FOUND;
 }
 
@@ -2392,5 +3146,5 @@
     *y = (paddr>>32) & 0xF;
 
-    return 0;
+    return GIET_SYSCALL_OK;
 }
 
@@ -2401,35 +3155,36 @@
                     unsigned int  y ) 
 {
+    // checking parameters
+    if ( (x >= X_SIZE) || (y >= Y_SIZE) )  
+    {
+        *vaddr  = 0;
+        *length = 0;
+        _printf("\n[GIET ERROR] in _sys_heap_info() : "
+                "illegal (%d,%d) coordinates\n", x , y );
+        return GIET_SYSCALL_ILLEGAL_CLUSTER_COORDINATES;
+    }
+
     mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
-    mapping_task_t *   task    = _get_task_base(header);
+    mapping_thread_t * thread  = _get_thread_base(header);
     mapping_vseg_t *   vseg    = _get_vseg_base(header);
     mapping_vspace_t * vspace  = _get_vspace_base(header);
 
-    unsigned int task_id;
+    unsigned int thread_id;
     unsigned int vspace_id;
     unsigned int vseg_id = 0xFFFFFFFF;
 
-    // searching the heap vseg
-    if ( (x < X_SIZE) && (y < Y_SIZE) )  // searching a task in cluster(x,y)
-    {
-        // get vspace global index
-        vspace_id = _get_context_slot(CTX_VSID_ID);
-
-        // scan all tasks in vspace
-        unsigned int min = vspace[vspace_id].task_offset ;
-        unsigned int max = min + vspace[vspace_id].tasks ;
-        for ( task_id = min ; task_id < max ; task_id++ )
+    // get calling thread vspace index
+    vspace_id = _get_context_slot(CTX_VSID_ID);
+
+    // scan all threads in vspace to find one in clyster[x,y]
+    unsigned int min = vspace[vspace_id].thread_offset ;
+    unsigned int max = min + vspace[vspace_id].threads ;
+    for ( thread_id = min ; thread_id < max ; thread_id++ )
+    {
+        if ( thread[thread_id].clusterid == (x * Y_SIZE + y) )
         {
-            if ( task[task_id].clusterid == (x * Y_SIZE + y) )
-            {
-                vseg_id = task[task_id].heap_vseg_id;
-                if ( vseg_id != 0xFFFFFFFF ) break;
-            }
+            vseg_id = thread[thread_id].heap_vseg_id;
+            break;
         }
-    }
-    else                                // searching in the calling task 
-    {
-        task_id = _get_context_slot(CTX_GTID_ID);
-        vseg_id = task[task_id].heap_vseg_id;
     }
 
@@ -2439,5 +3194,4 @@
         *vaddr  = vseg[vseg_id].vbase;
         *length = vseg[vseg_id].length;
-        return 0;
     }
     else 
@@ -2445,57 +3199,8 @@
         *vaddr  = 0;
         *length = 0;
-        return -1;
-    }
+        _printf("error in _sys_heap_info() : no heap in cluster (%d,%d)\n", x , y );
+    }
+    return GIET_SYSCALL_OK;
 }  // end _sys_heap_info()
-
-
-///////////////////////
-int _sys_tasks_status()
-{
-    mapping_header_t *  header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
-    mapping_task_t *    task    = _get_task_base(header);
-    mapping_vspace_t *  vspace  = _get_vspace_base(header);
-    mapping_cluster_t * cluster = _get_cluster_base(header);
-
-    unsigned int task_id;
-    unsigned int vspace_id;
-
-    // scan all vspaces
-    for( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
-    {
-        _printf("\n*** vspace %s\n", vspace[vspace_id].name );
-
-        // scan all tasks in vspace
-        unsigned int min = vspace[vspace_id].task_offset ;
-        unsigned int max = min + vspace[vspace_id].tasks ;
-        for ( task_id = min ; task_id < max ; task_id++ )
-        {
-            unsigned int         clusterid = task[task_id].clusterid;
-            unsigned int         p         = task[task_id].proclocid;
-            unsigned int         x         = cluster[clusterid].x;
-            unsigned int         y         = cluster[clusterid].y;
-            unsigned int         ltid      = task[task_id].ltid;
-            static_scheduler_t*  psched    = (static_scheduler_t*)_schedulers[x][y][p];
-            unsigned int         norun     = psched->context[ltid][CTX_NORUN_ID];
-            unsigned int         current   = psched->current;
-
-            if ( current == ltid )
-            _printf(" - task %s on P[%d,%d,%d] : running\n", task[task_id].name, x, y, p );
-            else if ( norun == 0 )
-            _printf(" - task %s on P[%d,%d,%d] : runable\n", task[task_id].name, x, y, p );
-            else
-            _printf(" - task %s on P[%d,%d,%d] : blocked\n", task[task_id].name, x, y, p );
-        }
-    }
-    return 0;
-}  // end _sys_tasks_status()
-
-int _sys_fat_read( unsigned int fd_id,
-                   unsigned int buffer,
-                   unsigned int count )
-{
-    return _fat_read(fd_id, buffer, count, 0);
-}
-
 
 
