Index: trunk/kernel/syscalls/sys_thread_exit.c
===================================================================
--- trunk/kernel/syscalls/sys_thread_exit.c	(revision 433)
+++ trunk/kernel/syscalls/sys_thread_exit.c	(revision 436)
@@ -32,78 +32,43 @@
 int sys_thread_exit( void * exit_value )
 {
-    paddr_t      paddr;
-    error_t	     error;
-
-#if CONFIG_SYSCALL_DEBUG
-uint32_t     tm_start;
-uint32_t     tm_end;
-tm_start = hal_get_cycles();
-#endif
-
 	thread_t  * this    = CURRENT_THREAD;
     process_t * process = this->process;
 
-    // check all locks released
-	if( !thread_can_yield() )
-	{
-        printk("\n[ERROR] in %s : locks not released / thread %x in process %x\n",
-        __FUNCTION__, this->trdid, process->pid );
+    // check exit_value argument
+    if( exit_value != NULL )
+    {
+
+#if CONFIG_DEBUG_SYSCALLS_ERROR
+printk("\n[ERROR] in %s : exit_value argument must be NULL for thread %x in process %x\n",
+__FUNCTION__ , exit_value, this->trdid , process->pid );
+#endif
         this->errno = EINVAL;
         return -1;
     }
 
-    // register the exit_value pointer in this thread descriptor
-    this->join_value = exit_value;
-
-    if( (this->flags & THREAD_FLAG_DETACHED) == 0 )    // this thread is joinable
-    {
-        // check exit_value in user space
-        error = vmm_v2p_translate( false , exit_value , &paddr );
-	    if( error )
-        {
-            printk("\n[ERROR] in %s : illegal pointer = %x / thread %x in process %x\n",
-            __FUNCTION__ , (intptr_t)exit_value, this->trdid , process->pid );
-            this->errno = EINVAL;
-            return -1;
-        }
-
-        // take the lock protecting the join 
-        remote_spinlock_lock( XPTR( local_cxy, &this->join_lock ) );
-
-        if( this->flags & THREAD_FLAG_JOIN_DONE )       // parent thread arrived first
-        {
-            // unblock the parent thread
-            thread_unblock( this->join_xp , THREAD_BLOCKED_EXIT );
-
-            // reset the JOIN_DONE flag in this thread
-            this->flags &= ~THREAD_FLAG_JOIN_DONE;
-
-            // release the lock protecting the flags
-	        remote_spinlock_unlock( XPTR( local_cxy, &this->join_lock ) );
-        }
-        else                                           // this thread arrived first
-        {
-            // block this thread
-            thread_block( this , THREAD_BLOCKED_JOIN );
-
-            // release the lock protecting the join
-	        remote_spinlock_unlock( XPTR( local_cxy, &this->join_lock ) );
-
-            // deschedule
-            sched_yield( "WAITING JOIN" );
-        }     
-    }
-
-#if CONFIG_SYSCALL_DEBUG
-tm_end = hal_get_cycles();
-syscall_dmsg("\n[DBG] %s : core[%x,%d] / thread %x in process %x / cycle %d\n"
-"thread %x killed / cost = %d\n",
-__FUNCTION__ , local_cxy , this->core->lid , this->trdid , this->process->pid , tm_start ,
-this->trdid , (uint32_t)(tm_end - tm_start) );
+#if CONFIG_DEBUG_SYS_THREAD_EXIT
+uint64_t     tm_start;
+uint64_t     tm_end;
+tm_start = hal_get_cycles();
+if( CONFIG_DEBUG_SYS_THREAD_EXIT < tm_start )
+printk("\n[DBG] %s : thread %x enter / process %x / cycle %d\n",
+__FUNCTION__ , this, process->pid , (uint32_t)tm_start );
 #endif
 
-    // suicide using a rpc because  a thread cannot kill itself
-    rpc_thread_kill_client( local_cxy , this );
+    // cal the relevant kernel function
+    thread_kill( XPTR( local_cxy , this ),
+                 1,           // is_exit
+                 0 );         // is forced
 
+#if CONFIG_DEBUG_SYS_THREAD_EXIT
+tm_end = hal_get_cycles();
+if( CONFIG_DEBUG_SYS_THREAD_EXIT < tm_end )
+printk("\n[DBG] %s : thread %x exit / process %x / cost %d / cycle %d\n",
+__FUNCTION__, this, this->process->pid, (uint32_t)(tm_end - tm_start), (uint32_t)tm_end );
+#endif
+
+    // deschedule <=> suicide, because blocked by thread_kill()
+    sched_yield( "suicide after thread_exit" );
+    
     return 0;   // never executed but required by compiler
 
