Index: trunk/kernel/mm/kcm.c
===================================================================
--- trunk/kernel/mm/kcm.c	(revision 20)
+++ trunk/kernel/mm/kcm.c	(revision 50)
@@ -3,5 +3,5 @@
  *
  * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
- *         Alain Greiner    (2016)
+ *         Alain Greiner    (2016,2017)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -41,36 +41,48 @@
 // It changes the page status if required.
 //////////////////////////////////////////////////////////////////////////////////////
-// @ kcm   : pointer on kcm allocator.
-// @ ptr   : pointer on active kcm page to use.
+// @ kcm      : pointer on kcm allocator.
+// @ kcm_page : pointer on active kcm page to use.
 /////////////////////////////////////////////////////////////////////////////////////
 static void * kcm_get_block( kcm_t      * kcm,
-                             kcm_page_t * page )
-{
-	assert( page->active , __FUNCTION__ , "kcm page should be active" );
+                             kcm_page_t * kcm_page )
+{
+	kcm_dmsg("\n[INFO] %s : enters for %s / page %x / count = %d / active = %d\n",
+	         __FUNCTION__ , kmem_type_str( kcm->type ) ,
+             (intptr_t)kcm_page , kcm_page->count , kcm_page->active );
+
+	assert( kcm_page->active , __FUNCTION__ , "kcm_page should be active" );
 
 	// get first block available
-	int32_t index = bitmap_ffs( page->bitmap , kcm->blocks_nr );
-
-	assert( (index != -1) , __FUNCTION__ , "kcm page should not be full" );
+	int32_t index = bitmap_ffs( kcm_page->bitmap , kcm->blocks_nr );
+
+	assert( (index != -1) , __FUNCTION__ , "kcm_page should not be full" );
 
 	// allocate block
-	bitmap_clear( page->bitmap , index );
-
-	// increase page refcount
-	page->refcount ++;
-
-	// change the page to busy no more free block in page
-	if( page->refcount >= kcm->blocks_nr )
-	{
-		page->active = 0;
-		list_unlink( &page->list);
+	bitmap_clear( kcm_page->bitmap , index );
+
+	// increase kcm_page count
+	kcm_page->count ++;
+
+	// change the kcm_page to busy if no more free block in page
+	if( kcm_page->count >= kcm->blocks_nr )
+	{
+        kcm_page->active = 0;
+		list_unlink( &kcm_page->list);
 		kcm->active_pages_nr --;
 
-		list_add_first( &kcm->busy_root , &page->list);
+		list_add_first( &kcm->busy_root , &kcm_page->list);
 		kcm->busy_pages_nr ++;
-		page->busy   = 1;
-	}
-
-	return (page->base + index * kcm->block_size );
+		kcm_page->busy = 1;
+	}
+
+    // compute return pointer
+    void * ptr = (void *)((intptr_t)kcm_page + CONFIG_KCM_SLOT_SIZE
+                 + (index * kcm->block_size) );
+
+	kcm_dmsg("\n[INFO] %s : allocated one block  %s / ptr = %x / page = %x / count = %d\n",
+	         __FUNCTION__ , kmem_type_str( kcm->type ) , (uint32_t)ptr ,
+             (intptr_t)kcm_page , kcm_page->count );
+
+	return ptr;
 
 }  // kcm_get_block()
@@ -78,5 +90,5 @@
 /////////////////////////////////////////////////////////////////////////////////////
 // This static function releases a previously allocated block.
-// It changes the page status if required.
+// It changes the kcm_page status if required.
 /////////////////////////////////////////////////////////////////////////////////////
 // @ kcm   : pointer on kcm allocator.
