Index: soft/giet_vm/giet_kernel/ctx_handler.c
===================================================================
--- soft/giet_vm/giet_kernel/ctx_handler.c	(revision 707)
+++ soft/giet_vm/giet_kernel/ctx_handler.c	(revision 709)
@@ -9,8 +9,10 @@
 #include <sys_handler.h>
 #include <giet_config.h>
+#include <fat32.h>
 #include <hard_config.h>
 #include <utils.h>
 #include <tty0.h>
 #include <xcu_driver.h>
+#include <bdv_driver.h>
 
 /////////////////////////////////////////////////////////////////////////////////
@@ -19,170 +21,84 @@
 
 // defined in giet_kernel/switch.s file
-extern void _task_switch(unsigned int *, unsigned int *);
+extern void _thread_switch( thread_context_t* , thread_context_t* );
 
 // allocated in boot.c or kernel_init.c files
 extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
 
-
-///////////////////////////////////////////////
-static void _ctx_kill_task( unsigned int ltid )
+// allocated in kernel_init.c file
+extern fat_desc_t  _fat;
+
+//////////////////////////////////////////////////////////////////
+// This function is called by the _ctx_switch() function.
+// It desactivates a thread that received a KILL signal.
+// We must release all ressources allocated to the thread
+// before the actual desactivation, that uses NORUN_MASK_THREAD.
+//////////////////////////////////////////////////////////////////
+static void _ctx_kill_thread( unsigned int x,
+                              unsigned int y,
+                              unsigned int p,
+                              unsigned int ltid )
 {
     // get scheduler address
-    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
-
-    // pretend the task to kill is scheduled (required for sys_handler calls)
-    unsigned int cur_task = psched->current;
+    static_scheduler_t* psched = _schedulers[x][y][p];
+
+    // pretend the thread to kill is the currently scheduled thread
+    // (required by the _sys_***_release() calls)
+    unsigned int cur_thread = psched->current;
     psched->current = ltid;
 
+    // release BDV lock if taken and reset BDV peripheral
+    if ( psched->context[ltid].slot[CTX_LOCKS_ID] & LOCKS_MASK_BDV ) 
+    {
+        _bdv_set_register( BLOCK_DEVICE_STATUS , 0 );
+        _spin_lock_release( &_bdv_lock );
+    }
+
+    // release FAT lock if taken 
+    if ( psched->context[ltid].slot[CTX_LOCKS_ID] & LOCKS_MASK_FAT ) 
+    {
+        _spin_lock_release( &_fat.fat_lock );
+    }
+
     // release private TTY terminal if required
-    if ( psched->context[ltid][CTX_TTY_ID] < NB_TTY_CHANNELS )
-    {
-        _sys_tty_release();
-        psched->context[ltid][CTX_TTY_ID] = -1;
-    }
+    if ( psched->context[ltid].slot[CTX_TTY_ID] < NB_TTY_CHANNELS ) 
+        _sys_tty_release(); 
 
     // release private TIM channel if required
-    if ( psched->context[ltid][CTX_TIM_ID] < NB_TIM_CHANNELS )
+
+    if ( psched->context[ltid].slot[CTX_TIM_ID] < NB_TIM_CHANNELS )
     {
         _sys_tim_release();
-        psched->context[ltid][CTX_TIM_ID] = -1;
-    }
-
-    // release private NIC_RX channel if required
-    if ( psched->context[ltid][CTX_NIC_RX_ID] < NB_NIC_CHANNELS )
+    }
+
+    // release private NIC_RX and CMA_RX channels if required
+    if ( psched->context[ltid].slot[CTX_NIC_RX_ID] < NB_NIC_CHANNELS )
     {
         _sys_nic_release( 1 );
-        psched->context[ltid][CTX_NIC_RX_ID] = -1;
-    }
-
-    // release private NIC_TX channel if required
-    if ( psched->context[ltid][CTX_NIC_TX_ID] < NB_NIC_CHANNELS )
+    }
+
+    // release private NIC_TX and CMA_TX channels if required
+    if ( psched->context[ltid].slot[CTX_NIC_TX_ID] < NB_NIC_CHANNELS )
     {
         _sys_nic_release( 0 );
-        psched->context[ltid][CTX_NIC_TX_ID] = -1;
     }
 
     // release private FBF_CMA channel if required
