Index: trunk/kernel/kern/process.c
===================================================================
--- trunk/kernel/kern/process.c	(revision 408)
+++ trunk/kernel/kern/process.c	(revision 409)
@@ -8,5 +8,5 @@
  * Copyright (c) UPMC Sorbonne Universites
  *
- * This file is part of ALMOS-MKH..
+ * This file is part of ALMOS-MKH.
  *
  * ALMOS-MKH is free software; you can redistribute it and/or modify it
@@ -28,4 +28,5 @@
 #include <hal_remote.h>
 #include <hal_uspace.h>
+#include <hal_irqmask.h>
 #include <errno.h>
 #include <printk.h>
@@ -49,4 +50,5 @@
 #include <elf.h>
 #include <syscalls.h>
+#include <signal.h>
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -124,6 +126,6 @@
     uint32_t    stderr_id;
 
-process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x\n",
-__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
+process_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / ppid = %x\n",
+__FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid , ppid );
 
     // get model process cluster and local pointer
@@ -136,5 +138,5 @@
     process->ref_xp = XPTR( local_cxy , process );
 
-    // initialize vmm 
+    // initialize vmm as empty 
     vmm_init( process );
 
@@ -142,9 +144,9 @@
 __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
 
-    // initialize fd_array (not for kernel)
+    // initialize fd_array as empty
     process_fd_init( process );
 
     // create stdin / stdout / stderr pseudo-files
-    if( ppid == 0 )                                        // process_init
+    if( ppid == 0 )                                       // process_init
     {
         error1 = vfs_open( process,
@@ -169,5 +171,5 @@
                            &stderr_id );
     }
-    else                                                  // other user process
+    else                                                  // any other process
     {
         error1 = vfs_open( process,
@@ -199,21 +201,19 @@
     "bad indexes : stdin %d / stdout %d / stderr %d \n", stdin_id , stdout_id , stderr_id );
 
-    // initialize specific files, cwd_lock, and fd_array
+    // initialize specific inodes root and cwd
     process->vfs_root_xp = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
                                                          &model_ptr->vfs_root_xp ) );
     process->vfs_cwd_xp  = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
                                                          &model_ptr->vfs_cwd_xp ) );
-    process->vfs_bin_xp  = (xptr_t)hal_remote_lwd( XPTR( model_cxy,
-                                                         &model_ptr->vfs_bin_xp ) );
-    vfs_file_count_up( process->vfs_root_xp );
-    vfs_file_count_up( process->vfs_cwd_xp );
-    vfs_file_count_up( process->vfs_bin_xp );
-
+    vfs_inode_remote_up( process->vfs_root_xp );
+    vfs_inode_remote_up( process->vfs_cwd_xp );
+
+    remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
+
+    // copy all open file descriptors (other than stdin / stdout / stderr) 
     process_fd_remote_copy( XPTR( local_cxy , &process->fd_array ),
                             XPTR( model_cxy , &model_ptr->fd_array ) );
 
-    remote_rwlock_init( XPTR( local_cxy , &process->cwd_lock ) );
-
-process_dmsg("\n[DBG] %s : core[%x,%d] / fd array initialised for process %x\n", 
+process_dmsg("\n[DBG] %s : core[%x,%d] / fd array for process %x\n", 
 __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , pid );
 
@@ -352,12 +352,9 @@
     remote_spinlock_unlock( copies_lock );
 
-    // synchronize memory
 	hal_fence();
 
     // From this point, the process descriptor is unreachable
 
-    // close all open files and update dirty TODO [AG]
-
-    // release signal manager TODO [AG]
+    // FIXME close all open files and update dirty [AG]
 
     // Decrease refcount for bin file, root file and cwd file
@@ -374,77 +371,285 @@
 }  // end process_destroy()
 
