Index: trunk/kernel/mm/ppm.c
===================================================================
--- trunk/kernel/mm/ppm.c	(revision 1)
+++ trunk/kernel/mm/ppm.c	(revision 7)
@@ -91,36 +91,46 @@
 static void ppm_free_pages_nolock( page_t * page )
 {
+	page_t   * buddy;            // searched buddy page descriptor
+	uint32_t   buddy_index;      // buddy page index
+	page_t   * current;          // current (merged) page descriptor
+	uint32_t   current_index;    // current (merged) page index
+	uint32_t   current_order;    // current (merget) page order
+
     ppm_t    * ppm         = &LOCAL_CLUSTER->ppm;
     page_t   * pages_tbl   = ppm->pages_tbl;
-    uint32_t   page_order  = page->order;
-    uint32_t   page_index  = (uint32_t)(page - ppm->pages_tbl);
-
-	page_t   * block;
-	uint32_t   block_index;
-	uint32_t   current_order;
-
-    // update page descriptor flag
+
+    // update released page descriptor flags
 	page_set_flag( page , PG_FREE );
 
-    // update free_lists
-	for( current_order = page_order ; current_order < CONFIG_PPM_MAX_ORDER ; current_order++ )
+    // search the buddy page descriptor
+    // - merge with current page descriptor if found
+    // - exit to release the current page descriptor if not found 
+    current       = page , 
+    current_index = (uint32_t)(page - ppm->pages_tbl);
+	for( current_order = page->order ; 
+         current_order < CONFIG_PPM_MAX_ORDER ;
+         current_order++ )
     {
-		block_index = page_index ^ (1 << current_order);
-		block = pages_tbl + block_index;
-    
-		if( page_is_flag( block , PG_FREE ) || (block->order != current_order) ) break;
-
-		list_unlink( &block->list );
+		buddy_index = current_index ^ (1 << current_order);
+		buddy       = pages_tbl + buddy_index;
+    
+		if( !page_is_flag( buddy , PG_FREE ) || (buddy->order != current_order) ) break;
+
+        // remove buddy from free list 
+		list_unlink( &buddy->list );
 		ppm->free_pages_nr[current_order] --;
         ppm->total_free_pages -= (1 << current_order);
     
-		block->order = 0;
-		page_index &= block_index;
-	}
-  
-	block        = pages_tbl + page_index;
-	block->order = current_order;
-
-	list_add_first( &ppm->free_pages_root[current_order] , &block->list );
+        // merge buddy with current
+		buddy->order = 0;
+		current_index &= buddy_index;
+	}
+  
+    // update merged page descriptor order
+	current        = pages_tbl + current_index;
+	current->order = current_order;
+
+    // insert current in free list
+	list_add_first( &ppm->free_pages_root[current_order] , &current->list );
 	ppm->free_pages_nr[current_order] ++;
     ppm->total_free_pages += (1 << current_order);
@@ -128,5 +138,5 @@
 }  // end ppm_free_pages_nolock()
 
-/////////////////////////////////
+//////////////////////////////
 void ppm_init( ppm_t    * ppm,
                uint32_t   pages_nr,        // total pages number
@@ -148,4 +158,8 @@
 		ppm->free_pages_nr[i] = 0;
 	}
+
+#if( CONFIG_PPM_DEBUG )
+ppm_print( ppm , "after reset" );
+#endif
   
     // initialize dirty_list as empty
@@ -166,25 +180,40 @@
 	// set pages numbers 
 	ppm->pages_nr      = pages_nr;
-    ppm->pages_offset  = pages_offset;
+    ppm->pages_offset  = reserved_pages;
 
     // initialises all page descriptors in pages_tbl[]
-    // TODO Peut-on accélérer ces monstrueuses boucle ? [AG]
 	for( i = 0 ; i < pages_nr ; i++ )
     { 
         page_init( &ppm->pages_tbl[i] );
+
+        // TODO optimisation : make only a partial init [AG]
+        // complete the initialisation when page is allocated [AG]
+        // ppm->pages_tbl[i].flags = 0;
     } 
 
-    // set PG_RESERVED flag for reserved pages (kernel code & pages_tbl[]) 
+    // - set PG_RESERVED flag for reserved pages (kernel code & pages_tbl[]) 
+    // - release all other pages to populate the free lists
 	for( i = 0 ; i < reserved_pages ; i++) 
     {
         page_set_flag( &ppm->pages_tbl[i] , PG_RESERVED );
     }
