Index: trunk/kernel/mm/vmm.c
===================================================================
--- trunk/kernel/mm/vmm.c	(revision 457)
+++ trunk/kernel/mm/vmm.c	(revision 469)
@@ -411,4 +411,5 @@
                 page_t   * page_ptr;
                 xptr_t     forks_xp;
+                xptr_t     lock_xp;
 
                 // update flags in remote GPT 
@@ -433,9 +434,17 @@
                         if( attr & GPT_MAPPED )
                         {
+                            // get pointers and cluster on page descriptor
                             page_xp  = ppm_ppn2page( ppn );
                             page_cxy = GET_CXY( page_xp );
                             page_ptr = GET_PTR( page_xp );
+
+                            // get extended pointers on "forks" and "lock"
                             forks_xp = XPTR( page_cxy , &page_ptr->forks );
+                            lock_xp  = XPTR( page_cxy , &page_ptr->lock );
+
+                            // increment "forks"
+                            remote_spinlock_lock( lock_xp );
                             hal_remote_atomic_add( forks_xp , 1 );
+                            remote_spinlock_unlock( lock_xp );
                         }
                     }   // end loop on vpn
@@ -473,7 +482,9 @@
     vpn_t       vpn_base;
     vpn_t       vpn_size;
-    xptr_t      page_xp;
+    xptr_t      page_xp;        // extended pointer on page descriptor
     page_t    * page_ptr;
     cxy_t       page_cxy;
+    xptr_t      forks_xp;       // extended pointer on forks counter in page descriptor
+    xptr_t      lock_xp;        // extended pointer on lock protecting the forks counter
     xptr_t      parent_root_xp;
     bool_t      mapped; 
@@ -592,8 +603,17 @@
                     if( mapped )
                     {
-                        page_xp = ppm_ppn2page( ppn );
+                        // get pointers and cluster on page descriptor
+                        page_xp  = ppm_ppn2page( ppn );
                         page_cxy = GET_CXY( page_xp );
                         page_ptr = GET_PTR( page_xp );
-                        hal_remote_atomic_add( XPTR( page_cxy , &page_ptr->forks ) , 1 );
+
+                        // get extended pointers on "forks" and "lock"
+                        forks_xp = XPTR( page_cxy , &page_ptr->forks );
+                        lock_xp  = XPTR( page_cxy , &page_ptr->lock );
+
+                        // increment "forks"
+                        remote_spinlock_lock( lock_xp );
+                        hal_remote_atomic_add( forks_xp , 1 );
+                        remote_spinlock_unlock( lock_xp );
 
 #if DEBUG_VMM_FORK_COPY
@@ -603,5 +623,4 @@
 __FUNCTION__ , CURRENT_THREAD , vpn , cycle );
 #endif
-
                     }
                 }
@@ -670,5 +689,5 @@
 if( DEBUG_VMM_DESTROY < cycle )
 printk("\n[DBG] %s : thread %x enter for process %x in cluster %x / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , process->pid , local_cxy , cycle );
+__FUNCTION__, CURRENT_THREAD->trdid, process->pid, local_cxy, cycle );
 #endif
 
@@ -695,9 +714,4 @@
         vseg    = GET_PTR( vseg_xp );
 
-#if( DEBUG_VMM_DESTROY & 1 )
-if( DEBUG_VMM_DESTROY < cycle )
-printk("\n[DBG] %s : found %s vseg / vpn_base %x / vpn_size %d\n",
-__FUNCTION__ , vseg_type_str( vseg->type ), vseg->vpn_base, vseg->vpn_size );
-#endif
         // unmap and release physical pages 
         vmm_unmap_vseg( process , vseg );
@@ -751,5 +765,5 @@
 if( DEBUG_VMM_DESTROY < cycle )
 printk("\n[DBG] %s : thread %x exit for process %x in cluster %x / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , process->pid , local_cxy , cycle );
+__FUNCTION__, CURRENT_THREAD->trdid, process->pid, local_cxy , cycle );
 #endif
 
@@ -1069,5 +1083,6 @@
     page_t    * page_ptr;   // page descriptor pointer
     xptr_t      forks_xp;   // extended pointer on pending forks counter
-    uint32_t    count;      // actual number of pendinf forks
+    xptr_t      lock_xp;    // extended pointer on lock protecting forks counter
+    uint32_t    forks;      // actual number of pendinf forks
 
 #if DEBUG_VMM_UNMAP_VSEG
@@ -1115,12 +1130,16 @@
                 page_ptr = GET_PTR( page_xp );
 
-                // FIXME lock the physical page
+                // get extended pointers on forks and lock fields
+                forks_xp = XPTR( page_cxy , &page_ptr->forks );
+                lock_xp  = XPTR( page_cxy , &page_ptr->lock );
+
+                // get lock protecting page descriptor
+                remote_spinlock_lock( lock_xp );
 
                 // get pending forks counter
-                count = hal_remote_lw( XPTR( page_cxy , &page_ptr->forks ) );
+                forks = hal_remote_lw( forks_xp );
                 