-    if ( psched->context[ltid][CTX_CMA_FB_ID] < NB_CMA_CHANNELS )
+    if ( psched->context[ltid].slot[CTX_CMA_FB_ID] < NB_CMA_CHANNELS )
     {
         _sys_fbf_cma_release();
-        psched->context[ltid][CTX_CMA_FB_ID] = -1;
-    }
-
-    // restore scheduled task
-    psched->current = cur_task;
-
-    // set NORUN_MASK_TASK bit
-    _atomic_or( &psched->context[ltid][CTX_NORUN_ID], NORUN_MASK_TASK );
-
-} // end _ctx_kill_task()
-
-
-//////////////////////////////////
-void _ctx_display( unsigned int x,
-                   unsigned int y,
-                   unsigned int p,
-                   unsigned int ltid,
-                   char*        string )
-{
-    static_scheduler_t* psched = _schedulers[x][y][p];
-    _printf("\n########## task[%d,%d,%d,%d] context\n"
-            " - CTX_EPC   = %x\n"
-            " - CTX_PTAB  = %x\n"
-            " - CTX_PTPR  = %x\n"
-            " - CTX_VSID  = %x\n"
-            " - CTX_SR    = %x\n"
-            " - CTX_RA    = %x\n"
-            " - CTX_SP    = %x\n"
-            " - CTX_NORUN = %x\n"
-            " - CTX_SIG   = %x\n"
-            "########## %s\n",
-            x , y , p , ltid ,
-            psched->context[ltid][CTX_EPC_ID], 
-            psched->context[ltid][CTX_PTAB_ID], 
-            psched->context[ltid][CTX_PTPR_ID], 
-            psched->context[ltid][CTX_VSID_ID], 
-            psched->context[ltid][CTX_SR_ID], 
-            psched->context[ltid][CTX_RA_ID], 
-            psched->context[ltid][CTX_SP_ID], 
-            psched->context[ltid][CTX_NORUN_ID],
-            psched->context[ltid][CTX_SIG_ID],
-            string );
-}  // _ctx_display()
+    }
+
+    // restore scheduled thread index
+    psched->current = cur_thread;
+
+    // set NORUN_MASK_THREAD bit to desactivate the target thread 
+    psched->context[ltid].slot[CTX_NORUN_ID] = NORUN_MASK_THREAD;
+
+} // end _ctx_kill_thread()
 
 
 //////////////////
 void _ctx_switch() 