+/////////////////////////////////////////////////
+char * process_action_str( uint32_t action_type )
+{
+    if     ( action_type == BLOCK_ALL_THREADS   ) return "BLOCK";
+    else if( action_type == UNBLOCK_ALL_THREADS ) return "UNBLOCK";
+    else if( action_type == DELETE_ALL_THREADS  ) return "DELETE";
+    else                                          return "undefined";
+}
+
+////////////////////////////////////////////
+void process_sigaction( process_t * process,
+                        uint32_t    action_type )
+{
+    cxy_t              owner_cxy;         // owner cluster identifier
+    lpid_t             lpid;              // process index in owner cluster
+    cluster_t        * cluster;           // pointer on cluster manager
+    xptr_t             root_xp;           // extended pointer on root of copies
+    xptr_t             lock_xp;           // extended pointer on lock protecting copies
+    xptr_t             client_xp;         // extended pointer on client thread
+    uint32_t           rsp_count;         // number of expected responses
+    xptr_t             rsp_xp;            // extended pointer on responses counter
+    xptr_t             iter_xp;           // iterator on copies list
+    xptr_t             process_xp;        // extended pointer on process copy
+    cxy_t              process_cxy;       // process copy cluster identifier
+    process_t        * process_ptr;       // local pointer on process copy
+
+signal_dmsg("\n[DBG] %s : enter for signal %s to process %x in cluster %x\n",
+__FUNCTION__ , process_action_str( action_type ) , process , local_cxy );
+
+    thread_t         * this = CURRENT_THREAD;
+
+    // get extended pointer on client thread and response counter
+    client_xp = XPTR( local_cxy , this );
+    rsp_xp    = XPTR( local_cxy , &rsp_count );
+
+    // get owner cluster identifier and process lpid
+    owner_cxy = CXY_FROM_PID( process->pid );
+    lpid      = LPID_FROM_PID( process->pid );
+
+    assert( (owner_cxy == local_cxy) , __FUNCTION__ , "illegal cluster\n" ); 
+   
+    // get local pointer on local cluster manager
+    cluster = LOCAL_CLUSTER;
+
+    // get extended pointers on copies root, copies lock, and number of copies
+    root_xp   = XPTR( local_cxy , &cluster->pmgr.copies_root[lpid] );
+    lock_xp   = XPTR( local_cxy , &cluster->pmgr.copies_lock[lpid] );
+
+    // initialize responses number 
+    rsp_count = cluster->pmgr.copies_nr[lpid];
+
+    // take the lock protecting the copies
+    remote_spinlock_lock( lock_xp );
+
+    // send RPCs to all process copies
+    XLIST_FOREACH( root_xp , iter_xp )
+    {
+        process_xp  = XLIST_ELEMENT( iter_xp , process_t , copies_list );
+        process_cxy = GET_CXY( process_xp );
+        process_ptr = (process_t *)GET_PTR( process_xp );
+
+printk("\n    @@@ %s : process = %x / pid = %x / ppid = %x\n",
+__FUNCTION__ , process_ptr , process_ptr->pid , process_ptr->ppid );
+
+        rpc_process_sigaction_client( process_cxy, 
+                                      process_ptr,
+                                      action_type,
+                                      rsp_xp,
+                                      client_xp );
+    }
+   
+    // release the lock protecting process copies
+    remote_spinlock_unlock( lock_xp );
+
+    // block and deschedule to wait response
+    thread_block( CURRENT_THREAD , THREAD_BLOCKED_RPC );
+    sched_yield("BLOCKED on RPC");
+
+signal_dmsg("\n[DBG] %s : exit for signal %s to process %x in cluster %x\n",
+__FUNCTION__ , process_action_str( action_type ) , process , local_cxy );
+
+}  // end process_sigaction()
+
 ////////////////////////////////////////