-                if( count )  // decrement pending forks counter
+                if( forks )  // decrement pending forks counter
                 {
-                    forks_xp = XPTR( page_cxy , &page_ptr->forks );
                     hal_remote_atomic_add( forks_xp , -1 );
                 }  
@@ -1139,5 +1158,6 @@
                 }
 
-                // FIXME unlock the physical page
+                // release lock protecting page descriptor
+                remote_spinlock_unlock( lock_xp );
             }
         }
@@ -1418,6 +1438,5 @@
 #if DEBUG_VMM_GET_ONE_PPN 
 thread_t * this = CURRENT_THREAD;
-// if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
-if( (vpn == 0x403) && ((local_cxy == 0) || (this->type == THREAD_RPC)) )
+if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
 printk("\n[DBG] %s : thread %x enter for vpn = %x / type = %s / index = %d\n",
 __FUNCTION__, this, vpn, vseg_type_str(type), index );
@@ -1482,6 +1501,5 @@
 
 #if (DEBUG_VMM_GET_ONE_PPN & 0x1)
-if( (vpn == 0x403) && ((local_cxy == 0) || (this->type == THREAD_RPC)) )
-// if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
+if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
 printk("\n[DBG] %s : thread %x for vpn = %x / elf_offset = %x\n",
 __FUNCTION__, this, vpn, elf_offset );
@@ -1499,6 +1517,5 @@
 
 #if (DEBUG_VMM_GET_ONE_PPN & 0x1)
-// if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
-if( (vpn == 0x403) && ((local_cxy == 0) || (this->type == THREAD_RPC)) )
+if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
 printk("\n[DBG] %s : thread%x for vpn = %x / fully in BSS\n",
 __FUNCTION__, this, vpn );
@@ -1519,6 +1536,5 @@
 
 #if (DEBUG_VMM_GET_ONE_PPN & 0x1)
-// if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
-if( (vpn == 0x403) && ((local_cxy == 0) || (this->type == THREAD_RPC)) )
+if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
 printk("\n[DBG] %s : thread %x, for vpn = %x / fully in mapper\n",
 __FUNCTION__, this, vpn );
@@ -1551,6 +1567,5 @@
 
 #if (DEBUG_VMM_GET_ONE_PPN & 0x1)
-// if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
-if( (vpn == 0x403) && ((local_cxy == 0) || (this->type == THREAD_RPC)) )
+if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
 printk("\n[DBG] %s : thread %x for vpn = %x / both mapper & BSS\n"
 "      %d bytes from mapper / %d bytes from BSS\n",
@@ -1599,6 +1614,5 @@
 
 #if DEBUG_VMM_GET_ONE_PPN
-// if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
-if( (vpn == 0x403) && ((local_cxy == 0) || (this->type == THREAD_RPC)) )
+if( DEBUG_VMM_GET_ONE_PPN < (uint32_t)hal_get_cycles() )
 printk("\n[DBG] %s : thread %x exit for vpn = %x / ppn = %x\n",
 __FUNCTION__ , this , vpn , *ppn );
@@ -1628,8 +1642,7 @@
 #if DEBUG_VMM_GET_PTE
 uint32_t   cycle = (uint32_t)hal_get_cycles();
-// if( DEBUG_VMM_GET_PTE < cycle )
-if( (vpn == 0x403) && ((local_cxy == 0) || (this->type == THREAD_RPC)) )
-printk("\n[DBG] %s : thread %x enter / vpn %x / process %x / cow %d / cycle %d\n",
-__FUNCTION__ , this , vpn , process->pid , cow , cycle );
+if( DEBUG_VMM_GET_PTE < cycle )
+printk("\n[DBG] %s : thread %x in process %x enter / vpn %x / cow %d / cycle %d\n",
+__FUNCTION__, this->trdid, process->pid, vpn, cow, cycle );
 #endif
 
@@ -1644,6 +1657,6 @@
     // vseg has been checked by the vmm_handle_page_fault() function
     assert( (vseg != NULL) , __FUNCTION__,
-    "vseg undefined / vpn %x / thread %x / process %x / core[%x,%d] / cycle %d\n", 
-    vpn, this, process->pid, local_cxy, this->core->lid,
+    "vseg undefined / vpn %x / thread %x in process %x / core[%x,%d] / cycle %d\n", 
+    vpn, this->trdid, process->pid, local_cxy, this->core->lid,
     (uint32_t)hal_get_cycles() );
 
@@ -1658,12 +1671,11 @@
 
         assert( (old_attr & GPT_MAPPED), __FUNCTION__,
-        "PTE unmapped for a COW exception / vpn %x / thread %x / process %x / cycle %d\n",
+        "PTE unmapped for a COW exception / vpn %x / thread %x in process %x / cycle %d\n",
         vpn, this, process->pid, (uint32_t)hal_get_cycles() );
 
 #if( DEBUG_VMM_GET_PTE & 1 )
-// if( DEBUG_VMM_GET_PTE < cycle )
-if( (vpn == 0x403) && ((local_cxy == 0) || (this->type == THREAD_RPC)) )
-printk("\n[DBG] %s : thread %x handling COW for vpn %x in process %x\n",
-__FUNCTION__, this, vpn, process->pid );
+if( DEBUG_VMM_GET_PTE < cycle )
+printk("\n[DBG] %s : thread %x in process %x handling COW for vpn %x\n",
+__FUNCTION__, this->trdid, process->pid, vpn );
 #endif
 
@@ -1673,6 +1685,13 @@
         page_t * page_ptr = GET_PTR( page_xp );
 
+        // get extended pointers on forks and lock field in page descriptor
+        xptr_t forks_xp = XPTR( page_cxy , &page_ptr->forks );
+        xptr_t lock_xp  = XPTR( page_cxy , &page_ptr->lock );
+
+        // take lock protecting page descriptor
+        remote_spinlock_lock( lock_xp );
+
         // get number of pending forks in page descriptor
-        uint32_t forks = hal_remote_lw( XPTR( page_cxy , &page_ptr->forks ) );
+        uint32_t forks = hal_remote_lw( forks_xp );
 
         if( forks )        // pending fork => allocate a new page, copy old to new
@@ -1696,10 +1715,16 @@
                     GET_PTR( old_base_xp ),
                     CONFIG_PPM_PAGE_SIZE );