@@ -86,33 +98,36 @@
                             void  * ptr )
 {
-	kcm_page_t * page;
+	kcm_page_t * kcm_page;
 	uint32_t     index;
 
-	page = (kcm_page_t*)((intptr_t)ptr & CONFIG_PPM_PAGE_MASK);
-	index = ((uint8_t*)ptr - page->base) / kcm->block_size;
-
-	bitmap_set( page->bitmap , index );
-	page->refcount --;
+    // compute pointer on kcm_page from block pointer
+	kcm_page = (kcm_page_t*)((intptr_t)ptr & ~CONFIG_PPM_PAGE_MASK);
+
+    // compute block index from block pointer
+	index = ((uint8_t *)ptr - (uint8_t *)kcm_page - CONFIG_KCM_SLOT_SIZE) / kcm->block_size;
+
+	bitmap_set( kcm_page->bitmap , index );
+	kcm_page->count --;
 
 	// change the page to active if it was busy
-	if( page->busy )
-	{
-		page->busy = 0;
-		list_unlink( &page->list );
+	if( kcm_page->busy )
+	{
+		kcm_page->busy = 0;
+		list_unlink( &kcm_page->list );
 		kcm->busy_pages_nr --;
 
-		list_add_last( &kcm->active_root, &page->list );
+		list_add_last( &kcm->active_root, &kcm_page->list );
 		kcm->active_pages_nr ++;
-		page->active = 1;
-	}
-
-	// change the page to free if last block in active page
-	if( (page->active) && (page->refcount == 0) )
-	{
-		page->active = 0;
-		list_unlink( &page->list);
+		kcm_page->active = 1;
+	}
+
+	// change the kcm_page to free if last block in active page
+	if( (kcm_page->active) && (kcm_page->count == 0) )
+	{
+		kcm_page->active = 0;
+		list_unlink( &kcm_page->list);
 		kcm->active_pages_nr --;
 
-		list_add_first( &kcm->free_root , &page->list);
+		list_add_first( &kcm->free_root , &kcm_page->list);
 		kcm->free_pages_nr ++;
 	}
@@ -121,10 +136,10 @@
 /////////////////////////////////////////////////////////////////////////////////////
 // This static function allocates one page from PPM. It initializes
-// the KCM-page descriptor, and introduces the new page into freelist.
+// the kcm_page descriptor, and introduces the new kcm_page into freelist.
 /////////////////////////////////////////////////////////////////////////////////////
 static error_t freelist_populate( kcm_t * kcm )
 {
 	page_t     * page;
-	kcm_page_t * ptr;
+	kcm_page_t * kcm_page;
 	kmem_req_t   req;
 
@@ -143,18 +158,17 @@
 
 	// get page base address
-	ptr = ppm_page2base( page );
+	kcm_page = (kcm_page_t *)ppm_page2base( page );
 
 	// initialize KCM-page descriptor
-	bitmap_set_range( ptr->bitmap , 0 , kcm->blocks_nr );
-
-	ptr->busy          = 0;
-	ptr->active        = 0;
-	ptr->refcount      = 0;
-	ptr->base          = (uint8_t*)ptr + kcm->block_size;
-	ptr->kcm           = kcm;
-	ptr->page          = page;
+	bitmap_set_range( kcm_page->bitmap , 0 , kcm->blocks_nr );
+
+	kcm_page->busy          = 0;
+	kcm_page->active        = 0;
+	kcm_page->count      = 0;
+	kcm_page->kcm           = kcm;
+	kcm_page->page          = page;
 
 	// introduce new page in free-list
-	list_add_first( &kcm->free_root , &ptr->list );
+	list_add_first( &kcm->free_root , &kcm_page->list );
 	kcm->free_pages_nr ++;
 
@@ -170,5 +184,5 @@
 {
 	error_t      error;
-	kcm_page_t * page;
+	kcm_page_t * kcm_page;
 
 	// get a new page from PPM if freelist empty
@@ -179,10 +193,10 @@
 	}
 
-	// get first KCM page from freelist and change its status to active
-	page = LIST_FIRST( &kcm->free_root, kcm_page_t , list );
-	list_unlink( &page->list );
+	// get first KCM page from freelist and unlink it
+	kcm_page = LIST_FIRST( &kcm->free_root, kcm_page_t , list );
+	list_unlink( &kcm_page->list );
 	kcm->free_pages_nr --;
 
-	return page;
+	return kcm_page;
 
 } // freelist_get()
@@ -193,7 +207,7 @@
 	           uint32_t   type )
 {
-	uint32_t     blocks_nr;
-	uint32_t     block_size;
-	uint32_t     remaining;
+    // the kcm_page descriptor mut fit in the KCM slot
+    assert( (sizeof(kcm_page_t) <= CONFIG_KCM_SLOT_SIZE) ,
+             __FUNCTION__ , "KCM slot too small\n" );
 
 	// initialize lock
@@ -211,15 +225,14 @@
 	list_root_init( &kcm->active_root );
 
-	// initialize block size and number of blocks per page
-	block_size      = ARROUND_UP( kmem_type_size( type ) , 64 );
-	blocks_nr       = CONFIG_PPM_PAGE_SIZE / block_size;
-	remaining       = CONFIG_PPM_PAGE_SIZE % block_size;
-	blocks_nr       = (remaining >= sizeof(kcm_page_t)) ? blocks_nr : blocks_nr - 1;
-
-	kcm->blocks_nr  = blocks_nr;
+	// initialize block size 
+	uint32_t block_size = ARROUND_UP( kmem_type_size( type ) , CONFIG_KCM_SLOT_SIZE );
 	kcm->block_size = block_size;
 
+	// initialize number of blocks per page
+	uint32_t  blocks_nr = (CONFIG_PPM_PAGE_SIZE - CONFIG_KCM_SLOT_SIZE) / block_size;
+    kcm->blocks_nr = blocks_nr;
+
 	kcm_dmsg("\n[INFO] %s : KCM %s initialised / block_size = %d / blocks_nr = %d\n",
-	         __FUNCTION__ , kmem_type_str( type ) , block_size , blocks_nr );
+	         __FUNCTION__ , kmem_type_str( type ) , kcm->block_size , kcm->blocks_nr );
 
 }  // kcm_init()