-void process_kill( process_t * process )
-{
-    thread_t     * thread;    // pointer on current thead descriptor
-    uint32_t       ltid;      // index in process th_tbl
-    uint32_t       count;     // thread counter
-
-printk("\n[@@@] %s enter\n", __FUNCTION__ );
-
-    // get lock protecting th_tbl[]
+void process_block( process_t * process,
+                    xptr_t      rsp_xp,
+                    xptr_t      client_xp )
+{
+    thread_t          * target;         // pointer on target thread 
+    uint32_t            ltid;           // index in process th_tbl
+    thread_t          * killer;         // killer thread pointer
+    uint32_t            count;          // requests counter
+    volatile uint32_t   sig_rsp_count;  // responses counter
+    cxy_t               client_cxy;     // client thread cluster identifier
+    thread_t          * client_ptr;     // client thread pointer
+    core_t            * client_core;    // client thread core pointer
+
+    // get local killer thread pointer
+    killer = CURRENT_THREAD;
+
+signal_dmsg("\n[DBG] %s : enter for process %x in cluster %x\n",
+__FUNCTION__ , process->pid , local_cxy );
+
+    // get lock protecting process th_tbl[]
     spinlock_lock( &process->th_lock );
 
-    // first loop on threads to send the THREAD_SIG_KILL signal to all process threads
-    // we use both "ltid" and "count" indexes, because it can exist "holes" in th_tbl
-    for( ltid = 0 , count = 0  ;
-         (ltid < CONFIG_THREAD_MAX_PER_CLUSTER) && (count < process->th_nr) ;
+    // initialize local responses counter 
+    sig_rsp_count = process->th_nr;
+
+    // loop on process threads to block and deschedule all threads in cluster
+    // we use both "ltid" and "count" because it can exist "holes" in th_tbl
+    for( ltid = 0 , count = 0 ; count < process->th_nr ; ltid++ )
+    {
+        target = process->th_tbl[ltid];
+
+        if( target != NULL )             // thread found
+        {
+            count++;
+
+            // set signal in target thread descriptor
+            thread_set_signal( target , (uint32_t *)sig_rsp_count );
+
+            // set the global blocked bit in target thread descriptor.
+            thread_block( target , THREAD_BLOCKED_GLOBAL );
+
+            // - if the killer thread and the target thread are not on the same core
+            //   we want the scheduler of target thread to acknowlege the signal
+            //   to be sure that the target thread is descheduled
+            // - if the killer thread and the target thread are on the same core
+            //   we simply decrement the response counter.
+            if( killer->core->lid != target->core->lid )
+            {
+                dev_pic_send_ipi( local_cxy , target->core->lid );
+            }
+            else                                                         
+            {
+                hal_atomic_add( (void *)&sig_rsp_count , -1 );
+            }
+        }
+    }
+
+    // poll the reponses counter 
+    while( 1 )
+    {
+        // exit loop when all responses received
+        if ( sig_rsp_count == 0 ) break;
+    
+        // wait 1000 cycles before retry
+        hal_fixed_delay( 1000 );
+    }
+
+    // acknowledge client thread & unblock client thread if last response
+    client_cxy  = GET_CXY( client_xp );
+    client_ptr  = (thread_t *)GET_PTR( client_xp );
+    client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );
+    if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 ) 
+    {
+        thread_unblock( client_xp , THREAD_BLOCKED_RPC);
+        dev_pic_send_ipi( client_cxy , client_core->lid );
+    }
+
+signal_dmsg("\n[DBG] %s : exit for process %x in cluster %x / %d threads blocked\n",
+__FUNCTION__ , process->pid , local_cxy , count );
+
+}  // end process_block()
+
+//////////////////////////////////////////
+void process_unblock( process_t * process,
+                      xptr_t      rsp_xp,
+                      xptr_t      client_xp )
+{
+    thread_t          * target;        // pointer on target thead 
+    uint32_t            ltid;          // index in process th_tbl
+    thread_t          * killer;        // killer thread pointer
+    uint32_t            req_count;     // requests counter
+    cxy_t               client_cxy;    // client thread cluster identifier
+    thread_t          * client_ptr;    // client thread pointer
+    core_t            * client_core;   // client thread core pointer
+
+    // get local killer thread pointer
+    killer = CURRENT_THREAD;
+
+signal_dmsg("\n[DBG] %s : enter for process %x in cluster %x\n",
+__FUNCTION__ , process->pid , local_cxy );
+
+    // get lock protecting process th_tbl[]
+    spinlock_lock( &process->th_lock );
+
+    // loop on process threads to unblock all threads in cluster
+    // we use both "ltid" and "req_count" because it can exist "holes" in th_tbl
+    for( ltid = 0 , req_count = 0 ;
+         req_count < process->th_nr ;
          ltid++ )
     {
+        target = process->th_tbl[ltid];
+
+        if( target != NULL )             // thread found
+        {
+            req_count++;
+
+            // reset the global blocked bit in target thread descriptor.
+            thread_unblock( XPTR( local_cxy , target ) , THREAD_BLOCKED_GLOBAL );
+        }
+    }
+
+    // acknowledge client thread & unblock client thread if last response
+    client_cxy  = GET_CXY( client_xp );
+    client_ptr  = (thread_t *)GET_PTR( client_xp );
+    client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );
+    if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 ) 
+    {
+        thread_unblock( client_xp , THREAD_BLOCKED_RPC);
+        dev_pic_send_ipi( client_cxy , client_core->lid );
+    }
+
+signal_dmsg("\n[DBG] %s : exit for process %x in cluster %x / %d threads blocked\n",
+__FUNCTION__ , process->pid , local_cxy , req_count );
+
+}  // end process_unblock()
+
+/////////////////////////////////////////
+void process_delete( process_t * process,
+                     xptr_t      rsp_xp,
+                     xptr_t      client_xp )
+{
+    thread_t          * thread;        // pointer on target thread 
+    uint32_t            ltid;          // index in process th_tbl
+    uint32_t            count;         // request counter
+    pid_t               pid;           // process PID
+    cxy_t               client_cxy;    // client thread cluster identifier
+    thread_t          * client_ptr;    // client thread pointer
+    core_t            * client_core;   // client thread core pointer
+
+    // get process PID
+    pid = process->pid;
+
+signal_dmsg("\n[DBG] %s : enter for process %x in cluster %x at cycle %d\n",
+__FUNCTION__ , pid , local_cxy , (uint32_t)hal_get_cycles() );
+
+    // loop on threads to release memory allocated to threads
+    for( ltid = 0 , count = 0  ; count < process->th_nr ; ltid++ )
+    {
         thread = process->th_tbl[ltid];
 
-        if( thread != NULL )
+        if( thread != NULL )             // thread found
         {
-            thread_kill( thread );
             count++;
+
+            // detach thread from parent if attached
+            if( (thread->flags & THREAD_FLAG_DETACHED) == 0 ) 
+            thread_child_parent_unlink( thread->parent , XPTR( local_cxy , thread ) );
+
+            // detach thread from process
+            process_remove_thread( thread );
+
+            // remove thread from scheduler
+            sched_remove_thread( thread );
+
+            // release memory allocated to thread
+            thread_destroy( thread );
         }
     }
 
-printk("\n[@@@] %s : %d signal(s) sent\n", __FUNCTION__, count );
-
-    // second loop on threads to wait acknowledge from scheduler,
-    // unlink thread from process and parent thread, and release thread descriptor
-    for( ltid = 0 , count = 0  ;
-         (ltid < CONFIG_THREAD_MAX_PER_CLUSTER) && (count < process->th_nr) ;
-         ltid++ )
-    {
-        thread = process->th_tbl[ltid];
-
-        if( thread != NULL )
-        {
-
-printk("\n[@@@] %s start polling at cycle %d\n", __FUNCTION__ , hal_time_stamp() );
-
-            // poll the THREAD_SIG_KILL bit until reset
-            while( thread->signals & THREAD_SIG_KILL ) asm volatile( "nop" );
-
-printk("\n[@@@] %s exit polling\n", __FUNCTION__ );
-
-            // detach target thread from parent if attached
-            if( (thread->flags & THREAD_FLAG_DETACHED) != 0 ) 
-            thread_child_parent_unlink( thread->parent , XPTR( local_cxy , thread ) );
-
-            // unlink thread from process
-            process_remove_thread( thread );
-
-            // release memory for thread descriptor
-            thread_destroy( thread );
-
-            count++;
-        }
-    }
-
-printk("\n[@@@] %s : %d ack(s) received\n", __FUNCTION__, count );
-
-    // release lock protecting th_tbl[]
-    spinlock_unlock( &process->th_lock );
-
-    // release memory allocated for process descriptor
-    process_destroy( process );
-
-printk("\n[DBG] %s : core[%x,%d] exit\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
-
-}  // end process_kill()
+    // release memory allocated to process descriptors
+    // for all clusters other than the owner cluster 
+    if( local_cxy != CXY_FROM_PID( process->pid ) ) process_destroy( process );
+
+    // acknowledge client thread & unblock client thread if last response
+    client_cxy  = GET_CXY( client_xp );
+    client_ptr  = (thread_t *)GET_PTR( client_xp );
+    client_core = (core_t *)hal_remote_lpt( XPTR( client_cxy , &client_ptr->core ) );
+    if( hal_remote_atomic_add( rsp_xp , -1 ) == 1 ) 
+    {
+        thread_unblock( client_xp , THREAD_BLOCKED_RPC);
+        dev_pic_send_ipi( client_cxy , client_core->lid );
+    }
+
+signal_dmsg("\n[DBG] %s : exit for process %x in cluster %x at cycle %d\n",
+__FUNCTION__ , pid , local_cxy , (uint32_t)hal_get_cycles() );
+
+}  // end process_delete()
 
 ///////////////////////////////////////////////
