Index: trunk/kernel/kern/thread.c
===================================================================
--- trunk/kernel/kern/thread.c	(revision 16)
+++ trunk/kernel/kern/thread.c	(revision 23)
@@ -3,6 +3,5 @@
  * 
  * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
- *         Mohamed Lamine Karaoui (2015)
- *         Alain Greiner (2016)
+ *         Alain Greiner (2016,2017)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -74,6 +73,6 @@
 static thread_t * thread_alloc()
 {
-	page_t       * page;       // pointer on page descriptor containing thread descriptor
-	kmem_req_t     req;        // kmem request 
+	page_t       * page;   // pointer on page descriptor containing thread descriptor
+	kmem_req_t     req;    // kmem request 
 
 	// allocates memory for thread descriptor + kernel stack
@@ -84,14 +83,25 @@
 
     // return pointer on new thread descriptor
-	if( page == NULL ) 
-    {
-        printk("\n[ERROR] in %s : no memory for thread descriptor\n", __FUNCTION__ );
-        return NULL;
-    }
-    else
-    {
-        return (thread_t *)ppm_page2base( page );
-    }
-}  // end thread_alloc()
+	if( page == NULL ) return NULL;
+    else               return (thread_t *)ppm_page2base( page );
+}  
+
+/////////////////////////////////////////////////////////////////////////////////////
+// This static function releases the physical memory for a thread descriptor.
+// It can be called by the three functions:
+// - thread_user_create()
+// - thread_user_fork()
+// - thread_kernel_create()
+/////////////////////////////////////////////////////////////////////////////////////
+// @ thread  : pointer on thread descriptor.
+/////////////////////////////////////////////////////////////////////////////////////
+static void thread_release( thread_t * thread )
+{
+    kmem_req_t   req;
+
+    req.type  = KMEM_PAGE;
+    req.ptr   = ppm_base2page( thread );
+    kmem_free( &req );
+}
 
 /////////////////////////////////////////////////////////////////////////////////////
@@ -194,8 +204,9 @@
 
 /////////////////////////////////////////////////////////
-error_t thread_user_create( thread_t       ** new_thread,
+error_t thread_user_create( pid_t             pid,
+                            void            * start_func,
+                            void            * start_arg,
                             pthread_attr_t  * attr,
-                            intptr_t          u_stack_base,
-                            uint32_t          u_stack_size )
+                            thread_t       ** new_thread )
 {
     error_t        error;
@@ -203,25 +214,49 @@
     process_t    * process;      // pointer to local process descriptor
     lid_t          core_lid;     // selected core local index
-	kmem_req_t     req;          // kmem request (for release) 
-
-    thread_dmsg("\n[INFO] %s : enters\n", __FUNCTION__ );
-
-	cluster_t    * local_cluster = LOCAL_CLUSTER;
+    vseg_t       * vseg;         // stack vseg
+
+    thread_dmsg("\n[INFO] %s : enters for process %x\n", __FUNCTION__ , pid );
+
+    // get process descriptor local copy
+    process = process_get_local_copy( pid );
+
+    if( process == NULL )
+    {
+		printk("\n[ERROR] in %s : cannot get process descriptor %x\n",
+               __FUNCTION__ , pid );
+        return ENOMEM;
+    }
 
     // select a target core in local cluster 
-    if( attr->flags & PT_FLAG_CORE_DEFINED ) core_lid = attr->lid;
-    else                                     core_lid = cluster_select_local_core();
+    if( attr->attributes & PT_ATTR_CORE_DEFINED ) core_lid = attr->lid;
+    else                                          core_lid = cluster_select_local_core();
 
     // check core local index
-    if( core_lid >= local_cluster->cores_nr ) return EINVAL;
-
-    // get process descriptor local copy
-    process = process_get_local_copy( attr->pid );
-    if( process == NULL ) return ENOMEM;
+    if( core_lid >= LOCAL_CLUSTER->cores_nr )
+    {
+	    printk("\n[ERROR] in %s : illegal core index attribute = %d\n",
+               __FUNCTION__ , core_lid );
+       
+        return EINVAL;
+    }
+
+    // allocate a stack from local VMM 
+    vseg = vmm_create_vseg( process, 0 , 0 , VSEG_TYPE_STACK );
+
+    if( vseg == NULL );
+    {
+	    printk("\n[ERROR] in %s : cannot create stack vseg\n", __FUNCTION__ );
+		return ENOMEM;
+    } 
 
     // allocates memory tor thread descriptor
     thread = thread_alloc();
 
-    if( thread == NULL ) return ENOMEM;
+    if( thread == NULL )
+    {
+	    printk("\n[ERROR] in %s : cannot create new thread\n", __FUNCTION__ );
+        vmm_remove_vseg( vseg );
+        return ENOMEM;
+    }
 
     // initializes thread descriptor
@@ -229,15 +264,15 @@
                          process,
                          THREAD_USER,
-                         attr->entry_func,
-                         attr->entry_args,
+                         start_func,
+                         start_arg,
                          core_lid,
-                         u_stack_base,
-                         u_stack_size );
-
-    if( error )  // release allocated memory for thread descriptor 
-    {
-	    req.type  = KMEM_PAGE;
-        req.ptr   = ppm_base2page( thread );
-        kmem_free( &req );
+                         vseg->min,
+                         vseg->max - vseg->min );
+
+    if( error ) 
+    {
+	    printk("\n[ERROR] in %s : cannot initialize new thread\n", __FUNCTION__ );
+        vmm_remove_vseg( vseg );
+        thread_release( thread );
         return EINVAL;
     }