-
-    // initialise the free lists by releasing all non reserved pages
-	for( i = 0 ; i < pages_nr ; i++ )
-	{
-		page_t * page = &ppm->pages_tbl[i];
-		if( page_is_flag( page , PG_RESERVED) ) ppm_free_pages_nolock( page );
-	}
+	for( i = reserved_pages ; i < pages_nr ; i++ )
+	{
+	    ppm_free_pages_nolock( &ppm->pages_tbl[i] );
+
+        // TODO optimisation : decompose this enormous set of small pages
+        // to a set big pages with various order values
+	}
+
+    // check consistency
+    ppm_assert_order( ppm );
+
+    kinit_dmsg("\n[INFO] %s : done in cluster %x at cycle %d\n",
+               __FUNCTION__ , local_cxy , hal_time_stamp() );
+
+#if( CONFIG_PPM_DEBUG )
+ppm_print( ppm , "after init" );
+#endif
+    
 } // end ppm_init()
 
@@ -198,24 +227,21 @@
     ppm_t    * ppm = &LOCAL_CLUSTER->ppm;
 
-	if( ppm->signature != PPM_SIGNATURE )
-    {
-        printk("\n[PANIC] in %s : PPM non initialised in cluster %x\n",
-               __FUNCTION__ , local_cxy );
-        hal_core_sleep();
-    }
-
-	if( order >= CONFIG_PPM_MAX_ORDER )
-    {
-        printk("\n[PANIC] in %s : illegal order argument in cluster %x\n",
-               __FUNCTION__ , local_cxy );
-        hal_core_sleep();
-    }
+	assert( (ppm->signature == PPM_SIGNATURE) , __FUNCTION__ , "PPM non initialised" );
+
+	assert( (order < CONFIG_PPM_MAX_ORDER) , __FUNCTION__ , "illegal order argument" );
 
 	page_t * block = NULL;
+
+    ppm_dmsg("\n[INFO] %s : enters / order = %d\n",
+             __FUNCTION__ , order );
+
+#if( CONFIG_PPM_DEBUG )
+ppm_print( ppm , "before allocation" );
+#endif
 
     // take lock protecting free lists
 	spinlock_lock( &ppm->free_lock );
 
-    // find a block larger or equal to requested size
+    // find a free block equal or larger to requested size
 	for( current_order = order ; current_order < CONFIG_PPM_MAX_ORDER ; current_order ++ )
 	{
@@ -264,4 +290,11 @@
 	spinlock_unlock( &ppm->free_lock );
   
+    ppm_dmsg("\n[INFO] %s : base = %x / order = %d\n",
+             __FUNCTION__ , (uint32_t)ppm_page2base( block ) , order );
+
+#if CONFIG_PPM_DEBUG
+ppm_print( ppm , "after allocation" );
+#endif
+
 	return block;
 }  // end pmm_alloc-pages()
@@ -282,6 +315,7 @@
 }
 
-/////////////////////////////
-void ppm_print( ppm_t * ppm )
+////////////////////////////
+void ppm_print( ppm_t * ppm,
+                char  * string )
 {
 	uint32_t       order;
@@ -292,10 +326,10 @@
 	spinlock_lock( &ppm->free_lock );
 
-	printk("***  PPM state in cluster %x : pages = %d / offset = %d / free = %d ***\n",
-	       local_cxy , ppm->pages_nr , ppm->pages_offset , ppm->total_free_pages ); 
+	printk("\n***  PPM state in cluster %x %s : pages = %d / offset = %d / free = %d ***\n",
+	       local_cxy , string , ppm->pages_nr , ppm->pages_offset , ppm->total_free_pages ); 
 	
 	for( order = 0 ; order < CONFIG_PPM_MAX_ORDER ; order++ )
 	{
-		printk("- order = %d / free_pages = %d  [\n",
+		printk("- order = %d / free_pages = %d  [",
                order , ppm->free_pages_nr[order] );
 		
@@ -311,8 +345,9 @@
     // release lock protecting free lists
 	spinlock_unlock( &ppm->free_lock );
-}
-
-////////////////////////////////////////
-void ppm_assert_order(struct ppm_s *ppm)
+
+}  // end ppm_print()
+ 
+//////////////////////////u/////////
+void ppm_assert_order( ppm_t * ppm )
 {
 	uint32_t       order;
@@ -328,12 +363,8 @@
 			page = LIST_ELEMENT( iter , page_t , list );
 
-			if( page->order != order )
-            {
-	            printk("%s detected inconsistency at order %d, page %d\n", 
-	                   __FUNCTION__, order , page - ppm->pages_tbl );
-            }
+			assert( (page->order == order) , __FUNCTION__ , "PPM inconsistency" );
 		}
 	}
-	return;
-}
-
+
+}  // end ppm_assert_order()
+
