Index: trunk/kernel/kern/process.c
===================================================================
--- trunk/kernel/kern/process.c	(revision 441)
+++ trunk/kernel/kern/process.c	(revision 443)
@@ -135,4 +135,5 @@
 	process->pid        = pid;
     process->ref_xp     = XPTR( local_cxy , process );
+    process->owner_xp   = XPTR( local_cxy , process );
     process->parent_xp  = parent_xp;
     process->term_state = 0;
@@ -320,4 +321,5 @@
     local_process->parent_xp  = hal_remote_lwd( XPTR( ref_cxy , &ref_ptr->parent_xp ) );
     local_process->ref_xp     = reference_process_xp;
+    local_process->owner_xp   = reference_process_xp;
     local_process->term_state = 0;
 
@@ -409,5 +411,5 @@
     cluster_process_copies_unlink( process );
 
-    // remove process from children_list if process is in owner cluster
+    // remove process from children_list if process owner cluster
     if( CXY_FROM_PID( pid ) == local_cxy )
     {
@@ -426,5 +428,5 @@
     }
 
-    // release the process PID to cluster manager if owner cluster
+    // release the process PID to cluster manager if process owner cluster
     if( CXY_FROM_PID( pid ) == local_cxy ) cluster_pid_release( pid );
 
@@ -800,8 +802,10 @@
         // allocate memory for local process descriptor
         process_ptr = process_alloc();
+
         if( process_ptr == NULL )  return NULL;
 
         // initialize local process descriptor copy
         error = process_copy_init( process_ptr , ref_xp );
+
         if( error ) return NULL;
     }
@@ -1021,5 +1025,4 @@
     }
 
-
     // release lock protecting th_tbl
     hal_fence();
@@ -1030,7 +1033,9 @@
 }  // end process_register_thread()
 
-///////////////////////////////////////////////
-void process_remove_thread( thread_t * thread )
-{
+/////////////////////////////////////////////////
+bool_t process_remove_thread( thread_t * thread )
+{
+    uint32_t count;  // number of threads in local process descriptor
+
     assert( (thread != NULL) , __FUNCTION__ , "thread argument is NULL" );
 
@@ -1043,5 +1048,7 @@
     spinlock_lock( &process->th_lock );
 
-    assert( (process->th_nr) , __FUNCTION__ , "process th_nr cannot be 0\n" );
+    count = process->th_nr;
+
+    assert( (count > 0) , __FUNCTION__ , "process th_nr cannot be 0\n" );
 
     // remove thread from th_tbl[]
@@ -1049,8 +1056,9 @@
     process->th_nr--;
 
+    // release lock protecting th_tbl
     hal_fence();
-
-    // release lock protecting th_tbl
     spinlock_unlock( &process->th_lock );
+
+    return (count == 1);
 
 }  // process_remove_thread()
@@ -1401,4 +1409,5 @@
     process->pid        = 0;
     process->ref_xp     = XPTR( local_cxy , process );
+    process->owner_xp   = XPTR( local_cxy , process );
     process->parent_xp  = XPTR_NULL;
     process->term_state = 0;
@@ -1531,19 +1540,23 @@
     process_t   * process_ptr;
     cxy_t         process_cxy;
+
     xptr_t        parent_xp;       // extended pointer on parent process
     process_t   * parent_ptr;
     cxy_t         parent_cxy;
 
+    xptr_t        owner_xp;        // extended pointer on owner process
+    process_t   * owner_ptr;
+    cxy_t         owner_cxy;
+
     pid_t         pid;
     pid_t         ppid;
     uint32_t      state;
-    xptr_t        ref_xp; 
     uint32_t      th_nr;
 
-    xptr_t        txt_file_xp;     // extended pointer on TXT_RX pseudo file
-    xptr_t        chdev_xp;        // extended pointer on TXT_RX chdev
-    chdev_t     * chdev_ptr;
-    cxy_t         chdev_cxy;
-    xptr_t        owner_xp;        // extended pointer on TXT owner process 
+    xptr_t        txt_file_xp;     // extended pointer on TXT_RX file descriptor
+    xptr_t        txt_chdev_xp;    // extended pointer on TXT_RX chdev
+    chdev_t     * txt_chdev_ptr;
+    cxy_t         txt_chdev_cxy;
+    xptr_t        txt_owner_xp;    // extended pointer on TXT owner process 
 
     xptr_t        elf_file_xp;     // extended pointer on .elf file 
@@ -1558,8 +1571,4 @@
     process_ptr = GET_PTR( process_xp );
     process_cxy = GET_CXY( process_xp );
-
-    // check reference process
-    ref_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->ref_xp ) );
-    assert( (process_xp == ref_xp) , __FUNCTION__ , "process is not the reference\n");
 
     // get PID and state
@@ -1576,20 +1585,29 @@
     th_nr      = hal_remote_lw( XPTR( process_cxy , &process_ptr->th_nr ) );
 
