Index: trunk/kernel/kern/process.c
===================================================================
--- trunk/kernel/kern/process.c	(revision 14)
+++ trunk/kernel/kern/process.c	(revision 23)
@@ -4,5 +4,5 @@
  * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
  *          Mohamed Lamine Karaoui (2015)
- *          Alain Greiner (2016)
+ *          Alain Greiner (2016,2017)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -47,4 +47,5 @@
 #include <process.h>
 #include <elf.h>
+#include <syscalls.h>
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -103,15 +104,15 @@
                              pid_t       ppid )
 {
-    // reset signal manager  TODO [AG]
-
-    // reset the file descriptors array 
+    // reset reference process vmm
+    vmm_init( process );
+
+    // reset reference process file descriptors array 
 	process_fd_init( process );
 
-    // reset the process files structures and cd_lock
+    // reset reference process files structures and cd_lock
 	process->vfs_root_xp     = XPTR_NULL;
+	process->vfs_bin_xp      = XPTR_NULL;
 	process->vfs_cwd_xp      = XPTR_NULL;
-	process->vfs_bin_xp      = XPTR_NULL;
-
-    spinlock_init( &process->cd_lock );
+    remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
 
     // reset children list root
@@ -119,7 +120,10 @@
 	process->children_nr     = 0;
 
-    // reset semaphore list root
+    // reset semaphore / mutex / barrier / condvar list roots
     xlist_root_init( XPTR( local_cxy , &process->sem_root ) );
-	process->sem_nr          = 0;
+    xlist_root_init( XPTR( local_cxy , &process->mutex_root ) );
+    xlist_root_init( XPTR( local_cxy , &process->barrier_root ) );
+    xlist_root_init( XPTR( local_cxy , &process->condvar_root ) );
+    remote_spinlock_init( XPTR( local_cxy , &process->sync_lock ) );
 
     // register new process in the parent children list
@@ -128,5 +132,5 @@
     xlist_add_first( root , entry );
     
-    // reset th_tbl[] array
+    // reset th_tbl[] array as empty
     uint32_t i;
     for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
@@ -137,13 +141,9 @@
     spinlock_init( &process->th_lock );
 
-    // reset process VMM 
-	memset( &process->vmm , 0 , sizeof(vmm_t) );
-
     // initialize PID and PPID
 	process->pid   = pid;
     process->ppid  = ppid;
 
-    // set ref_xp field and is_ref flag
-    process->is_ref = true;
+    // set ref_xp field 
     process->ref_xp = XPTR( local_cxy , process );
 
@@ -153,4 +153,6 @@
     // register new process descriptor in owner cluster manager copies_list
     cluster_process_copies_link( process );
+
+    // initalise signal manager TODO [AG]
 
 	hal_wbflush();
@@ -162,17 +164,23 @@
                            xptr_t      reference_process_xp )
 {
-    // replicate the remote process descriptor in new process descriptor
-    xptr_t local_process_xp = XPTR( local_cxy , local_process );
-    hal_remote_memcpy( local_process_xp , reference_process_xp , sizeof(process_t) );
-
-    // initalise signal manager TODO [AG]
-
-    // initialise file descriptors array TODO [AG]
-
-    // initialise process files structures TODO [AG]
-
-    // set the ref_xp field and clear the is_ref flag
+    // get reference process cluster and local pointer
+    cxy_t       ref_cxy = GET_CXY( reference_process_xp );
+    process_t * ref_ptr = (process_t *)GET_PTR( reference_process_xp );
+
+    // reset local process vmm 
+    vmm_init( local_process );
+
+    // reset process file descriptors array 
+	process_fd_init( local_process );
+
+    // reset vfs_root_xp / vfs_bin_xp / vfs_cwd_xp fields
+    local_process->vfs_root_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_root_xp ) );
+    local_process->vfs_bin_xp  = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->vfs_bin_xp ) );
+    local_process->vfs_cwd_xp  = XPTR_NULL;
+
+    // set the pid, ppid, ref_xp fields
+    local_process->pid    = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->pid ) );
+    local_process->ppid   = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->ppid ) );
     local_process->ref_xp = reference_process_xp;
-    local_process->is_ref = false;
 
     // reset children list root (not used in a process descriptor copy)