@@ -247,14 +282,28 @@
 
     // set DETACHED flag if required
-    if( attr->flags & PT_FLAG_DETACH ) thread->flags |= THREAD_FLAG_DETACHED;
+    if( attr->attributes & PT_ATTR_DETACH ) thread->flags |= THREAD_FLAG_DETACHED;
 
     // allocate & initialise CPU context 
 	error = hal_cpu_context_create( thread ); 
-    if( error ) return ENOMEM;
+
+    if( error ) 
+    {
+	    printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ );
+        vmm_remove_vseg( vseg );
+        thread_release( thread );
+        return ENOMEM;
+    }
 
     // allocate & initialise FPU context 
     error = hal_fpu_context_create( thread ); 
-    if( error ) return ENOMEM;
-  
+
+    if( error )
+    {
+	    printk("\n[ERROR] in %s : cannot create FPU context\n", __FUNCTION__ );
+        vmm_remove_vseg( vseg );
+        thread_release( thread );
+        return ENOMEM;
+    }
+
     thread_dmsg("\n[INFO] %s : exit / trdid = %x / process %x / core = %d\n", 
                 __FUNCTION__ , thread->trdid , process->pid , core_lid );
@@ -266,16 +315,23 @@
 
 
-/////////////////////////////////////////////////
-error_t thread_user_fork( thread_t ** new_thread,
-                          process_t * process,
-                          intptr_t    u_stack_base,
-                          uint32_t    u_stack_size )
+//////////////////////////////////////////////
+error_t thread_user_fork( process_t * process,
+                          thread_t ** new_thread )
 {
     error_t        error;
 	thread_t     * thread;       // pointer on new thread descriptor
     lid_t          core_lid;     // selected core local index
-	kmem_req_t     req;          // kmem request (for release) 
+	vseg_t       * vseg;         // stack vseg
 
     thread_dmsg("\n[INFO] %s : enters\n", __FUNCTION__ );
+
+    // allocate a stack from local VMM 
+    vseg = vmm_create_vseg( process, 0 , 0 , VSEG_TYPE_STACK );
+
+    if( vseg == NULL );
+    {
+	    printk("\n[ERROR] in %s : cannot create stack vseg\n", __FUNCTION__ );
+		return ENOMEM;
+    } 
 
     // select a target core in local cluster
@@ -288,5 +344,10 @@
     thread = thread_alloc();
 
-    if( thread == NULL ) return ENOMEM;
+    if( thread == NULL )
+    {
+        printk("\n[ERROR] in %s : cannot allocate new thread\n", __FUNCTION__ );
+        vmm_remove_vseg( vseg );
+        return ENOMEM;
+    }
 
     // initializes thread descriptor
@@ -297,12 +358,12 @@
                          this->entry_args,
                          core_lid,
-                         u_stack_base,
-                         u_stack_size );
-
-    if( error ) // release allocated memory for thread descriptor 
-    {
-	    req.type  = KMEM_PAGE;
-        req.ptr   = ppm_base2page( thread );
-        kmem_free( &req );
+                         vseg->min,
+                         vseg->max - vseg->min );
+
+    if( error )
+    {
+	    printk("\n[ERROR] in %s : cannot initialize new thread\n", __FUNCTION__ );
+        vmm_remove_vseg( vseg );
+        thread_release( thread );
         return EINVAL;
     }
@@ -313,11 +374,25 @@
     // allocate & initialise CPU context from calling thread
 	error = hal_cpu_context_copy( thread , this ); 
