Index: trunk/kernel/mm/ppm.c
===================================================================
--- trunk/kernel/mm/ppm.c	(revision 551)
+++ trunk/kernel/mm/ppm.c	(revision 567)
@@ -3,5 +3,5 @@
  *
  * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
- *          Alain Greiner    (2016,2017)
+ *          Alain Greiner    (2016,2017,2018)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -30,11 +30,16 @@
 #include <bits.h>
 #include <page.h>
-#include <spinlock.h>
+#include <busylock.h>
+#include <queuelock.h>
 #include <thread.h>
 #include <cluster.h>
 #include <kmem.h>
 #include <process.h>
-#include <dqdt.h>
+#include <mapper.h>
 #include <ppm.h>
+
+////////////////////////////////////////////////////////////////////////////////////////
+//     functions to  translate [ page <-> base <-> ppn ]
+////////////////////////////////////////////////////////////////////////////////////////
 
 ////////////////////////////////////////////////
@@ -46,6 +51,4 @@
 }
 
-
-
 /////////////////////////////////////////////
 inline xptr_t ppm_page2base( xptr_t page_xp )
@@ -139,4 +142,7 @@
 
 
+////////////////////////////////////////////////////////////////////////////////////////
+//     functions to  allocate / release  physical pages 
+////////////////////////////////////////////////////////////////////////////////////////
 
 ///////////////////////////////////////////
@@ -204,6 +210,6 @@
 uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PPM_ALLOC_PAGES < cycle )
-printk("\n[DBG] in %s : thread %x enter for %d page(s) / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , 1<<order, cycle );
+printk("\n[DBG] in %s : thread %x in process %x enter for %d page(s) / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, 1<<order, cycle );
 #endif
 
@@ -221,6 +227,5 @@
 
 	// take lock protecting free lists
-	uint32_t       irq_state;
-	spinlock_lock_busy( &ppm->free_lock, &irq_state );
+	busylock_acquire( &ppm->free_lock );
 
 	// find a free block equal or larger to requested size
@@ -238,11 +243,11 @@
 	{
 		// release lock protecting free lists
-		spinlock_unlock_busy( &ppm->free_lock, irq_state );
+		busylock_release( &ppm->free_lock );
 
 #if DEBUG_PPM_ALLOC_PAGES
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PPM_ALLOC_PAGES < cycle )
-printk("\n[DBG] in %s : thread %x cannot allocate %d page(s) at cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , 1<<order, cycle );
+printk("\n[DBG] in %s : thread %x in process %x cannot allocate %d page(s) / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, 1<<order, cycle );
 #endif
 
@@ -274,11 +279,12 @@
 
 	// release lock protecting free lists
-	spinlock_unlock_busy( &ppm->free_lock, irq_state );
+	busylock_release( &ppm->free_lock );
 
 #if DEBUG_PPM_ALLOC_PAGES
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PPM_ALLOC_PAGES < cycle )
-printk("\n[DBG] in %s : thread %x exit / %d page(s) allocated / ppn = %x / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, 1<<order, ppm_page2ppn(XPTR( local_cxy , block )), cycle );
+printk("\n[DBG] in %s : thread %x in process %x exit for %d page(s) / ppn = %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, 
+1<<order, ppm_page2ppn(XPTR( local_cxy , block )), cycle );
 #endif
 
@@ -296,6 +302,7 @@
 uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PPM_FREE_PAGES < cycle )
-printk("\n[DBG] in %s : thread %x enter for %d page(s) / cycle %d\n",
-__FUNCTION__ , CURRENT_THREAD , 1<<page->order , cycle );
+printk("\n[DBG] in %s : thread %x in process %x enter for %d page(s) / ppn %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, 
+1<<page->order, ppm_page2ppn(XPTR(local_cxy , page)), cycle );
 #endif
 
@@ -306,21 +313,22 @@
 
 	// get lock protecting free_pages[] array
-	spinlock_lock( &ppm->free_lock );
+	busylock_acquire( &ppm->free_lock );
 
 	ppm_free_pages_nolock( page );
 
 	// release lock protecting free_pages[] array
-	spinlock_unlock( &ppm->free_lock );
+	busylock_release( &ppm->free_lock );
 
 #if DEBUG_PPM_FREE_PAGES
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_PPM_FREE_PAGES < cycle )
-printk("\n[DBG] in %s : thread %x exit / %d page(s) released / ppn = %x / cycle %d\n",
-__FUNCTION__, CURRENT_THREAD, 1<<page->order, ppm_page2ppn(XPTR(local_cxy , page)), cycle );
-#endif
-
-}
-
-////////////////
+printk("\n[DBG] in %s : thread %x in process %x exit for %d page(s) / ppn %x / cycle %d\n",
+__FUNCTION__, CURRENT_THREAD->trdid, CURRENT_THREAD->process->pid, 
+1<<page->order, ppm_page2ppn(XPTR(local_cxy , page)), cycle );
+#endif
+
+}  // end ppm_free_pages()
+
+//////////////////////
 void ppm_print( void )
 {
@@ -332,5 +340,5 @@
 
 	// get lock protecting free lists
-	spinlock_lock( &ppm->free_lock );
+	busylock_acquire( &ppm->free_lock );
 
 	printk("\n***  PPM in cluster %x : %d pages ***\n", local_cxy , ppm->pages_nr );
@@ -351,5 +359,5 @@
 
 	// release lock protecting free lists
-	spinlock_unlock( &ppm->free_lock );
+	busylock_release( &ppm->free_lock );
 }
 