@@ -185,7 +193,9 @@
     // reset semaphores list root (not used in a process descriptor copy)
     xlist_root_init( XPTR( local_cxy , &local_process->sem_root ) );
-    local_process->sem_nr        = 0;           
-
-    // initialize th_tbl[] array as empty
+    xlist_root_init( XPTR( local_cxy , &local_process->mutex_root ) );
+    xlist_root_init( XPTR( local_cxy , &local_process->barrier_root ) );
+    xlist_root_init( XPTR( local_cxy , &local_process->condvar_root ) );
+
+    // reset th_tbl[] array as empty
     uint32_t i;
     for( i = 0 ; i < CONFIG_THREAD_MAX_PER_CLUSTER ; i++ )
@@ -196,6 +206,4 @@
     spinlock_init( &local_process->th_lock );
 
-    // initialise  process VMM TODO [AG]
-
     // register new process descriptor in local cluster manager local_list
     cluster_process_local_link( local_process );
@@ -203,4 +211,6 @@
     // register new process descriptor in owner cluster manager copies_list
     cluster_process_copies_link( local_process );
+
+    // initalise signal manager TODO [AG]
 
 	hal_wbflush();
@@ -223,8 +233,12 @@
     pmgr_t * pmgr = &LOCAL_CLUSTER->pmgr;
 
+    // get the lock protecting the list of local process descriptors
+    remote_spinlock_lock( XPTR( local_cxy , &pmgr->local_lock ) );
+
     // remove the process descriptor from local_list in local cluster manager 
-    spinlock_lock( &pmgr->local_lock );
     xlist_unlink( XPTR( local_cxy , &process->local_list ) );
-    spinlock_unlock( &pmgr->local_lock );
+
+    // release the lock protecting the list of local process descriptors
+    remote_spinlock_unlock( XPTR( local_cxy , &pmgr->local_lock ) );
 
     // get extended pointer on copies_lock in owner cluster manager
@@ -243,11 +257,10 @@
     // From this point, the process descriptor is unreachable 
 
+    // close all open files and update dirty TODO [AG]
+
     // release signal manager TODO [AG]
 
-    // delete all open file descriptors
-    process_fd_destroy( process );
-
-    // Close bin file and decrease refcount for root and cwd
-	if( process->vfs_bin_xp != XPTR_NULL ) vfs_close( process->vfs_bin_xp , NULL );
+    // Decrease refcount for bin file, root file and cwd file
+	vfs_file_count_down( process->vfs_bin_xp );
     vfs_file_count_down( process->vfs_root_xp );
     vfs_file_count_down( process->vfs_cwd_xp );
