Index: trunk/kernel/syscalls/sys_thread_exit.c
===================================================================
--- trunk/kernel/syscalls/sys_thread_exit.c	(revision 690)
+++ trunk/kernel/syscalls/sys_thread_exit.c	(revision 1)
@@ -1,16 +1,15 @@
 /*
- * sys_thread_exit.c - terminates the execution of calling thread
+ * kern/sys_thread_exit.c - terminates the execution of current thread
  * 
- * Authors   Alain Greiner (2016,2017,2018,2019,2020)
+ * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless
+ * Copyright (c) 2011,2012 UPMC Sorbonne Universites
  *
- * Copyright (c) UPMC Sorbonne Universites
+ * This file is part of ALMOS-kernel.
  *
- * This file is part of ALMOS-MKH.
- *
- * ALMOS-MKH is free software; you can redistribute it and/or modify it
+ * ALMOS-kernel is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
  * the Free Software Foundation; version 2.0 of the License.
  *
- * ALMOS-MKH is distributed in the hope that it will be useful, but
+ * ALMOS-kernel is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
@@ -18,102 +17,77 @@
  *
  * You should have received a copy of the GNU General Public License
- * along with ALMOS-MKH; if not, write to the Free Software Foundation,
+ * along with ALMOS-kernel; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <hal_kernel_types.h>
-#include <hal_irqmask.h>
+#include <list.h>
 #include <thread.h>
+#include <scheduler.h>
+#include <wait_queue.h>
+#include <cluster.h>
+#include <dqdt.h>
 #include <process.h>
-#include <core.h>
-#include <vmm.h>
-#include <scheduler.h>
-#include <printk.h>
 
-#include <syscalls.h>
+///////////////////////////////////////
+int sys_thread_exit ( void * exit_val )
+{
+	thread_t * this = current_thread;
+    cpu_t    * cpu  = current_cpu;
+	uint32_t   state;
+	bool_t     isEmpty;
+	bool_t     isReleased;
 
-/////////////////////////////////////////
-int sys_thread_exit( void * exit_status )
-{
-    error_t     error;
-    vseg_t    * vseg;
+	/* TODO: the cpu->lid must match the core index in the logical cluster */
+	if(this->process->pid != 1)
+		dqdt_update_threads_number( local_cxy , cpu->lid , -1 );
 
-	thread_t  * this      = CURRENT_THREAD;
-    trdid_t     trdid     = this->trdid;
-    process_t * process   = this->process;
-    pid_t       pid       = process->pid;
-    
-#if DEBUG_SYS_THREAD_EXIT || DEBUG_SYSCALLS_ERROR 
-uint64_t     tm_start = hal_get_cycles();
-#endif
+	spinlock_lock( &this->lock );
 
-    // check exit_value pointer in user space if required
-    if( exit_status != NULL )
-    {
-        error = vmm_get_vseg( process , (intptr_t)exit_status  , &vseg );
+	if(!(thread_isJoinable(this)))
+	{
+		spinlock_unlock_nosched(&this->lock);
+		goto exit_dead;
+	}
 
-    	if( error )
-	    {
+	// Check if there's a thread waiting the end of callee thread
+	isEmpty = wait_queue_isEmpty(&this->info.wait_queue);
 
-#if DEBUG_SYSCALLS_ERROR
-if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start ) 
-printk("\n[WARNING] in %s : exit_status buffer %x unmapped / thread[%x,%x]\n",
-__FUNCTION__, (intptr_t)exit_status, pid, trdid );
-#endif
-            this->errno = EINVAL;
-	        return -1;
-        }
-    }
+	if(isEmpty)
+	{
+		this->info.exit_value = exit_val;
+		wait_on(&this->info.wait_queue, WAIT_ANY);
+		spinlock_unlock_nosched(&this->lock);
+		sched_sleep(this);
+	}
+	else
+	{
+		this->info.join->info.exit_value = exit_val;
+		wakeup_one(&this->info.wait_queue, WAIT_ANY);
+		spinlock_unlock_nosched(&this->lock);
+	}
 
-	// check busylocks
-    uint32_t count = this->busylocks;
-	if( count )
+exit_dead:
+
+	isReleased = false;
+
+	// Release FPU if required
+	cpu_disable_all_irq(&state);
+	if(current_cpu->fpu_owner == this)
 	{
+		current_cpu->fpu_owner = NULL;
+		isReleased = true;
+	}
+	cpu_restore_irq(state);
 
-#if DEBUG_SYSCALLS_ERROR
-if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start ) 
-printk("\n[WARNING] in %s : busylocks count = %d  / thread[%x,%x]\n",
-__FUNCTION__ , count, pid, trdid );
-#endif
-            this->errno = EINVAL;
-	        return -1;
-    }
+	if(isReleased)
+	{
+		thread_dmsg(1, "INFO: Thread %x has released FPU on CPU %d\n",
+		       this, 
+		       current_cpu->gid);
+	}
 
-    // If calling thread is the main thread, the process must be deleted. 
-    // => delete all process threads and synchronize with parent process.
-    // If calling thread is not the main thread, only this thread must be deleted.
-    // => register exit_status in thread descriptor, block the thread, 
-    //    mark it for delete, and synchronize with joining thread. 
+	sched_exit(this);
 
-    if( (CXY_FROM_PID( pid ) == local_cxy) && (LTID_FROM_TRDID(trdid) == 0) )  // main
-    {
-
-#if DEBUG_SYS_THREAD_EXIT
-if( DEBUG_SYS_THREAD_EXIT < (uint32_t)tm_start ) 
-printk("\n[%s] thread[%x,%x] is main => delete process / cycle %d\n",
-__FUNCTION__ , pid , trdid , (uint32_t)tm_start );
-#endif
-        // delete process
-        sys_exit( 0 );
-    }
-    else                                                             // not the main
-    {
-
-#if DEBUG_SYS_THREAD_EXIT
-if( DEBUG_SYS_THREAD_EXIT < (uint32_t)tm_start )
-printk("\n[%s] thread[%x,%x] is not main => delete thread / cycle %d\n",
-__FUNCTION__ , pid , trdid , (uint32_t)tm_start );
-#endif
-        // register exit_status in thread descriptor
-        this->exit_status = exit_status;
-
-        // block calling thread and mark it for delete,
-        thread_delete_request( XPTR( local_cxy , this ) , false );   // not forced
-
-        // deschedule
-        sched_yield( "suicide after thread_exit" );
-    }
-
-    return 0;   // never executed but required by compiler
-
-}  // end sys_thread exit
+	PANIC ("Thread %x, CPU %d must never return", this, current_cpu->gid);
+	return -1;		/* Fake return ! */
+}