@@ -228,5 +241,5 @@
 void kcm_destroy( kcm_t * kcm )
 {
-	kcm_page_t   * page;
+	kcm_page_t   * kcm_page;
 	list_entry_t * iter;
 
@@ -237,8 +250,8 @@
 	LIST_FOREACH( &kcm->free_root , iter )
 	{
-		page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );
+		kcm_page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );
 		list_unlink( iter );
 		kcm->free_pages_nr --;
-		ppm_free_pages( page->page );
+		ppm_free_pages( kcm_page->page );
 	}
 
@@ -246,8 +259,8 @@
 	LIST_FOREACH( &kcm->active_root , iter )
 	{
-		page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );
+		kcm_page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );
 		list_unlink( iter );
 		kcm->free_pages_nr --;
-		ppm_free_pages( page->page );
+		ppm_free_pages( kcm_page->page );
 	}
 
@@ -255,8 +268,8 @@
 	LIST_FOREACH( &kcm->busy_root , iter )
 	{
-		page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );
+		kcm_page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );
 		list_unlink( iter );
 		kcm->free_pages_nr --;
-		ppm_free_pages( page->page );
+		ppm_free_pages( kcm_page->page );
 	}
 
@@ -269,5 +282,5 @@
 void * kcm_alloc( kcm_t * kcm )
 {
-	kcm_page_t * page;
+	kcm_page_t * kcm_page;
 	void       * ptr = NULL;   // pointer on block
 
@@ -278,49 +291,50 @@
 	if( list_is_empty( &kcm->active_root ) )  // no active page => get one
 	{
-		kcm_dmsg("\n[INFO] %s : enters for type %s but no active page => get one\n",
-		         __FUNCTION__ , kmem_type_str( kcm->type ) );
-
 		// get a page from free list
-		page = freelist_get( kcm );
-		if( page == NULL ) return NULL;
+		kcm_page = freelist_get( kcm );
+
+		if( kcm_page == NULL ) return NULL;
 
 		// insert page in active list
-		list_add_first( &kcm->active_root , &page->list );
+		list_add_first( &kcm->active_root , &kcm_page->list );
 		kcm->active_pages_nr ++;
-		page->active = 1;
-	}
-	else                     // get first page from active list
-	{
-		kcm_dmsg("\n[INFO] %s : enters for type %s with an active page\n",
-		         __FUNCTION__ , kmem_type_str( kcm->type ) );
-
+	    kcm_page->active = 1;
+
+        kcm_dmsg("\n[INFO] %s : enters for type %s at cycle %d / new page = %x / count = %d\n",
+		         __FUNCTION__ , kmem_type_str( kcm->type ) , hal_time_stamp() ,
+                 (intptr_t)kcm_page , kcm_page->count );
+
+	}
+	else                                    // get first page from active list
+	{
 		// get page pointer from active list
-		page = (kcm_page_t *)LIST_FIRST( &kcm->active_root , kcm_page_t , list );
+		kcm_page = (kcm_page_t *)LIST_FIRST( &kcm->active_root , kcm_page_t , list );
+
+		kcm_dmsg("\n[INFO] %s : enters for type %s at cycle %d / page = %x / count = %d\n",
+		         __FUNCTION__ , kmem_type_str( kcm->type ) , hal_time_stamp() ,  
+                 (intptr_t)kcm_page , kcm_page->count );
 	}
 
 	// get a block from selected active page
 	// cannot fail, as an active page cannot be full...
-	ptr  = kcm_get_block( kcm , page );
+	ptr  = kcm_get_block( kcm , kcm_page );
 
 	// release lock
-	spinlock_unlock(&kcm->lock);
-
-	kcm_dmsg("\n[INFO] %s : allocated one block of type %s / ptr = %x\n",
-	         __FUNCTION__ , kmem_type_str( kcm->type ) , (uint32_t)ptr );
+	spinlock_unlock( &kcm->lock );
 
 	return ptr;
 
-}  // kcm_alloc()
+}  // end kcm_allo()
 
 ///////////////////////////
 void kcm_free( void * ptr )
 {
-	kcm_page_t * page;
+	kcm_page_t * kcm_page;
 	kcm_t      * kcm;
 
-	if( ptr == NULL ) return;
-
-	page = (kcm_page_t *)((intptr_t)ptr & CONFIG_PPM_PAGE_MASK);
-	kcm  = page->kcm;
+	assert( (ptr != NULL) , __FUNCTION__ , "pointer cannot be NULL" );
+
+	kcm_page = (kcm_page_t *)((intptr_t)ptr & ~CONFIG_PPM_PAGE_MASK);
+	kcm      = kcm_page->kcm;
 
 	// get lock
@@ -332,5 +346,6 @@
 	// release lock
 	spinlock_unlock( &kcm->lock );
-}
+
+}  // end kcm_free()
 
 ////////////////////////////
