Index: trunk/kernel/kern/thread.c
===================================================================
--- trunk/kernel/kern/thread.c	(revision 408)
+++ trunk/kernel/kern/thread.c	(revision 409)
@@ -112,5 +112,5 @@
 /////////////////////////////////////////////////////////////////////////////////////
 // This static function initializes a thread descriptor (kernel or user).
-// It can be called by the four functions:
+// It can be called by the three functions:
 // - thread_user_create()
 // - thread_user_fork()
@@ -164,8 +164,10 @@
 
     thread->local_locks     = 0;
-    list_root_init( &thread->locks_root );
-
     thread->remote_locks    = 0;
+
+#if CONFIG_LOCKS_DEBUG 
+    list_root_init( &thread->locks_root );  
     xlist_root_init( XPTR( local_cxy , &thread->xlocks_root ) );
+#endif
 
     thread->u_stack_base    = u_stack_base;
@@ -177,11 +179,8 @@
     thread->entry_args      = args;         // thread function arguments
     thread->flags           = 0;            // all flags reset
-    thread->signals         = 0;            // no pending signal
     thread->errno           = 0;            // no error detected
     thread->fork_user       = 0;            // no user defined placement for fork
     thread->fork_cxy        = 0;            // user defined target cluster for fork
-
-    // thread blocked
-    thread->blocked = THREAD_BLOCKED_GLOBAL;
+    thread->blocked         = THREAD_BLOCKED_GLOBAL;
 
     // reset children list
@@ -195,4 +194,7 @@
     // reset thread info
     memset( &thread->info , 0 , sizeof(thread_info_t) );
+
+    // initializes join_lock
+    remote_spinlock_init( XPTR( local_cxy , &thread->join_lock ) );
 
     // initialise signature
@@ -296,7 +298,4 @@
         return EINVAL;
     }
-
-    // set LOADABLE flag
-    thread->flags = THREAD_FLAG_LOADABLE;
 
     // set DETACHED flag if required
@@ -593,5 +592,5 @@
 	uint32_t     tm_start;
 	uint32_t     tm_end;
-    reg_t        state;
+    reg_t        save_sr;
 
     process_t  * process    = thread->process;
@@ -614,9 +613,9 @@
     // release memory allocated for CPU context and FPU context
 	hal_cpu_context_destroy( thread );
-	hal_fpu_context_destroy( thread );
+	if ( thread->type == THREAD_USER ) hal_fpu_context_destroy( thread );
 	
     // release FPU if required
     // TODO This should be done before calling thread_destroy()
-	hal_disable_irq( &state );
+	hal_disable_irq( &save_sr );
 	if( core->fpu_owner == thread )
 	{
@@ -624,5 +623,5 @@
 		hal_fpu_disable();
 	}
-	hal_restore_irq( state );
+	hal_restore_irq( save_sr );
 
     // remove thread from process th_tbl[]
@@ -668,5 +667,6 @@
     xlist_add_first( root , entry );
     hal_remote_atomic_add( XPTR( parent_cxy , &parent_ptr->children_nr ) , 1 );
-}
+
+}  // end thread_child_parent_link()
 
 ///////////////////////////////////////////////////
@@ -693,21 +693,67 @@
     // release the lock
     remote_spinlock_unlock( lock );