@@ -325,26 +338,26 @@
 
 
-
-
-
 ///////////////////////////////////////////////
 process_t * process_get_local_copy( pid_t pid )
 {
     error_t        error;
-    bool_t         found;
-    list_entry_t * iter;
-    process_t    * process;     // pointer on local copy
+    process_t    * process_ptr;   // local pointer on process 
+    xptr_t         process_xp;    // extended pointer on process
+    pid_t          process_pid;   // process identifier
 
     cluster_t * cluster = LOCAL_CLUSTER;
 
     // get lock protecting local list of processes
-    spinlock_lock( &cluster->pmgr.local_lock );
+    remote_spinlock_lock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
 
     // scan the local list of process descriptors to find the process
-    found = false;
-    LIST_FOREACH( &cluster->pmgr.local_root , iter )
-    {
-        process = LIST_ELEMENT( iter , process_t , local_list );
-        if( process->pid == pid )
+    xptr_t  iter;
+    bool_t  found = false;
+    XLIST_FOREACH( XPTR( local_cxy , &cluster->pmgr.local_root ) , iter )
+    {
+        process_xp  = XLIST_ELEMENT( iter , process_t , local_list );
+        process_ptr = (process_t *)GET_PTR( process_xp );
+        process_pid = hal_remote_lw( XPTR( local_cxy , &process_ptr->pid ) ); 
+        if( process_ptr->pid == pid )
         {
             found = true;
@@ -354,26 +367,25 @@
 
     // release lock protecting local list of processes
-    spinlock_unlock( &cluster->pmgr.local_lock );
-
-    // allocate memory for a local process descriptor 
-    // and initialise it from reference if required
+    remote_spinlock_unlock( XPTR( local_cxy , &cluster->pmgr.local_lock ) );
+
+    // allocate memory for a new local process descriptor 
+    // and initialise it from reference cluster if required
     if( !found )
     {
         // get extended pointer on reference process descriptor
-        xptr_t reference = cluster_get_reference_process_from_pid( pid );
+        xptr_t ref_xp = cluster_get_reference_process_from_pid( pid );
+
+        assert( (ref_xp != XPTR_NULL) , __FUNCTION__ , "illegal pid\n" );
 
         // allocate memory for local process descriptor
-        process = process_alloc();
-        if( process == NULL )  return NULL;
+        process_ptr = process_alloc();
+        if( process_ptr == NULL )  return NULL;
 
         // initialize local process descriptor copy
-        error = process_copy_init( process, reference );
+        error = process_copy_init( process_ptr , ref_xp );
         if( error ) return NULL;
-
-        
-        // register process in global copies_list
-    }
-
-    return process;
+    }
+
+    return process_ptr;
 } // end process_get_local_copy()
 
@@ -389,9 +401,9 @@
 
     remote_spinlock_init( XPTR( local_cxy , &process->fd_array.lock ) );
-    process->fd_array.max       = CONFIG_PROCESS_FILE_MAX_NR;
-    process->fd_array.current   = 0;
+
+    process->fd_array.current = 0;
 
     // initialize array
-    for ( fd = 0 ; fd < process->fd_array.max ; fd++ )
+    for ( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
     {
         process->fd_array.array[fd] = XPTR_NULL;
@@ -399,96 +411,91 @@
 }
 
-//////////////////////////////////////////////
-void process_fd_destroy( process_t * process )
-{
-    uint32_t fd;
-
-    // loop on all open file descriptors to close all open files 
-    for( fd = 0 ; fd < process->fd_array.max ; fd++ )
-    {
-        xptr_t file_xp = process->fd_array.array[fd];
-        if ( file_xp != XPTR_NULL ) vfs_close( file_xp , NULL );
-    }
+
+//////////////////////////////
+bool_t process_fd_array_full()
+{
+    // get extended pointer on reference process 
+    xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
+
+    // get reference process cluster and local pointer
+    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
+    cxy_t       ref_cxy = GET_CXY( ref_xp );
+
+    // get number of open file descriptors from reference fd_array
+    uint32_t current = hal_remote_lw( XPTR( ref_cxy , &ref_ptr->fd_array.current ) );
+
+	return ( current >= CONFIG_PROCESS_FILE_MAX_NR );  
 }
 
-///////////////////////////////////////////////////
-bool_t process_fd_array_full( process_t * process )
-{
-	return ( process->fd_array.current >= process->fd_array.max);  
-}
-
 /////////////////////////////////////////////////
-error_t process_fd_allocate( process_t * process, 
-                             xptr_t      file_xp, 
-                             uint32_t   * ret_fd )
+error_t process_fd_register(  xptr_t     file_xp, 
+                              uint32_t * file_id )
 {
     bool_t    found;
-    uint32_t  fd;
-
-	remote_spinlock_lock( XPTR( local_cxy , &process->fd_array.lock ) );
+    uint32_t  id;
+    xptr_t    xp;
+
+    // get extended pointer on reference process 
+    xptr_t ref_xp = CURRENT_THREAD->process->ref_xp;
+
+    // get reference process cluster and local pointer
+    process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
+    cxy_t       ref_cxy = GET_CXY( ref_xp );
+
+    // take lock protecting reference fd_array
+	remote_spinlock_lock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
 
     found   = false;
 
-    for ( fd = 0; fd < process->fd_array.max; fd++ )
-    {
-        if ( process->fd_array.array[fd] == XPTR_NULL )
+    for ( id = 0; id < CONFIG_PROCESS_FILE_MAX_NR ; id++ )
+    {
+        xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) );
+        if ( xp == XPTR_NULL )
         {
             found = true;
-            process->fd_array.array[fd] = file_xp;
-	        process->fd_array.current++;
-			*ret_fd = fd;
+            hal_remote_swd( XPTR( ref_cxy , &ref_ptr->fd_array.array[id] ) , file_xp );
+	        hal_remote_atomic_add( XPTR( ref_cxy , &ref_ptr->fd_array.current ) , 1 );
+			*file_id = id;
             break;
         }
     }
 
-	remote_spinlock_unlock( XPTR( local_cxy , &process->fd_array.lock ) );
+    // release lock protecting reference fd_array
+	remote_spinlock_unlock( XPTR( ref_cxy , &ref_ptr->fd_array.lock ) );
 
     if ( !found ) return EMFILE;
     else          return 0;
-} 
-
-////////////////////////////////////////////////
-error_t process_fd_release( process_t * process,
-                            uint32_t    fd )
-{
-    if ( (fd < 0) || (fd > process->fd_array.max) ) return EBADF;
-
-    remote_spinlock_lock( XPTR( local_cxy , &process->fd_array.lock ) );
-
-    process->fd_array.array[fd] = XPTR_NULL;
-	process->fd_array.current--;
-
-	remote_spinlock_unlock( XPTR( local_cxy , &process->fd_array.lock ) );
-
-    return 0;
-}
-
-///////////////////////////////////////
-void process_fd_copy( fd_array_t * dst,
-                      fd_array_t * src )
-{
-    uint32_t fd;
-    xptr_t   entry;
-
-    remote_spinlock_lock( XPTR( local_cxy , &src->lock ) );
-
-    // loop on all entries in source process fd_array        
-    for( fd = 0 ; fd < src->max ; fd++ )
-	{
-		entry = src->array[fd];
-
-		if( entry != XPTR_NULL )
-		{
-            // increment file descriptor ref count
-            vfs_file_count_up( entry );
-
-			// copy entry in destination process fd_array
-			dst->array[fd] = entry;
-		}
-	}
-
-    // release lock on source process fd_array
-	remote_spinlock_unlock( XPTR( local_cxy , &src->lock ) );
-} 
+
+}  // end process_fd_register()
+
+//////////////////////////////////////////////// 
+xptr_t process_fd_get_xptr( process_t * process,
+                            uint32_t    file_id )
+{
+    xptr_t  file_xp;
+
+    // access local copy of process descriptor
+    file_xp = process->fd_array.array[file_id];
+
+    if( file_xp == XPTR_NULL )
+    {
+        // get reference process cluster and local pointer
+        xptr_t      ref_xp  = process->ref_xp;
+        cxy_t       ref_cxy = GET_CXY( ref_xp );
+        process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
+
+        // access reference process descriptor
+        file_xp = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->fd_array.array[file_id] ) );
+
+        // update local fd_array if found
+        if( file_xp != XPTR_NULL )
+        {
+            process->fd_array.array[file_id] = file_xp;
+        }
+    }
+
+    return file_xp;
+
+}  // end process_fd_get_xptr()
 
 ///////////////////////////////////////////