@@ -496,5 +701,6 @@
 
     return process_ptr;
-}
+
+}  // end process_get_local_copy()
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -621,6 +827,7 @@
 	remote_spinlock_lock( XPTR( src_cxy , &src_ptr->lock ) );
 
-    // loop on all entries in source process fd_array
-    for( fd = 0 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
+    // loop on all entries other than
+    // the three first entries: stdin/stdout/stderr
+    for( fd = 3 ; fd < CONFIG_PROCESS_FILE_MAX_NR ; fd++ )
 	{
 		entry = (xptr_t)hal_remote_lwd( XPTR( src_cxy , &src_ptr->array[fd] ) );
@@ -724,6 +931,6 @@
     "parent process must be the reference process\n" );
 
-process_dmsg("\n[DBG] %s : core[%x,%d] enter at cycle %d\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid , hal_get_cycles() );
+fork_dmsg("\n[DBG] %s : core[%x,%d] enter at cycle %d\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid , (uint32_t)hal_get_cycles() );
 
     // allocate a process descriptor
@@ -736,6 +943,6 @@
     }
 
-process_dmsg("\n[DBG] %s : core[%x,%d] child process descriptor allocated at cycle %d\n",
- __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
+fork_dmsg("\n[DBG] %s : core[%x,%d] child process descriptor allocated at cycle %d\n",
+ __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
 
     // allocate a child PID from local cluster
@@ -749,6 +956,6 @@
     }
 
-process_dmsg("\n[DBG] %s : core[%x, %d] child process PID allocated = %x at cycle %d\n",
- __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, new_pid , hal_get_cycles() );
+fork_dmsg("\n[DBG] %s : core[%x, %d] child process PID allocated = %x at cycle %d\n",
+ __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, new_pid , (uint32_t)hal_get_cycles() );
 
     // initializes child process descriptor from parent process descriptor 
@@ -758,5 +965,5 @@
                             parent_process_xp );
 
-process_dmsg("\n[DBG] %s : core[%x, %d] child process initialised at cycle %d\n",
+fork_dmsg("\n[DBG] %s : core[%x, %d] child process initialised at cycle %d\n",
 __FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
 
@@ -773,6 +980,6 @@
     }
 
-process_dmsg("\n[DBG] %s : core[%x, %d] child process VMM copied at cycle %d\n",
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
+fork_dmsg("\n[DBG] %s : core[%x, %d] child process VMM copied at cycle %d\n",
+__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
 
     // create child thread descriptor from parent thread descriptor
@@ -789,6 +996,6 @@
     }
 
-process_dmsg("\n[DBG] %s : core[%x,%d] child thread created at cycle %d\n", 
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
+fork_dmsg("\n[DBG] %s : core[%x,%d] child thread created at cycle %d\n", 
+__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
 
     // update parent process GPT to set Copy_On_Write for shared data vsegs 
@@ -804,6 +1011,6 @@
     }
 
-process_dmsg("\n[DBG] %s : core[%x,%d] COW set in parent_process at cycle %d\n",
-__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, hal_get_cycles() );
+fork_dmsg("\n[DBG] %s : core[%x,%d] COW set in parent_process at cycle %d\n",
+__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
 
     // update children list in parent process
@@ -821,7 +1028,12 @@
     *child_pid    = new_pid;
 
+fork_dmsg("\n[DBG] %s : core[%x,%d] exit at cycle %d\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, (uint32_t)hal_get_cycles() );
+
     return 0;
 
 }  // end process_make_fork()
+
+/*  deprecated because we don't wand to destroy the existing process descriptor
 
 /////////////////////////////////////////////////////
@@ -841,5 +1053,5 @@
     pid  = exec_info->pid;
 
-    // check local cluster is old process owner
+    // check local cluster is process owner
     assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
     "local cluster %x is not owner for process %x\n", local_cxy, pid );
@@ -876,6 +1088,6 @@
 	}
 
-exec_dmsg("\n[DBG] %s : core[%x,%d] registered code/data vsegs / process %x / path = %s\n",
-__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid, path );
+exec_dmsg("\n[DBG] %s : core[%x,%d] vsegs registered / path = %s\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
 
     // select a core in local cluster to execute the main thread
@@ -908,5 +1120,6 @@
                    XPTR( local_cxy , &new->brothers_list ) );
 
-    // FIXME request destruction of old process copies and threads in all clusters
+    // request destruction of old process copies and threads in all clusters
+    process_sigaction( old , SIGKILL );
 
     // activate new thread
@@ -920,14 +1133,169 @@
 }  // end process_make_exec()
 
+*/
+
+/////////////////////////////////////////////////////
+error_t process_make_exec( exec_info_t  * exec_info )
+{
+    char           * path;                    // pathname to .elf file
+    process_t      * process;                 // local pointer on old process
+    pid_t            pid;                     // old process identifier
+    thread_t       * thread;                  // pointer on new main thread
+    pthread_attr_t   attr;                    // main thread attributes
+    lid_t            lid;                     // selected core local index
+	error_t          error;
+
+	// get .elf pathname and PID from exec_info
+	path = exec_info->path;
+    pid  = exec_info->pid;
+
+    // check local cluster is process owner
+    assert( (CXY_FROM_PID( pid ) == local_cxy), __FUNCTION__,
+    "local cluster %x is not owner for process %x\n", local_cxy, pid );
+
+exec_dmsg("\n[DBG] %s : core[%x,%d] enters for process %x / path = %s\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, pid , path );
+
+    // get process local pointer
+    process = (process_t *)cluster_get_local_process_from_pid( pid );
+    
+    assert( (process != NULL ) , __FUNCTION__ , 
+    "process %x not found in cluster %x\n", pid , local_cxy ); 
+
+    // reset the existing vmm
+    vmm_destroy( process );
+
+exec_dmsg("\n[DBG] %s : core[%x,%d] VMM cleared\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
+
+    // block all existing process threads
+    process_sigaction( process , BLOCK_ALL_THREADS );
+
+    // kill all existing threads and process descriptors (other than owner)
+    process_sigaction( process , DELETE_ALL_THREADS );
+
+    // check no threads
+    assert( (process->th_nr == 0) , __FUNCTION__ , "no threads at this point" );
+
+exec_dmsg("\n[DBG] %s : core[%x,%d] all threads deleted\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid );
+
+    // re-initialize VMM 
+    vmm_init( process );
+
+    // register "code" and "data" vsegs as well as entry-point and vfs_bin_xp
+    // in VMM, using information contained in the elf file.
+	if( elf_load_process( path , process ) )
+	{
+		printk("\n[ERROR] in %s : failed to access .elf file for process %x / path = %s\n",
+		__FUNCTION__, pid , path );
+        process_destroy( process );
+        return -1;
+	}
+
+exec_dmsg("\n[DBG] %s : core[%x,%d] new vsegs registered / path = %s\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path );
+
+// @@@
+vmm_display( process , true );
+// @@@
+
+    // select a core in local cluster to execute the new main thread
+    lid  = cluster_select_local_core();
+
+    // initialize pthread attributes for new main thread
+    attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
+    attr.cxy        = local_cxy;
+    attr.lid        = lid;
+
+    // create and initialize thread descriptor
+	error = thread_user_create( pid,
+                                (void *)process->vmm.entry_point,
+                                exec_info->args_pointers,
+                                &attr,
+                                &thread );
+	if( error )
+	{
+		printk("\n[ERROR] in %s : cannot create thread for process %x / path = %s\n",
+		       __FUNCTION__, pid , path );
+        process_destroy( process );
+        return -1;
+	}
+
+exec_dmsg("\n[DBG] %s : core[%x,%d] created main thread %x for new process %x\n",
+__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid, thread->trdid, pid );
+
+    // activate new thread
+	thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
+
+exec_dmsg("\n[DBG] %s : core[%x,%d] exit for path = %s\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, path  );
+
+	return 0;
+
+}  // end process_make_exec()
+
+////////////////////////////////////////////
+void process_make_kill( process_t * process,
+                        uint32_t    sig_id )
+{
+    // this function must be executed by a thread running in owner cluster
+    assert( (CXY_FROM_PID( process->pid ) == local_cxy) , __FUNCTION__ ,
+    "must execute in owner cluster" );
+
+    // analyse signal type
+    switch( sig_id )
+    {
+        case SIGSTOP:     // block all threads
+        {
+            process_sigaction( process , BLOCK_ALL_THREADS );
+        }
+        break;
+        case SIGCONT:     // unblock all threads
+        {
+            process_sigaction( process , UNBLOCK_ALL_THREADS );
+        }
+        break;
+        case SIGKILL:  // block all threads, then delete all threads
+        {
+            process_sigaction( process , BLOCK_ALL_THREADS );
+            process_sigaction( process , DELETE_ALL_THREADS );
+            process_destroy( process );
+        }
+        break;
+    }
+}  // end process_make_kill()
+
+////////////////////////////////////////////
+void process_make_exit( process_t * process,
+                        uint32_t    status )
+{
+    // this function must be executed by a thread running in owner cluster
+    assert( (CXY_FROM_PID( process->pid ) == local_cxy) , __FUNCTION__ ,
+    "must execute in owner cluster" );
+
+    // block all threads in all clusters
+    process_sigaction( process , BLOCK_ALL_THREADS );
+
+    // delete all threads in all clusters
+    process_sigaction( process , DELETE_ALL_THREADS );
+
+    // delete local process descriptor
+    process_destroy( process ); 
+
+}  // end process_make_exit()
+
 //////////////////////////
 void process_init_create()
 {
-    exec_info_t   exec_info;     // structure to be passed to process_make_exec()
-    process_t   * process;       // local pointer on process_init descriptor
-    pid_t         pid;           // process_init identifier
-    error_t       error;
-
-process_dmsg("\n[DBG] %s : enters in cluster %x\n", 
-__FUNCTION__ , local_cxy );
+    process_t      * process;       // local pointer on process_init descriptor
+    pid_t            pid;           // process_init identifier
+    thread_t       * thread;        // local pointer on main thread
+    pthread_attr_t   attr;          // main thread attributes
+    lid_t            lid;           // selected core local index for main thread
+    error_t          error;
+
+kinit_dmsg("\n[DBG] %s :  core[%x,%d] enters\n", 
+__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid );
 
     // allocates memory for process descriptor from local cluster
@@ -936,8 +1304,8 @@
     {
 		printk("\n[PANIC] in %s : no memory for process descriptor in cluster %x\n",
-		__FUNCTION__, local_cxy );
-    }
-
-    // get new PID from local cluster
+		__FUNCTION__, local_cxy  );
+    }
+
+    // get PID from local cluster
     error = cluster_pid_alloc( XPTR( local_cxy , process ) , &pid );
     if( error )
@@ -945,32 +1313,59 @@
 		printk("\n[PANIC] in %s : cannot allocate PID in cluster %x\n",
 		__FUNCTION__, local_cxy );
-    }
-
-    // initialise the process desciptor (parent is local kernel process)
-    process_reference_init( process, 
+        process_destroy( process );
+    }
+
+    assert( (LPID_FROM_PID(pid) == 1) , __FUNCTION__ , "LPID must be 1 for process_init" );
+
+    // initialize process descriptor / parent is local process_zero
+    process_reference_init( process,
                             pid,
-                            process_zero.pid, 
+                            0,
                             XPTR( local_cxy , &process_zero ) );
 
-    // initialize the exec_info structure
-    exec_info.pid          = pid;
-    exec_info.args_nr      = 0;
-    exec_info.envs_nr      = 0;
-    strcpy( exec_info.path , CONFIG_PROCESS_INIT_PATH );
-
-    // update process descriptor and create thread descriptor
-	error = process_make_exec( &exec_info );
-
+kinit_dmsg("\n[DBG] %s : core[%x,%d] / process initialised\n", 
+__FUNCTION__ , local_cxy, CURRENT_THREAD->core->lid );
+
+    // register "code" and "data" vsegs as well as entry-point
+    // in process VMM, using information contained in the elf file.
+	if( elf_load_process( CONFIG_PROCESS_INIT_PATH , process ) )
+	{
+		printk("\n[PANIC] in %s : cannot access .elf file / path = %s\n",
+		__FUNCTION__, CONFIG_PROCESS_INIT_PATH );
+        process_destroy( process );
+	}
+
+kinit_dmsg("\n[DBG] %s : core[%x,%d] vsegs registered / path = %s\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, CONFIG_PROCESS_INIT_PATH );
+
+    // select a core in local cluster to execute the main thread
+    lid  = cluster_select_local_core();
+
+    // initialize pthread attributes for main thread
+    attr.attributes = PT_ATTR_DETACH | PT_ATTR_CLUSTER_DEFINED | PT_ATTR_CORE_DEFINED;
+    attr.cxy        = local_cxy;
+    attr.lid        = lid;
+
+    // create and initialize thread descriptor
+	error = thread_user_create( pid,
+                                (void *)process->vmm.entry_point,
+                                NULL,
+                                &attr,
+                                &thread );
 	if( error )
-    { 
-		printk("\n[PANIC] in %s : cannot exec %s in cluster %x\n",
-		__FUNCTION__, CONFIG_PROCESS_INIT_PATH , local_cxy );
-    }
-
-process_dmsg("\n[DBG] %s : exit in cluster %x\n", 
-__FUNCTION__ , local_cxy );
-		
+	{
+		printk("\n[PANIC] in %s : cannot create main thread / path = %s\n",
+		__FUNCTION__, CONFIG_PROCESS_INIT_PATH );
+        process_destroy( process );
+	}
+
+    // activate thread
+	thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_GLOBAL );
+
     hal_fence();
 
+kinit_dmsg("\n[DBG] %s : core[%x,%d] exit / main thread = %x\n",
+__FUNCTION__, local_cxy, CURRENT_THREAD->core->lid, thread );
+
 }  // end process_init_create()
 
