Index: trunk/kernel/mm/vmm.c
===================================================================
--- trunk/kernel/mm/vmm.c	(revision 610)
+++ trunk/kernel/mm/vmm.c	(revision 611)
@@ -1,4 +1,4 @@
 /*
- * vmm.c - virtual memory manager related operations interface.
+ * vmm.c - virtual memory manager related operations definition.
  *
  * Authors   Ghassan Almaless (2008,2009,2010,2011, 2012)
@@ -254,7 +254,7 @@
 }  // vmm_display()
 
-///////////////////////////////////
-void vmm_vseg_attach( vmm_t  * vmm,
-                      vseg_t * vseg )
+//////////////////////////////////////////
+void vmm_attach_vseg_to_vsl( vmm_t  * vmm,
+                             vseg_t * vseg )
 {
     // build extended pointer on rwlock protecting VSL
@@ -275,8 +275,11 @@
 }
 
-///////////////////////////////////
-void vmm_vseg_detach( vmm_t  * vmm,
-                      vseg_t * vseg )
+////////////////////////////////////////////
+void vmm_detach_vseg_from_vsl( vmm_t  * vmm,
+                               vseg_t * vseg )
 {
+    // get vseg type
+    uint32_t type = vseg->type;
+
     // build extended pointer on rwlock protecting VSL
     xptr_t lock_xp = XPTR( local_cxy , &vmm->vsegs_lock );
@@ -288,10 +291,47 @@
     vseg->vmm = NULL;
 
-    // remove vseg from vmm list
+    // remove vseg from VSL
     xlist_unlink( XPTR( local_cxy , &vseg->xlist ) );
 
     // release rwlock in write mode
     remote_rwlock_wr_release( lock_xp );
-}
+
+    // release the stack slot to VMM stack allocator if STACK type
+    if( type == VSEG_TYPE_STACK )
+    {
+        // get pointer on stack allocator
+        stack_mgr_t * mgr = &vmm->stack_mgr;
+
+        // compute slot index
+        uint32_t index = ((vseg->vpn_base - mgr->vpn_base - 1) / CONFIG_VMM_STACK_SIZE);
+
+        // update stacks_bitmap
+        busylock_acquire( &mgr->lock );
+        bitmap_clear( &mgr->bitmap , index );
+        busylock_release( &mgr->lock );
+    }
+
+    // release the vseg to VMM mmap allocator if MMAP type
+    if( (type == VSEG_TYPE_ANON) || (type == VSEG_TYPE_FILE) || (type == VSEG_TYPE_REMOTE) )
+    {
+        // get pointer on mmap allocator
+        mmap_mgr_t * mgr = &vmm->mmap_mgr;
+
+        // compute zombi_list index
+        uint32_t index = bits_log2( vseg->vpn_size );
+
+        // update zombi_list
+        busylock_acquire( &mgr->lock );
+        list_add_first( &mgr->zombi_list[index] , &vseg->zlist );
+        busylock_release( &mgr->lock );
+    }
+
+    // release physical memory allocated for vseg descriptor if no MMAP type
+    if( (type != VSEG_TYPE_ANON) && (type != VSEG_TYPE_FILE) && (type != VSEG_TYPE_REMOTE) )
+    {
+        vseg_free( vseg );
+    }
+
+}  // end vmm_remove_vseg_from_vsl()
 
 ////////////////////////////////////////////////
@@ -616,5 +656,5 @@
 
             // register child vseg in child VSL
-            vmm_vseg_attach( child_vmm , child_vseg );
+            vmm_attach_vseg_to_vsl( child_vmm , child_vseg );
 
 #if DEBUG_VMM_FORK_COPY
@@ -759,5 +799,6 @@
     xptr_t   root_xp = XPTR( local_cxy , &vmm->vsegs_root );
 
-    // remove all user vsegs registered in VSL
+    // scan the VSL to delete all registered vsegs
+    // (don't use a FOREACH for item deletion in xlist)
 	while( !xlist_is_empty( root_xp ) )
 	{
@@ -766,16 +807,10 @@
         vseg    = GET_PTR( vseg_xp );
 
-        // unmap and release physical pages 
-        vmm_unmap_vseg( process , vseg );
-
-        // remove vseg from VSL
-		vmm_vseg_detach( vmm , vseg );
-
-        // release memory allocated to vseg descriptor
-        vseg_free( vseg );
+        // delete vseg and release physical pages 
+        vmm_delete_vseg( process->pid , vseg->min );
 
 #if( DEBUG_VMM_DESTROY & 1 )
 if( DEBUG_VMM_DESTROY < cycle )
-printk("\n[%s] %s vseg released / vpn_base %x / vpn_size %d\n",
+printk("\n[%s] %s vseg deleted / vpn_base %x / vpn_size %d\n",
 __FUNCTION__ , vseg_type_str( vseg->type ), vseg->vpn_base, vseg->vpn_size );
 #endif
@@ -796,5 +831,11 @@
 __FUNCTION__ , vseg_type_str( vseg->type ), vseg->vpn_base, vseg->vpn_size );
 #endif
-		    vmm_vseg_detach( vmm , vseg );
+            // clean vseg descriptor
+            vseg->vmm = NULL;
+
+            // remove vseg from  xlist
+            xlist_unlink( XPTR( local_cxy , &vseg->xlist ) );
+
+		    // release vseg descriptor
             vseg_free( vseg );
 
@@ -1079,5 +1120,5 @@
 
     // attach vseg to VSL
-	vmm_vseg_attach( vmm , vseg );
+	vmm_attach_vseg_to_vsl( vmm , vseg );
 
 #if DEBUG_VMM_CREATE_VSEG
@@ -1092,56 +1133,12 @@
 }  // vmm_create_vseg()
 
-/////////////////////////////////////
-void vmm_remove_vseg( vseg_t * vseg )
+///////////////////////////////////
+void vmm_delete_vseg( pid_t    pid,
+                      intptr_t vaddr )
 {
-    // get pointers on calling process and VMM
-    thread_t   * this    = CURRENT_THREAD;
-    vmm_t      * vmm     = &this->process->vmm;
-    uint32_t     type    = vseg->type;
-
-    // detach vseg from VSL
-	vmm_vseg_detach( vmm , vseg );
-
-    // release the stack slot to VMM stack allocator if STACK type
-    if( type == VSEG_TYPE_STACK )
-    {
-        // get pointer on stack allocator
-        stack_mgr_t * mgr = &vmm->stack_mgr;
-
-        // compute slot index
-        uint32_t index = ((vseg->vpn_base - mgr->vpn_base - 1) / CONFIG_VMM_STACK_SIZE);
-
-        // update stacks_bitmap
-        busylock_acquire( &mgr->lock );
-        bitmap_clear( &mgr->bitmap , index );
-        busylock_release( &mgr->lock );
-    }
-
-    // release the vseg to VMM mmap allocator if MMAP type
-    if( (type == VSEG_TYPE_ANON) || (type == VSEG_TYPE_FILE) || (type == VSEG_TYPE_REMOTE) )
-    {
-        // get pointer on mmap allocator
-        mmap_mgr_t * mgr = &vmm->mmap_mgr;
-
-        // compute zombi_list index
-        uint32_t index = bits_log2( vseg->vpn_size );
-
-        // update zombi_list
-        busylock_acquire( &mgr->lock );
-        list_add_first( &mgr->zombi_list[index] , &vseg->zlist );
-        busylock_release( &mgr->lock );
-    }
-
-    // release physical memory allocated for vseg descriptor if no MMAP type
-    if( (type != VSEG_TYPE_ANON) && (type != VSEG_TYPE_FILE) && (type != VSEG_TYPE_REMOTE) )
-    {
-        vseg_free( vseg );
-    }
-}  // end vmm_remove_vseg()
-
-/////////////////////////////////////////
-void vmm_unmap_vseg( process_t * process,
-                     vseg_t    * vseg )
-{
+    process_t * process;    // local pointer on local process 
+    vmm_t     * vmm;        // local pointer on local process VMM
+    vseg_t    * vseg;       // local pointer on local vseg containing vaddr
+    gpt_t     * gpt;        // local pointer on local process GPT
     vpn_t       vpn;        // VPN of current PTE
     vpn_t       vpn_min;    // VPN of first PTE
@@ -1157,17 +1154,27 @@
     uint32_t    forks;      // actual number of pendinf forks
 
-#if DEBUG_VMM_UNMAP_VSEG
+#if DEBUG_VMM_DELETE_VSEG
 uint32_t   cycle = (uint32_t)hal_get_cycles();
 thread_t * this  = CURRENT_THREAD;
-if( DEBUG_VMM_UNMAP_VSEG < cycle )
-printk("\n[%s] thread[%x,%x] enter / process %x / vseg %s / base %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, process->pid,
-vseg_type_str( vseg->type ), vseg->vpn_base, cycle );
-#endif
-
-    // get pointer on local GPT
-    gpt_t     * gpt = &process->vmm.gpt;
-
-    // loop on pages in vseg
+if( DEBUG_VMM_DELETE_VSEG < cycle )
+printk("\n[%s] thread[%x,%x] enter / process %x / vaddr %x / cycle %d\n",
+__FUNCTION__, this->process->pid, this->trdid, pid, vaddr, cycle );
+#endif
+
+    // get local pointer on local process descriptor
+    process = cluster_get_local_process_from_pid( pid );
+
+    if( process == NULL ) return;
+
+    // get pointers on local process VMM an GPT
+    vmm = &process->vmm;
+    gpt = &process->vmm.gpt;
+
+    // get local pointer on vseg containing vaddr
+    vseg = vmm_vseg_from_vaddr( vmm , vaddr );
+
+    if( vseg == NULL ) return;
+
+    // loop to invalidate all vseg PTEs in GPT
     vpn_min = vseg->vpn_base;
     vpn_max = vpn_min + vseg->vpn_size;
@@ -1180,7 +1187,7 @@
         { 
 
-#if( DEBUG_VMM_UNMAP_VSEG & 1 )
-if( DEBUG_VMM_UNMAP_VSEG < cycle )
-printk("- vpn %x / ppn %x\n" , vpn , ppn );
+#if( DEBUG_VMM_DELETE_VSEG & 1 )
+if( DEBUG_VMM_DELETE_VSEG < cycle )
+printk("- unmap vpn %x / ppn %x / vseg %s \n" , vpn , ppn, vseg_type_str(vseg->type) );
 #endif
 
@@ -1225,4 +1232,9 @@
                         rpc_pmem_release_pages_client( page_cxy , page_ptr );
                     }
+
+#if( DEBUG_VMM_DELETE_VSEG & 1 )
+if( DEBUG_VMM_DELETE_VSEG < cycle )
+printk("- release ppn %x\n", ppn );
+#endif
                 }
             }
@@ -1230,25 +1242,19 @@
     }
 
-#if DEBUG_VMM_UNMAP_VSEG
+    // remove vseg from VSL and release vseg descriptor (if not MMAP)
+    vmm_detach_vseg_from_vsl( vmm , vseg );
+
+#if DEBUG_VMM_DELETE_VSEG
 cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_VMM_UNMAP_VSEG < cycle )
+if( DEBUG_VMM_DELETE_VSEG < cycle )
 printk("\n[%s] thread[%x,%x] exit / process %x / vseg %s / base %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid, process->pid, 
-vseg_type_str( vseg->type ), vseg->vpn_base, cycle );
-#endif
-
-}  // end vmm_unmap_vseg()
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// This low-level static function is called by the vmm_get_vseg(), vmm_get_pte(),
-// and vmm_resize_vseg() functions.  It scan the local VSL to find the unique vseg 
-// containing a given virtual address.
-//////////////////////////////////////////////////////////////////////////////////////////
-// @ vmm     : pointer on the process VMM.
-// @ vaddr   : virtual address.
-// @ return vseg pointer if success / return NULL if not found.
-//////////////////////////////////////////////////////////////////////////////////////////
-static vseg_t * vmm_vseg_from_vaddr( vmm_t    * vmm,
-                                     intptr_t   vaddr )
+__FUNCTION__, this->process->pid, this->trdid, pid, vseg_type_str(vseg->type), vaddr, cycle );
+#endif
+
+}  // end vmm_delete_vseg()
+
+/////////////////////////////////////////////
+vseg_t * vmm_vseg_from_vaddr( vmm_t    * vmm,
+                              intptr_t   vaddr )
 {
     xptr_t   iter_xp;
@@ -1310,14 +1316,14 @@
 	remote_rwlock_wr_acquire( lock_xp );
 
-	if( (vseg->min > addr_min) || (vseg->max < addr_max) )   // region not included in vseg
-    {
-        error = EINVAL;
-    }
-	else if( (vseg->min == addr_min) && (vseg->max == addr_max) ) // vseg must be removed
-    {
-        vmm_remove_vseg( vseg );
+	if( (vseg->min > addr_min) || (vseg->max < addr_max) )        // not included in vseg
+    {
+        error = -1;
+    }
+	else if( (vseg->min == addr_min) && (vseg->max == addr_max) )  // vseg must be deleted
+    {
+        vmm_delete_vseg( process->pid , vseg->min );
         error = 0;
     }
-	else if( vseg->min == addr_min )                         // vseg must be resized
+	else if( vseg->min == addr_min )                               // vseg must be resized
     {
         // update vseg base address
@@ -1331,5 +1337,5 @@
         error = 0;
     }
-	else if( vseg->max == addr_max )                          // vseg must be resized
+	else if( vseg->max == addr_max )                              // vseg must be resized
     {
         // update vseg max address
@@ -1343,5 +1349,5 @@
         error = 0;
     }
-    else                                                      // vseg cut in three regions 
+    else                                                          // vseg cut in three regions 
     {
         // resize existing vseg
@@ -1415,6 +1421,6 @@
         vseg_init_from_ref( vseg , vseg_xp );
 
-        // register local vseg in local VMM
-        vmm_vseg_attach( vmm , vseg );
+        // register local vseg in local VSL
+        vmm_attach_vseg_to_vsl( vmm , vseg );
     }   
 