-    if( error ) return ENOMEM;
+
+    if( error )
+    {
+	    printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ );
+        vmm_remove_vseg( vseg );
+        thread_release( thread );
+        return ENOMEM;
+    }
 
     // allocate & initialise FPU context from calling thread
 	error = hal_fpu_context_copy( thread , this ); 
-    if( error ) return ENOMEM;
-
-    thread_dmsg("INFO : %s thread %x for process %x on core %d in cluster %x\n", 
+
+    if( error )
+    {
+	    printk("\n[ERROR] in %s : cannot create CPU context\n", __FUNCTION__ );
+        vmm_remove_vseg( vseg );
+        thread_release( thread );
+        return ENOMEM;
+    }
+
+    thread_dmsg("\n[INFO] %s : exit / thread %x for process %x on core %d in cluster %x\n", 
                  __FUNCTION__, thread->trdid, process->pid, core_lid, local_cxy );
 
@@ -473,12 +548,12 @@
 	spinlock_unlock( &process->th_lock );
 	
+    // update local DQDT
+    dqdt_local_update_threads( -1 );
+
     // invalidate thread descriptor
 	thread->signature = 0;
 
     // release memory for thread descriptor
-	kmem_req_t   req; 
-	req.type     = KMEM_PAGE; 
-	req.ptr      = ppm_base2page( thread );
-	kmem_free(&req);
+    thread_release( thread );
 
 	tm_end = hal_time_stamp();
@@ -706,5 +781,5 @@
 
 ////////////////////////////////////////////////
-void thread_signals_handler( thread_t * thread )
+void thread_signals_handle( thread_t * thread )
 {
     // TODO
@@ -712,3 +787,67 @@
 }
 
-
+/////////////////////////////////////
+xptr_t thread_get_xptr( pid_t    pid,
+                        trdid_t  trdid )
+{
+    cxy_t         target_cxy;          // target thread cluster identifier
+    ltid_t        target_thread_ltid;  // target thread local index
+    thread_t    * target_thread_ptr;   // target thread local pointer           
+    xptr_t        target_process_xp;   // extended pointer on target process descriptor
+    process_t   * target_process_ptr;  // local pointer on target process descriptor 
+    pid_t         target_process_pid;  // target process identifier
+    xlist_entry_t root;                // root of list of process in target cluster
+    xptr_t        lock_xp;             // extended pointer on lock protecting  this list
+
+    // get target cluster identifier and local thread identifier
+    target_cxy         = CXY_FROM_TRDID( trdid );
+    target_thread_ltid = LTID_FROM_TRDID( trdid );
+
+    // get root of list of process descriptors in target cluster
+    hal_remote_memcpy( XPTR( local_cxy  , &root ),
+                       XPTR( target_cxy , &LOCAL_CLUSTER->pmgr.local_root ),
+                       sizeof(xlist_entry_t) );
+
+    // get extended pointer on lock protecting the list of processes 
+    lock_xp = XPTR( target_cxy , &LOCAL_CLUSTER->pmgr.local_lock );
+
+    // take the lock protecting the list of processes in target cluster
+    remote_spinlock_lock( lock_xp );
+
+    // loop on list of process in target cluster to find the PID process
+    xptr_t  iter;
+    bool_t  found = false;
+    XLIST_FOREACH( XPTR( target_cxy , &LOCAL_CLUSTER->pmgr.local_root ) , iter )
+    {
+        target_process_xp  = XLIST_ELEMENT( iter , process_t , local_list );
+        target_process_ptr = (process_t *)GET_PTR( target_process_xp );
+        target_process_pid = hal_remote_lw( XPTR( target_cxy , &target_process_ptr->pid ) );
+        if( target_process_pid == pid )
+        {
+            found = true;
+            break;
+        }
+    }
+
+    // release the lock protecting the list of processes in target cluster
+    remote_spinlock_unlock( lock_xp );
+
+    // check target thread found
+    if( found == false )
+    {
+        return XPTR_NULL;
+    }
+
+    // get target thread local pointer
+    xptr_t xp = XPTR( target_cxy , &target_process_ptr->th_tbl[target_thread_ltid] );
+    target_thread_ptr = (thread_t *)hal_remote_lpt( xp );    
+
+    if( target_thread_ptr == NULL )
+    {
+        return XPTR_NULL;
+    }
+
+    return XPTR( target_cxy , target_thread_ptr );
+
+}  // end thread_get_xptr()
+