-{
-    unsigned int gpid       = _get_procid();
-    unsigned int cluster_xy = gpid >> P_WIDTH;
-    unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
-
-    // get scheduler address
-    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
-
-    // get number of tasks allocated to scheduler
-    unsigned int tasks = psched->tasks;
-
-    // get current task index
-    unsigned int curr_task_id = psched->current;
-
-    // select the next task using a round-robin policy
-    unsigned int next_task_id;
-    unsigned int tid;
-    unsigned int found = 0;
-
-    for (tid = curr_task_id + 1; tid < curr_task_id + 1 + tasks; tid++) 
-    {
-        next_task_id = tid % tasks;
-
-        // this task needs to be killed
-        if ( psched->context[next_task_id][CTX_SIG_ID] & SIG_MASK_KILL )
-        {
-            // acknowledge signal
-            _atomic_and( &psched->context[next_task_id][CTX_SIG_ID], ~SIG_MASK_KILL );
-
-            _ctx_kill_task( next_task_id );
-        }
-
-        // test if the task is runable
-        if ( psched->context[next_task_id][CTX_NORUN_ID] == 0 ) 
-        {
-            found = 1;
-            // TODO: don't break to process all pending signals.
-            break;
-        }
-    }
-
-    // launch "idle" task if no runable task
-    if (found == 0) next_task_id = IDLE_TASK_INDEX;
-
-#if ( GIET_DEBUG_SWITCH & 0x1 )
-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] (%d) -> (%d) on processor[%d,%d,%d] at cycle %d\n",
-        curr_task_id, next_task_id, x, y , lpid, _get_proctime() );
-#endif
-
-    if (curr_task_id != next_task_id)  // actual task switch required
-    {
-        unsigned int* curr_ctx_vaddr = &(psched->context[curr_task_id][0]);
-        unsigned int* next_ctx_vaddr = &(psched->context[next_task_id][0]);
-
-        // reset TICK timer counter. 
-        _xcu_timer_reset_cpt( cluster_xy, lpid );
-
-        // set current task index 
-        psched->current = next_task_id;
-
-        // makes context switch
-        _task_switch( curr_ctx_vaddr , next_ctx_vaddr );
-    }
-} //end _ctx_switch()
-
-
-/////////////////
-void _idle_task() 
 {
     unsigned int gpid       = _get_procid();
@@ -192,15 +108,92 @@
     unsigned int p          = gpid & ((1<<P_WIDTH)-1);
 
+    unsigned int ltid;     // index for loops on threads in scheduler
+
+    // get calling thread scheduler address
+    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
+
+    // get number of threads allocated to scheduler
+    unsigned int threads = psched->threads;
+
+    // get current thread ltid
+    unsigned int curr_thread_id = psched->current;
+
+    // first loop on threads: handle all pending KILL signals
+    for ( ltid = 0 ; ltid < threads ; ltid++ )
+    {
+        if ( psched->context[ltid].slot[CTX_SIGS_ID] & SIGS_MASK_KILL )
+        {
+            // acknowledge KILL signal
+            _atomic_and( &psched->context[ltid].slot[CTX_SIGS_ID], ~SIGS_MASK_KILL );
+
+            // desactivate the killed thread
+            _ctx_kill_thread( x , y , p , ltid );
+        }
+    }
+
+    // second loop: select next thread using a round-robin policy
+    unsigned int next_thread_id;
+    unsigned int found = 0;
+    for ( ltid = curr_thread_id + 1 ; ltid < (curr_thread_id + 1 + threads) ; ltid++ ) 
+    {
+        next_thread_id = ltid % threads;
+
+        // test if the thread is runable
+        if ( psched->context[next_thread_id].slot[CTX_NORUN_ID] == 0 )
+        {
+            found = 1;
+            break;
+        }
+    }
+
+    // launch idle_thread if no runable thread
+    if ( found == 0 ) next_thread_id = IDLE_THREAD_INDEX;
+
+    if ( curr_thread_id != next_thread_id )  // actual thread switch required
+    {
+
+#if GIET_DEBUG_SWITCH 
+unsigned int x = cluster_xy >> Y_WIDTH;
+unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
+if ( (_get_proctime() > GIET_DEBUG_SWITCH) && (x == 0) && (y == 0) && (p == 0) )
+_printf("\n[DEBUG SWITCH] (%d) -> (%d) on processor[%d,%d,%d] at cycle %d\n",
+        curr_thread_id, next_thread_id, x, y , p, _get_proctime() );
+#endif
+
+        thread_context_t* curr_ctx_vaddr = &(psched->context[curr_thread_id]);
+        thread_context_t* next_ctx_vaddr = &(psched->context[next_thread_id]);
+
+        // reset TICK timer counter. 
+        _xcu_timer_reset_cpt( cluster_xy, p );
+
+        // set current thread index 
+        psched->current = next_thread_id;
+
+        // makes context switch
+        _thread_switch( curr_ctx_vaddr , next_ctx_vaddr );
+    }
+} //end _ctx_switch()
+
+
+///////////////////
+void _idle_thread() 
+{
+    unsigned int gpid       = _get_procid();
+    unsigned int cluster_xy = gpid >> P_WIDTH;
+    unsigned int x          = cluster_xy >> Y_WIDTH;
+    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
+    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
+
     while(1)
     {
         // initialize counter
-        unsigned int count = GIET_IDLE_TASK_PERIOD;
+        unsigned int count = GIET_IDLE_THREAD_PERIOD;
 
         // decounting loop
         asm volatile(
                 "move   $3,   %0              \n"
-                "_idle_task_loop:             \n"
+                "_idle_thread_loop:             \n"
                 "addi   $3,   $3,   -1        \n"
-                "bnez   $3,   _idle_task_loop \n"
+                "bnez   $3,   _idle_thread_loop \n"
                 "nop                          \n"
                 :