-}
+
+}  // thread_child_parent_unlink()
 
 /////////////////////////////////////////////////
 inline void thread_set_signal( thread_t * thread,
-                               uint32_t   mask )
-{
-    hal_atomic_or( &thread->signals , mask );
+                               uint32_t * sig_rsp_count )
+{
+    reg_t    save_sr;   // for critical section
+
+    // get pointer on thread thread scheduler
+    scheduler_t * thread_sched = &thread->core->scheduler;
+
+    // wait scheduler ready to handle a new signal
+    while( thread_sched->sig_pending ) asm volatile( "nop" );
+    
+    // enter critical section
+    hal_disable_irq( &save_sr );
+      
+    // set signal in thread scheduler
+    thread_sched->sig_pending = true;
+
+    // set signal in thread thread "flags"
+    hal_atomic_or( &thread->flags , THREAD_FLAG_SIGNAL );
+
+    // set pointer on responses counter in thread thread
+    thread->sig_rsp_count = sig_rsp_count;
+    
+    // exit critical section
+    hal_restore_irq( save_sr );
+
     hal_fence();
-}
-
-///////////////////////////////////////////////////
-inline void thread_reset_signal( thread_t * thread,
-                                 uint32_t   mask )
-{
-    hal_atomic_and( &thread->signals , ~mask );
+
+}  // thread_set_signal()
+
+////////////////////////////////////////////////////
+inline void thread_reset_signal( thread_t * thread )
+{
+    reg_t    save_sr;   // for critical section
+
+    // get pointer on target thread scheduler
+    scheduler_t * sched = &thread->core->scheduler;
+
+    // check signal pending in scheduler
+    assert( sched->sig_pending , __FUNCTION__ , "no pending signal" );
+    
+    // enter critical section
+    hal_disable_irq( &save_sr );
+      
+    // reset signal in scheduler
+    sched->sig_pending = false;
+
+    // reset signal in thread "flags"
+    hal_atomic_and( &thread->flags , ~THREAD_FLAG_SIGNAL );
+
+    // reset pointer on responses counter 
+    thread->sig_rsp_count = NULL;
+    
+    // exit critical section
+    hal_restore_irq( save_sr );
+
     hal_fence();
-}
+
+}  // thread_reset_signal()
 
 ////////////////////////////////
@@ -760,50 +806,56 @@
 }  // end thread_unblock()
 
-/////////////////////
-error_t thread_exit()
-{
-    reg_t      sr_save;
-
-	thread_t * this = CURRENT_THREAD;
-
-    // test if this thread can be descheduled
-	if( !thread_can_yield() )
-	{
-        printk("ERROR in %s : locks not released for thread %x in process %x on core[%x,%d]\n",
-        __FUNCTION__, this->trdid, this->process->pid, local_cxy, this->core->lid );
-        return EINVAL;
-    }
-
-    if( this->flags & THREAD_FLAG_DETACHED )
-    {
-        // if detached set signal and set blocking cause atomically
-        hal_disable_irq( &sr_save );
-        thread_set_signal( this , THREAD_SIG_KILL );
-        thread_block( this , THREAD_BLOCKED_EXIT );
-        hal_restore_irq( sr_save );
-    }
-    else
-    {
-        // if attached, set blocking cause
-        thread_block( this , THREAD_BLOCKED_EXIT );
-    }
-
-    // deschedule
-    sched_yield( "exit" );
-    return 0;
-
-}  // end thread_exit()
-
 /////////////////////////////////////
 void thread_kill( thread_t * target )
 {
-    // set SIG_KILL signal in target thread descriptor
-    thread_set_signal( target , THREAD_SIG_KILL );
+    volatile uint32_t  sig_rsp_count = 1;     // responses counter
+
+    thread_t * killer = CURRENT_THREAD;
+
+kill_dmsg("\n[DBG] %s : killer thread %x enter for target thread %x\n",
+__FUNCTION__, local_cxy, killer->trdid , target trdid );
 
     // set the global blocked bit in target thread descriptor.
     thread_block( target , THREAD_BLOCKED_GLOBAL );
 
-    // send an IPI to schedule the target thread core.
-    dev_pic_send_ipi( local_cxy , target->core->lid );
+    // 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_signal( target , (uint32_t *)(&sig_rsp_count) );
+
+        // send an IPI to the target thread core.
+        dev_pic_send_ipi( local_cxy , target->core->lid );
+
+        // poll the response
+        while( 1 )
+        {
+            // exit when response received from scheduler
+            if( sig_rsp_count == 0 )  break;
+
+            // deschedule without blocking
+            hal_fixed_delay( 1000 );
+        }
+    }
+
+	// release FPU if required
+	if( target->core->fpu_owner == target )  target->core->fpu_owner = NULL;
+
+    // detach thread from parent if attached
+    if( (target->flags & THREAD_FLAG_DETACHED) == 0 ) 
+    thread_child_parent_unlink( target->parent , XPTR( local_cxy , target ) );
+
+    // detach thread from process
+    process_remove_thread( target );
+
+    // remove thread from scheduler
+    sched_remove_thread( target );
+
+    // release memory allocated to target thread
+    thread_destroy( target );
+
+kill_dmsg("\n[DBG] %s : killer thread %x enter for target thread %x\n",
+__FUNCTION__, local_cxy, killer->trdid , target trdid );
 
 }  // end thread_kill()