@@ -368,5 +376,4 @@
 		{
 			page = LIST_ELEMENT( iter , page_t , list );
-
 			if( page->order != order )  return -1;
 		}
@@ -376,2 +383,86 @@
 }
 
+
+//////////////////////////////////////////////////////////////////////////////////////
+//     functions to handle  dirty physical pages
+//////////////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////
+bool_t ppm_page_do_dirty( page_t * page )
+{
+	bool_t done = false;
+
+	ppm_t * ppm = &LOCAL_CLUSTER->ppm;
+
+	// lock the PPM dirty_list
+	queuelock_acquire( &ppm->dirty_lock );
+
+	if( !page_is_flag( page , PG_DIRTY ) )
+	{
+		// set dirty flag in page descriptor
+		page_set_flag( page , PG_DIRTY );
+
+		// register page in PPM dirty list
+		list_add_first( &ppm->dirty_root , &page->list );
+		done = true;
+	}
+
+	// unlock the PPM dirty_list
+	queuelock_release( &ppm->dirty_lock );
+
+	return done;
+}
+
+///////////////////////////////////////////
+bool_t ppm_page_undo_dirty( page_t * page )
+{
+	bool_t done = false;
+
+	ppm_t * ppm = &LOCAL_CLUSTER->ppm;
+
+	// lock the dirty_list
+	queuelock_acquire( &ppm->dirty_lock );
+
+	if( page_is_flag( page , PG_DIRTY) )
+	{
+		// clear dirty flag in page descriptor
+		page_clear_flag( page , PG_DIRTY );
+
+		// remove page from PPM dirty list
+		list_unlink( &page->list );
+		done = true;
+	}
+
+	// unlock the dirty_list
+	queuelock_release( &ppm->dirty_lock );
+
+	return done;
+}
+
+///////////////////////////////
+void ppm_sync_all_pages( void )
+{
+	page_t   * page;
+	ppm_t    * ppm = &LOCAL_CLUSTER->ppm;
+
+	// get the PPM dirty_list lock
+	queuelock_acquire( &ppm->dirty_lock );
+
+	while( !list_is_empty( &ppm->dirty_root ) )
+	{
+		page = LIST_FIRST( &ppm->dirty_root ,  page_t , list );
+
+		// get the page lock
+		remote_busylock_acquire( XPTR( local_cxy, &page->lock ) );
+
+		// sync the page
+		vfs_mapper_move_page( page , false );  // from mapper
+
+		// release the page lock
+		remote_busylock_release( XPTR( local_cxy , &page->lock ) );
+	}
+
+	// release the PPM dirty_list lock
+	queuelock_release( &ppm->dirty_lock );
+}
+