+
+             // decrement pending forks counter in page descriptor
+             hal_remote_atomic_add( forks_xp , -1 );
         }             
-        else               // no pending fork => keep the existing page, reset COW
+        else               // no pending fork => keep the existing page
         {
             new_ppn = old_ppn;
         }
 
+        // release lock protecting page descriptor
+        remote_spinlock_unlock( lock_xp );
+
         // build new_attr : reset COW and set WRITABLE,
         new_attr = (old_attr | GPT_WRITABLE) & (~GPT_COW);
@@ -1707,7 +1732,4 @@
         // update GPT[vpn] for all GPT copies
         vmm_global_update_pte( process, vpn, new_attr, new_ppn );
-
-        // decrement pending forks counter in page descriptor
-        hal_remote_atomic_add( XPTR( page_cxy , &page_ptr->forks ) , -1 );
     }
     else        //////////// page_fault request ///////////////////////////
@@ -1724,8 +1746,7 @@
 
 #if( DEBUG_VMM_GET_PTE & 1 )
-// if( DEBUG_VMM_GET_PTE < cycle )
-if( (vpn == 0x403) && ((local_cxy == 0) || (this->type == THREAD_RPC)) )
-printk("\n[DBG] %s : thread %x handling page fault for vpn %x in process %x\n",
-__FUNCTION__, this, vpn, process->pid );
+if( DEBUG_VMM_GET_PTE < cycle )
+printk("\n[DBG] %s : thread %x in process %x handling page fault for vpn %x\n",
+__FUNCTION__, this->trdid, process->pid, vpn );
 #endif
             // allocate new_ppn, and initialize the new page
@@ -1767,8 +1788,7 @@
 #if DEBUG_VMM_GET_PTE
 cycle = (uint32_t)hal_get_cycles();
-// if( DEBUG_VMM_GET_PTE < cycle )
-if( (vpn == 0x403) && (local_cxy == 0) )
-printk("\n[DBG] %s : thread %x exit / vpn %x in process %x / ppn %x / attr %x / cycle %d\n",
-__FUNCTION__, this, vpn, process->pid, new_ppn, new_attr, cycle );
+if( DEBUG_VMM_GET_PTE < cycle )
+printk("\n[DBG] %s : thread %x in process %x exit / vpn %x / ppn %x / attr %x / cycle %d\n",
+__FUNCTION__, this->trdid, process->pid, vpn, new_ppn, new_attr, cycle );
 #endif
 
@@ -1797,6 +1817,5 @@
 #if DEBUG_VMM_HANDLE_PAGE_FAULT
 uint32_t cycle = (uint32_t)hal_get_cycles();
-// if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
-if( (vpn == 0x403) && (local_cxy == 0) )
+if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
 printk("\n[DBG] %s : thread %x in process %x enter for vpn %x / core[%x,%d] / cycle %d\n",
 __FUNCTION__, this, process->pid, vpn, local_cxy, this->core->lid, cycle );
@@ -1836,6 +1855,5 @@
 
 #if DEBUG_VMM_HANDLE_PAGE_FAULT
-// if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
-if( (vpn == 0x403) && (local_cxy == 0) )
+if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
 printk("\n[DBG] %s : thread %x in process %x call RPC_VMM_GET_PTE\n",
 __FUNCTION__, this, process->pid );
@@ -1870,6 +1888,5 @@
 #if DEBUG_VMM_HANDLE_PAGE_FAULT
 cycle = (uint32_t)hal_get_cycles();
-// if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
-if( (vpn == 0x403) && (local_cxy == 0) )
+if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )
 printk("\n[DBG] %s : thread %x in process %x exit for vpn %x / core[%x,%d] / cycle %d\n",
 __FUNCTION__, this, process->pid, vpn, local_cxy, this->core->lid, cycle );