@@ -510,9 +517,6 @@
 	remote_spinlock_lock( XPTR( src_cxy , &src_ptr->lock ) );
 
-    // get number of entries in fd_array
-    uint32_t max = hal_remote_lw( XPTR( src_cxy , &src_ptr->max ) );
-
     // loop on all entries in source process fd_array        
-    for( fd = 0 ; fd < max ; fd++ )
+    for( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
 	{
 		entry = (xptr_t)hal_remote_lwd( XPTR( src_cxy , &src_ptr->array[fd] ) );
@@ -609,10 +613,5 @@
     pid   = exec_info->pid;
     
-    if( CXY_FROM_PID( pid ) != local_cxy )
-    {
-        printk("\n[PANIC] in %s : illegal process PID %x in cluster %x\n",
-               __FUNCTION__ , pid , local_cxy );
-        hal_core_sleep();
-    }
+    assert( (CXY_FROM_PID( pid ) == local_cxy) , __FUNCTION__ , "illegal PID\n" );
 
     exec_dmsg("\n[INFO] %s enters in cluster %x for process %x / path = %s\n",
@@ -677,17 +676,4 @@
 	}
 
-    // create "stack" vseg descriptor for associated main thread
-    vseg_t * stack_vseg = vmm_create_vseg( process,
-                                           0,             // base defined by VMM
-                                           0,             // size defined by VMM
-                                           VSEG_TYPE_STACK );
-    if( stack_vseg == NULL )
-	{
-		printk("\n[ERROR] in %s : cannot create stack vseg for process %x / path = %s\n",
-		       __FUNCTION__, pid , path );
-        process_destroy( process );
-        return error;
-	}
-
     // select a core in cluster
     lid  = cluster_select_local_core();
@@ -695,16 +681,14 @@
 
     // initialize pthread attributes for main thread
-    attr.pid          = pid;
-    attr.entry_func   = (void*)process->vmm.entry_point;
-    attr.entry_args   = exec_info->args_pointers; 
-    attr.flags        = PT_FLAG_DETACH;             // main thread always detached
-    attr.cxy          = local_cxy;
-    attr.lid          = lid;
-
-    // create and initialise thread descriptor, link thread & process
-	error = thread_user_create( &thread, 
+    attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
+    attr.cxy        = local_cxy;
+    attr.lid        = lid;
+
+    // create and initialise thread descriptor
+	error = thread_user_create( pid,
+                                (void *)process->vmm.entry_point,
+                                exec_info->args_pointers,
                                 &attr,
-                                stack_vseg->min,
-                                stack_vseg->max - stack_vseg->min );
+                                &thread ); 
 	if( error )
 	{
@@ -732,5 +716,4 @@
 {
 	process_t   * process_init;  // process_init descriptor 
-	thread_t    * thread_init;   // process_init main thread descriptor
     pid_t         init_pid;      // process_init pid
     exec_info_t   exec_info;     // structure to be passed to process_make_exec()
@@ -779,18 +762,24 @@
 	process_zero.children_nr = 1;
 
-    // TODO open stdin / stdout / stderr pseudo-files
-    xptr_t  stdin_xp;
-    xptr_t  stdout_xp;
-    xptr_t  stderr_xp; 
-
-	// error1 = vfs_open( process_init->vfs_cwd_xp, NULL, VFS_O_RDONLY, &stdin_xp );
-	// error2 = vfs_open( process_init->vfs_cwd_xp, NULL, VFS_O_WRONLY, &stdout_xp );
-	// error3 = vfs_open( process_init->vfs_cwd_xp, NULL, VFS_O_WRONLY, &stderr_xp );
+    // TODO create inodes for stdin / stdout / stderr pseudo-files
+    // these inodes should be created in the cluster containing the relevant TXT chdev
+
+    // open stdin / stdout / stderr pseudo-files
+    xptr_t    stdin_xp;
+    xptr_t    stdout_xp;
+    xptr_t    stderr_xp;
+    uint32_t  stdin_id; 
+    uint32_t  stdout_id; 
+    uint32_t  stderr_id; 
+
+	error1 = vfs_open( XPTR_NULL, CONFIG_DEV_STDIN , O_RDONLY, 0, &stdin_xp , &stdin_id  );
+	error2 = vfs_open( XPTR_NULL, CONFIG_DEV_STDOUT, O_WRONLY, 0, &stdout_xp, &stdout_id );
+	error3 = vfs_open( XPTR_NULL, CONFIG_DEV_STDERR, O_WRONLY, 0, &stderr_xp, &stderr_id );
 
 	if( error1 || error2 || error3 )
 	{
-		if( !error1 ) vfs_close( stdin_xp  , NULL );
-		if( !error2 ) vfs_close( stdout_xp , NULL );
-		if( !error3 ) vfs_close( stderr_xp , NULL );
+		if( !error1 ) vfs_close( stdin_xp  , stdin_id );
+		if( !error2 ) vfs_close( stdout_xp , stdout_id );
+		if( !error3 ) vfs_close( stderr_xp , stderr_id );
     
 		printk("\n[PANIC] in %s : cannot open stdin/stdout/stderr in cluster %x\n",
@@ -799,9 +788,11 @@
 	}
 
-    // register stdin / stdout / stderr in the fd_array 3 first slots 
-	process_init->fd_array.array[0] = stdin_xp;
-	process_init->fd_array.array[1] = stdout_xp;
-	process_init->fd_array.array[2] = stderr_xp;
-    process_init->fd_array.current  = 3;
+    // check stdin / stdout / stderr indexes
+    if( (stdin_id != 0) || (stdout_id != 1) || (stderr_id != 2) )
+    {
+		printk("\n[PANIC] in %s : bad indexes for stdin/stdout/stderr in cluster %x\n",
+            __FUNCTION__ , local_cxy );
+        hal_core_sleep();
+    }
 
     // initialize the exec_info structure
