Index: trunk/kernel/kern/thread.c
===================================================================
--- trunk/kernel/kern/thread.c	(revision 433)
+++ trunk/kernel/kern/thread.c	(revision 436)
@@ -799,10 +799,14 @@
 }  // end thread_check_sched()
 
-/////////////////////////////////////
-void thread_block( thread_t * thread,
-                   uint32_t   cause )
-{
+//////////////////////////////////////
+void thread_block( xptr_t   thread_xp,
+                   uint32_t cause )
+{
+    // get thread cluster and local pointer
+    cxy_t      cxy = GET_CXY( thread_xp );
+    thread_t * ptr = GET_PTR( thread_xp );
+
     // set blocking cause
-    hal_atomic_or( &thread->blocked , cause );
+    hal_remote_atomic_or( XPTR( cxy , &ptr->blocked ) , cause );
     hal_fence();
 
@@ -810,6 +814,11 @@
 uint32_t cycle = (uint32_t)hal_get_cycles();
 if( CONFIG_DEBUG_THREAD_BLOCK < cycle )
-printk("\n[DBG] %s : thread %x blocked thread %x / cause %x / state %x / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , thread , cause , thread->blocked , cycle );
+printk("\n[DBG] %s : thread %x blocked thread %x / cause %x / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD , ptr , cause , cycle );
+#endif
+
+#if (CONFIG_DEBUG_THREAD_BLOCK & 1)
+if( CONFIG_DEBUG_THREAD_BLOCK < cycle )
+sched_display( ptr->core->lid );
 #endif
 
@@ -831,6 +840,11 @@
 uint32_t cycle = (uint32_t)hal_get_cycles();
 if( CONFIG_DEBUG_THREAD_BLOCK < cycle )
-printk("\n[DBG] %s : thread %x unblocked thread %x / cause %x / state %x / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , ptr , cause , ptr->blocked , cycle );
+printk("\n[DBG] %s : thread %x unblocked thread %x / cause %x / cycle %d\n",
+__FUNCTION__ , CURRENT_THREAD , ptr , cause , cycle );
+#endif
+
+#if (CONFIG_DEBUG_THREAD_BLOCK & 1)
+if( CONFIG_DEBUG_THREAD_BLOCK < cycle )
+sched_display( ptr->core->lid );
 #endif
 
@@ -840,10 +854,39 @@
 }  // end thread_unblock()
 
-/////////////////////////////////////
-void thread_kill( thread_t * target )
-{
-    volatile uint32_t  rsp_count = 1;     // responses counter
-
-    thread_t * killer = CURRENT_THREAD;
+////////////////////////////////////
+void thread_kill( xptr_t  target_xp,
+                  bool_t  is_exit,
+                  bool_t  is_forced )
+{
+    reg_t       save_sr;                // for critical section
+    bool_t      attached;               // target thread in attached mode
+    bool_t      join_done;              // joining thread arrived first
+    xptr_t      killer_xp;              // extended pointer on killer thread (this)
+    thread_t  * killer_ptr;             // pointer on killer thread (this)
+    cxy_t       target_cxy;             // target thread cluster     
+    thread_t  * target_ptr;             // pointer on target thread
+    xptr_t      joining_xp;             // extended pointer on joining thread
+    thread_t  * joining_ptr;            // pointer on joining thread
+    cxy_t       joining_cxy;            // joining thread cluster
+    pid_t       target_pid;             // target process PID
+    cxy_t       owner_cxy;              // target process owner cluster
+    trdid_t     target_trdid;           // target thread identifier
+    ltid_t      target_ltid;            // target thread local index
+    xptr_t      process_state_xp;       // extended pointer on <term_state> in process
+
+    xptr_t      target_flags_xp;        // extended pointer on target thread <flags>
+    xptr_t      target_join_lock_xp;    // extended pointer on target thread <join_lock>
+    xptr_t      target_join_xp_xp;      // extended pointer on target thread <join_xp>
+    xptr_t      target_process_xp;      // extended pointer on target thread <process>
+
+    process_t * target_process;         // pointer on target thread process
+
+    // get target thread cluster and pointer
+    target_cxy = GET_CXY( target_xp );
+    target_ptr = GET_PTR( target_xp );
+
+    // get killer thread pointers
+    killer_ptr = CURRENT_THREAD;
+    killer_xp  = XPTR( local_cxy , killer_ptr );
 
 #if CONFIG_DEBUG_THREAD_KILL
@@ -851,40 +894,120 @@
 if( CONFIG_DEBUG_THREAD_KILL < cycle )
 printk("\n[DBG] %s : thread %x enter for target thread %x / cycle %d\n",
-__FUNCTION__, killer, target, cycle );
-#endif
-
-    // set the global blocked bit in target thread descriptor.
-    thread_block( target , THREAD_BLOCKED_GLOBAL );
-
-    // request target scheduler to deschedule the target thread
-    // when killer thread is not running on same core as target thread
-    if( killer->core->lid != target->core->lid )
-    {
-        // set signal in target thread descriptor and in target scheduler
-        thread_set_req_ack( target , (void *)(&rsp_count) );
-
-        // send an IPI to the target thread core.
-        dev_pic_send_ipi( local_cxy , target->core->lid );
-
-        // poll the response
-        while( 1 )
+__FUNCTION__, killer_ptr, target_ptr, cycle );
+#endif
+
+    // block the target thread 
+    thread_block( target_xp , THREAD_BLOCKED_GLOBAL );
+
+    // get target thread attached mode
+    target_flags_xp = XPTR( target_cxy , &target_ptr->flags );
+    attached = ((hal_remote_lw( target_flags_xp ) & THREAD_FLAG_DETACHED) == 0);
+
+    // synchronize with the joining thread 
+    // if the target thread is attached && not forced
+
+    if( attached  && (is_forced == false) )
+    {
+        // build extended pointers on target thread join fields
+        target_join_lock_xp  = XPTR( target_cxy , &target_ptr->join_lock );
+        target_join_xp_xp    = XPTR( target_cxy , &target_ptr->join_xp );
+
+        // enter critical section
+        hal_disable_irq( &save_sr );
+
+        // take the join_lock in target thread descriptor
+        remote_spinlock_lock( target_join_lock_xp );
+
+        // get join_done from target thread descriptor
+        join_done = ((hal_remote_lw( target_flags_xp ) & THREAD_FLAG_JOIN_DONE) != 0);
+    
+        if( join_done )     // joining thread arrived first
         {
-            // exit when response received from scheduler
-            if( rsp_count == 0 )  break;
-
-            // deschedule without blocking
-            hal_fixed_delay( 1000 );
+            // get extended pointer on joining thread
+            joining_xp  = (xptr_t)hal_remote_lwd( target_join_xp_xp );
+            joining_ptr = GET_PTR( joining_xp );
+            joining_cxy = GET_CXY( joining_xp );
+            
+            // reset the join_done flag in target thread
+            hal_remote_atomic_and( target_flags_xp , ~THREAD_FLAG_JOIN_DONE );
+
+            // unblock the joining thread
+            thread_unblock( joining_xp , THREAD_BLOCKED_JOIN );
+
+            // release the join_lock in target thread descriptor
+            remote_spinlock_unlock( target_join_lock_xp );
+
+            // restore IRQs
+            hal_restore_irq( save_sr );
         }
-    }
-
-	// set REQ_DELETE flag
-	hal_atomic_or( &target->flags , THREAD_FLAG_REQ_DELETE );
+        else                // this thread arrived first
+        {
+            // set the kill_done flag in target thread
+            hal_remote_atomic_or( target_flags_xp , THREAD_FLAG_KILL_DONE );
+
+            // block this thread on BLOCKED_JOIN
+            thread_block( killer_xp , THREAD_BLOCKED_JOIN );
+
+            // set extended pointer on killer thread in target thread
+            hal_remote_swd( target_join_xp_xp , killer_xp );
+
+            // release the join_lock in target thread descriptor
+            remote_spinlock_unlock( target_join_lock_xp );
+
+            // deschedule
+            sched_yield( "killer thread wait joining thread" );
+
+            // restore IRQs
+            hal_restore_irq( save_sr );
+        }
+    }  // end if attached
+
+    // - if the target thread is the main thread
+    //   => synchronize with the parent process main thread
+    // - if the target thread is not the main thread
+    //   => simply mark the target thread for delete
+
+    // get pointer on target thread process
+    target_process_xp  = XPTR( target_cxy , &target_ptr->process );
+    target_process     = (process_t *)hal_remote_lpt( target_process_xp ); 
+
+	// get target process owner cluster
+	target_pid = hal_remote_lw( XPTR( target_cxy , &target_process->pid ) );
+    owner_cxy = CXY_FROM_PID( target_pid );
+
+    // get target thread local index
+    target_trdid = hal_remote_lw( XPTR( target_cxy , &target_ptr->trdid ) );
+    target_ltid  = LTID_FROM_TRDID( target_trdid );
+
+    if( (owner_cxy == target_cxy) && (target_ltid == 0) )     // main thread
+    {
+        // get extended pointer on term_state in target process owner cluster
+        process_state_xp = XPTR( owner_cxy , &target_process->term_state );
+
+        // set termination info in target process owner  
+        if( is_exit ) hal_remote_atomic_or( process_state_xp , PROCESS_TERM_EXIT );
+        else          hal_remote_atomic_or( process_state_xp , PROCESS_TERM_KILL );
 
 #if CONFIG_DEBUG_THREAD_KILL
 cycle  = (uint32_t)hal_get_cycles;
 if( CONFIG_DEBUG_THREAD_KILL < cycle )
-printk("\n[DBG] %s : thread %x exit for target thread %x / cycle %d\n",
-__FUNCTION__, killer, target, cycle );
-#endif
+printk("\n[DBG] %s : thread %x exit for thread %x / main thread / cycle %d\n",
+__FUNCTION__, killer_ptr, target_ptr, cycle );
+#endif
+
+    }
+    else                                                      // main thread
+    {
+        // set the REQ_DELETE flag in target thread descriptor
+        hal_remote_atomic_or( target_flags_xp , THREAD_FLAG_REQ_DELETE );
+
+#if CONFIG_DEBUG_THREAD_KILL
+cycle  = (uint32_t)hal_get_cycles;
+if( CONFIG_DEBUG_THREAD_KILL < cycle )
+printk("\n[DBG] %s : thread %x exit for thread %x / not the main thread / cycle %d\n",
+__FUNCTION__, killer_ptr, target_ptr, cycle );
+#endif
+
+    }
 
 }  // end thread_kill()
@@ -958,4 +1081,8 @@
     target_thread_ltid = LTID_FROM_TRDID( trdid );
 
+    // check trdid argument
+	if( (target_thread_ltid >= CONFIG_THREAD_MAX_PER_CLUSTER) || 
+        cluster_is_undefined( target_cxy ) )         return XPTR_NULL;
+
     // get root of list of process descriptors in target cluster
     hal_remote_memcpy( XPTR( local_cxy  , &root ),
@@ -987,9 +1114,6 @@
     remote_spinlock_unlock( lock_xp );
 
-    // check target thread found
-    if( found == false )
-    {
-        return XPTR_NULL;
-    }
+    // check PID found
+    if( found == false ) return XPTR_NULL;
 
     // get target thread local pointer
@@ -997,8 +1121,5 @@
     target_thread_ptr = (thread_t *)hal_remote_lpt( xp );
 
-    if( target_thread_ptr == NULL )
-    {
-        return XPTR_NULL;
-    }
+    if( target_thread_ptr == NULL )  return XPTR_NULL;
 
     return XPTR( target_cxy , target_thread_ptr );