-    // get TXT name and process owner
-    txt_file_xp = hal_remote_lwd( XPTR( process_cxy , &process_ptr->fd_array.array[0] ) );
+    // get pointers on owner process descriptor
+    owner_xp  = hal_remote_lwd( XPTR( process_cxy , &process_ptr->owner_xp ) );
+    owner_cxy = GET_CXY( owner_xp );
+    owner_ptr = GET_PTR( owner_xp );
+
+    // get extended pointer on TXT_RX file descriptor attached to process
+    txt_file_xp = hal_remote_lwd( XPTR( owner_cxy , &owner_ptr->fd_array.array[0] ) );
 
     assert( (txt_file_xp != XPTR_NULL) , __FUNCTION__ , 
     "process must be attached to one TXT terminal\n" ); 
 
-    chdev_xp  = chdev_from_file( txt_file_xp );
-    chdev_cxy = GET_CXY( chdev_xp );
-    chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
+    // get TXT_RX chdev pointers
+    txt_chdev_xp  = chdev_from_file( txt_file_xp );
+    txt_chdev_cxy = GET_CXY( txt_chdev_xp );
+    txt_chdev_ptr = GET_PTR( txt_chdev_xp );
+
+    // get TXT_RX name and ownership
     hal_remote_strcpy( XPTR( local_cxy , txt_name ) ,
-                           XPTR( chdev_cxy , chdev_ptr->name ) );
-    owner_xp = (xptr_t)hal_remote_lwd( XPTR( chdev_cxy , &chdev_ptr->ext.txt.owner_xp ) );
+                       XPTR( txt_chdev_cxy , txt_chdev_ptr->name ) );
+    
+    txt_owner_xp = (xptr_t)hal_remote_lwd( XPTR( txt_chdev_cxy, 
+                                                 &txt_chdev_ptr->ext.txt.owner_xp ) );
     
     // get process .elf name
     elf_file_xp   = hal_remote_lwd( XPTR( process_cxy , &process_ptr->vfs_bin_xp ) );
-
     elf_file_cxy  = GET_CXY( elf_file_xp );
     elf_file_ptr  = (vfs_file_t *)GET_PTR( elf_file_xp );
@@ -1598,12 +1616,12 @@
 
     // display process info
-    if( owner_xp == process_xp )
-    {
-        printk("PID %X | PPID %X | STS %X | %s (FG) | %X | %d | %s\n", 
+    if( txt_owner_xp == process_xp )
+    {
+        nolock_printk("PID %X | PPID %X | STS %X | %s (FG) | %X | %d | %s\n", 
         pid, ppid, state, txt_name, process_ptr, th_nr, elf_name );
     }
     else
     {
-        printk("PID %X | PPID %X | STS %X | %s (BG) | %X | %d | %s\n", 
+        nolock_printk("PID %X | PPID %X | STS %X | %s (BG) | %X | %d | %s\n", 
         pid, ppid, state, txt_name, process_ptr, th_nr, elf_name );
     }
@@ -1988,8 +2006,20 @@
     xptr_t      current_xp;
     xptr_t      iter_xp;
-
-    // check terminal index
+    cxy_t       txt0_cxy;
+    chdev_t   * txt0_ptr;
+    xptr_t      txt0_xp;
+    xptr_t      txt0_lock_xp;
+    reg_t       txt0_save_sr;    // save SR to take TXT0 lock in busy mode
+    
     assert( (txt_id < LOCAL_CLUSTER->nb_txt_channels) ,
     __FUNCTION__ , "illegal TXT terminal index" );
+
+    // get pointers on TXT0 chdev
+    txt0_xp  = chdev_dir.txt_tx[0];
+    txt0_cxy = GET_CXY( txt0_xp );
+    txt0_ptr = GET_PTR( txt0_xp );
+
+    // get extended pointer on TXT0 lock
+    txt0_lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
 
     // get pointers on TXT_RX[txt_id] chdev
@@ -2002,9 +2032,13 @@
     lock_xp = XPTR( chdev_cxy , &chdev_ptr->ext.txt.lock );
 
+    // get lock on attached process list
+    remote_spinlock_lock( lock_xp );
+
+    // get TXT0 lock in busy waiting mode
+    remote_spinlock_lock_busy( txt0_lock_xp , &txt0_save_sr );
+
     // display header
-    printk("\n***** processes attached to TXT_%d\n", txt_id );
-
-    // get lock
-    remote_spinlock_lock( lock_xp );
+    nolock_printk("\n***** processes attached to TXT_%d / cycle %d\n",
+    txt_id , (uint32_t)hal_get_cycles() );
 
     // scan attached process list 
@@ -2015,5 +2049,8 @@
     }
 
-    // release lock
+    // release TXT0 lock in busy waiting mode
+    remote_spinlock_unlock_busy( txt0_lock_xp , txt0_save_sr );
+
+    // release lock on attached process list
     remote_spinlock_unlock( lock_xp );
 
