Index: trunk/kernel/mm/kmem.c
===================================================================
--- trunk/kernel/mm/kmem.c	(revision 690)
+++ trunk/kernel/mm/kmem.c	(revision 1)
@@ -2,5 +2,7 @@
  * kmem.c - kernel memory allocator implementation.
  *
- * Authors  Alain Greiner     (2016,2017,2018,2019,2020)
+ * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
+ *          Mohamed Lamine Karaoui (2015)
+ *          Alain Greiner (2016)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -22,191 +24,207 @@
  */
 
-#include <kernel_config.h>
-#include <hal_kernel_types.h>
+#include <almos_config.h>
+#include <hal_types.h>
 #include <hal_special.h>
 #include <printk.h>
+#include <spinlock.h>
+#include <readlock.h>
+#include <memcpy.h>
+#include <khm.h>
+#include <ppm.h>
+#include <page.h>
 #include <cluster.h>
 #include <thread.h>
-#include <memcpy.h>
-#include <ppm.h>
-#include <kcm.h>
-#include <page.h>
+#include <process.h>
+#include <device.h>
+#include <mapper.h>
+#include <vfs.h>
+#include <fatfs.h>
+#include <ramfs.h>
+#include <remote_sem.h>
+#include <remote_barrier.h>
+#include <mapper.h>
+#include <grdxt.h>
+#include <vseg.h>
 #include <kmem.h>
 
-///////////////////////////////////
-void * kmem_alloc( uint32_t  order,
-                   uint32_t  flags )
-{
-
-#if DEBUG_KMEM || DEBUG_KMEM_ERROR
-thread_t * this  = CURRENT_THREAD;
-uint32_t   cycle = (uint32_t)hal_get_cycles();
-#endif
-
-	if( order >= CONFIG_PPM_PAGE_ORDER )     // use PPM
+/////////////////////////////////////////////////////////////////////////////////////////////
+// This global array is indexed by the Kernel Memory Object Type (defined in kmem.h)
+// It contains the size of fixed size objects type dynamically allocated by the KCMs.
+// This array should be consistent with the enum defined kmem.h.
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+uint32_t  kmem_size_tbl[KMEM_TYPES_NR] =
+{
+    0,                        // 0  KMEM_PAGE is not a fixed size object
+    0,                        // 1  KMEM_GENERIC   
+    sizeof( kcm_t ),          // 2  KMEM_KCM
+    sizeof( vseg_t ),         // 3  KMEM_VSEG
+    sizeof( device_t ),       // 4  KMEM_DEVICE
+    sizeof( mapper_t ),       // 5  KMEM_MAPPER
+    sizeof( process_t ),      // 6  KMEM_PROCESS
+    0,                        // 7 
+    0,                        // 8  
+    0,                        // 9  
+
+    sizeof( fatfs_inode_t ),  // 10 KMEM_FATFS_INODE
+    sizeof( fatfs_ctx_t ),    // 11 KMEM_FATFS_CTX
+    sizeof( ramfs_inode_t ),  // 12 KMEM_RAMFS_INODE
+    sizeof( ramfs_ctx_t ),    // 13 KMEM_RAMFS_CTX
+    sizeof( vfs_ctx_t ),      // 14 KMEM_VFS_CTX
+    sizeof( vfs_inode_t ),    // 15 KMEM_VFS_INODE
+    sizeof( vfs_dentry_t ),   // 16 KMEM_VFS_DENTRY
+    sizeof( vfs_file_t ),     // 17 KMEM_VFS_FILE
+    sizeof( remote_sem_t ),   // 18 KMEM_SEM
+    0,                        // 19 
+
+    64,                       // 20 KMEM_64_BYTES
+    128,                      // 21 KMEM_128_BYTES
+    256,                      // 22 KMEM_256_BYTES
+    512,                      // 23 KMEM_512_BYTES
+    1024,                     // 24 KMEM_1024_BYTES
+    2048,                     // 25 KMEM_2048_BYTES
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// This static function dynamically allocates and initializes a specific KCM allocator.
+// It uses the KCM allocator embedded in cluster manager, initialized by cluster_init().
+/////////////////////////////////////////////////////////////////////////////////////////////
+static error_t kmem_get_kcm( uint32_t type )
+{
+	kcm_t    * kcm;
+	error_t    error;
+
+    // check kmem object type
+    if( (type < 2) || (type >= KMEM_TYPES_NR) )
+    {
+        printk("\n[PANIC] in %s illegal request type\n", __FUNCTION__ );
+        hal_core_sleep();
+    }
+
+    cluster_t * cluster = LOCAL_CLUSTER;
+
+    // allocates memory for the requested KCM allocator
+	kcm = kcm_alloc( &cluster->kcm );
+	if( kcm == NULL )
+    {
+		printk("\n[ERROR] in %s : failed to create KCM type %d in cluster %x\n",
+               __FUNCTION__ , type , local_cxy );
+        return ENOMEM;
+    }
+
+    // initializes the new KCM allocator 
+	error = kcm_init( kcm , type );
+
+	if( error )
 	{
-		// allocate memory from PPM
-		page_t * page = (void *)ppm_alloc_pages( order - CONFIG_PPM_PAGE_ORDER );
-
-		if( page == NULL )
-		{
-
-#if DEBUG_KMEM_ERROR
-if (DEBUG_KMEM_ERROR < cycle)
-printk("\n[ERROR] in %s : thread[%x,%x] failed for PPM / order %d / cluster %x / cycle %d\n",
-__FUNCTION__ , this->process->pid , this->trdid , order , local_cxy , cycle );
-#endif
-			return NULL;
-		}
-
-		// reset page if requested
-		if( flags & AF_ZERO ) page_zero( page );
-
-        // get pointer on buffer from the page descriptor
-        xptr_t page_xp = XPTR( local_cxy , page );
-        void * ptr     = GET_PTR( ppm_page2base( page_xp ) );
-
-#if DEBUG_KMEM
-if( (DEBUG_KMEM < cycle) && (DEBUG_KMEM_CXY == local_cxy) && (DEBUG_KMEM_ORDER == order) )
-printk("\n[%s] thread[%x,%x] from PPM / order %d / ppn %x / cxy %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid,
-order, ppm_page2ppn(XPTR(local_cxy,ptr)), local_cxy, cycle );
-#endif
-        return ptr;
-	}
-	else                                     // use KCM 
+		printk("\n[ERROR] in %s : failed to init KCM type %d\n",
+               __FUNCTION__ , type , local_cxy );
+		return error;
+	}
+
+	cluster->kcm_tbl[type] = kcm;
+	hal_wbflush();
+
+	return 0;
+}
+ 
+
+/////////////////////////////////////
+void * kmem_alloc( kmem_req_t * req )
+{
+	cluster_t * cluster = LOCAL_CLUSTER;
+
+	uint32_t    type;
+	uint32_t    size;    // ln( pages ) if PPM / bytes if KHM or BKM / unused if KCM
+	uint32_t    flags;
+	void      * ptr;     // local pointer on allocated memory buffer
+
+	type  = req->type;
+	size  = req->size;
+	flags = req->flags;
+  
+	kmem_dmsg("\n[INFO] %s in cluster %x : type %d, size %d, flags %x at cycle %d \n",
+		      __FUNCTION__, local_cxy , type, size, flags , hal_time_stamp() );
+
+	if( type >= KMEM_TYPES_NR )
+    {
+        printk("\n[PANIC] in %s illegal request type\n", __FUNCTION__ );
+        hal_core_sleep();
+    }
+  
+    // analyse request type
+	if( type ==  KMEM_PAGE )                       // PPM allocator
+    {        
+        // allocate the number of requested pages
+		ptr = (void*)ppm_alloc_pages( size );
+
+        // reset page if required
+		if( flags & AF_ZERO ) page_zero( (page_t*)ptr );
+	}
+    else if( type == KMEM_GENERIC )                // KHM allocator
+    {
+        // allocate memory from KHM
+		ptr = khm_alloc( &cluster->khm , size );
+
+        // reset memory if requested
+		if( flags & AF_ZERO ) memset( ptr , 0 , size );
+	}
+    else                                           // KCM allocator
+    {
+        uint32_t error = 0;
+
+        // initialize the KCM allocator if not already done
+	    if( cluster->kcm_tbl[type] == NULL )
+	    { 
+            spinlock_lock( &cluster->kcm_lock );
+			error = kmem_get_kcm( type );
+            spinlock_unlock( &cluster->kcm_lock );
+	    }
+
+        // allocate memory from KCM if success
+        if( error ) ptr = NULL;
+        else        ptr = kcm_alloc( cluster->kcm_tbl[type] );
+	}
+
+    if( ptr == NULL )
+    {
+	    printk("\n[ERROR] in %s : failed for type %d, size %d, flags %x in cluster %x\n", 
+	       __FUNCTION__ , type , size , flags , local_cxy );
+ 
+	    return NULL;
+    }
+
+	kmem_dmsg("\n[INFO] %s got ptr = %x in cluster %x at cycle %d\n",
+		  __FUNCTION__, (intptr_t)ptr , local_cxy , hal_time_stamp() );
+	    
+	return ptr;
+
+} // end kmem_alloc()
+
+//////////////////////////////////
+void kmem_free( kmem_req_t * req )
+{
+	if( req->type >= KMEM_TYPES_NR )
+    {
+        printk("\n[PANIC] in %s : illegal request type\n", __FUNCTION__ );
+        hal_core_sleep();
+    }
+  
+	switch(req->type)
 	{
-		// allocate memory from KCM
-		void * ptr = kcm_alloc( order );
-
-		if( ptr == NULL )
-		{
-
-#if DEBUG_KMEM_ERROR
-if (DEBUG_KMEM_ERROR < cycle)
-printk("\n[ERROR] in %s : thread[%x,%x] failed for KCM / order %d / cluster %x / cycle %d\n",
-__FUNCTION__ , this->process->pid , this->trdid , order , local_cxy , cycle );
-#endif
-			return NULL;
-		}
-
-		// reset memory if requested
-		if( flags & AF_ZERO ) memset( ptr , 0 , 1<<order );
-
-#if DEBUG_KMEM
-if( (DEBUG_KMEM < cycle) && (DEBUG_KMEM_CXY == local_cxy) && (DEBUG_KMEM_ORDER == order) )
-printk("\n[%s] thread [%x,%x] from KCM / order %d / base %x / cxy %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid,
-order, ptr, local_cxy, cycle ); 
-#endif
-        return ptr;
-	}
-}  // end kmem_alloc()
-
-//////////////////////////////
-void kmem_free( void    * ptr,
-                uint32_t  order )
-{
-	if( order >= CONFIG_PPM_PAGE_ORDER )     // use PPM
-	{
-        page_t * page = GET_PTR( ppm_base2page( XPTR( local_cxy , ptr ) ) );
-
-        ppm_free_pages( page );
-    }
-	else                                     // use KCM 
-    {
-        kcm_free( ptr , order );
-	}
-}  // end kmem_free()
-
-
-
-////////////////////////////////////////
-void * kmem_remote_alloc( cxy_t     cxy,
-                          uint32_t  order,
-                          uint32_t  flags )
-{
-
-#if DEBUG_KMEM || DEBUG_KMEM_ERROR
-thread_t * this = CURRENT_THREAD;
-uint32_t   cycle = (uint32_t)hal_get_cycles();
-#endif
-
-	if( order >= CONFIG_PPM_PAGE_ORDER )     // use PPM
-	{
-		// allocate memory from PPM
-		xptr_t page_xp = ppm_remote_alloc_pages( cxy , order - CONFIG_PPM_PAGE_ORDER );
-
-		if( page_xp == XPTR_NULL )
-		{
-
-#if DEBUG_KMEM_ERROR
-if( DEBUG_KMEM_ERROR < cycle )
-printk("\n[ERROR] in %s : thread[%x,%x] failed for PPM / order %d / cluster %x / cycle %d\n",
-__FUNCTION__ , this->process->pid , this->trdid , order , cxy , cycle );
-#endif
-			return NULL;
-		}
-
-        // get extended pointer on remote buffer
-        xptr_t base_xp = ppm_page2base( page_xp );
-
-		// reset memory if requested
-		if( flags & AF_ZERO ) hal_remote_memset( base_xp , 0 , 1<<order );
-
-#if DEBUG_KMEM
-if( (DEBUG_KMEM < cycle) && (DEBUG_KMEM_CXY == local_cxy) && (DEBUG_KMEM_ORDER == order) )
-printk("\n[%s] thread[%x,%x] from PPM / order %d / ppn %x / cxy %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid,
-order, ppm_page2ppn( page_xp ), cxy, cycle );
-#endif
-        return GET_PTR( base_xp );
-	}
-	else                                     // use KCM 
-	{
-		// allocate memory from KCM
-		void * ptr = kcm_remote_alloc( cxy , order );
-
-		if( ptr == NULL )
-		{
-
-#if DEBUG_KMEM_ERROR
-if( DEBUG_KMEM_ERROR < cycle )
-printk("\n[ERROR] in %s : thread[%x,%x] failed for KCM / order %d / cluster %x / cycle %d\n",
-__FUNCTION__ , this->process->pid , this->trdid , order , cxy , cycle );
-#endif
-			return NULL;
-		}
-
-		// reset memory if requested
-		if( flags & AF_ZERO )  hal_remote_memset( XPTR( cxy , ptr ) , 0 , 1<<order );
-
-#if DEBUG_KMEM
-if( (DEBUG_KMEM < cycle) && (DEBUG_KMEM_CXY == local_cxy) && (DEBUG_KMEM_ORDER == order) )
-printk("\n[%s] thread [%x,%x] from KCM / order %d / base %x / cxy %x / cycle %d\n",
-__FUNCTION__, this->process->pid, this->trdid,
-order, ptr, cxy, cycle );
-#endif
-        return ptr;
-	}
-}  // kmem_remote_malloc()
-
-/////////////////////////////////////
-void kmem_remote_free( cxy_t     cxy,
-                       void    * ptr,
-                       uint32_t  order )
-{
-	if( order >= CONFIG_PPM_PAGE_ORDER )     // use PPM
-	{
-        page_t * page = GET_PTR( ppm_base2page( XPTR( cxy , ptr ) ) );
-
-        ppm_remote_free_pages( cxy , page );
-    }
-	else                                     // use KCM 
-    {
-        kcm_remote_free( cxy , ptr , order );
-	}
-}  // end kmem_remote_free()
-
-
-
+	    case KMEM_PAGE:
+		ppm_free_pages( (page_t*)req->ptr );
+		return;
+
+	    case KMEM_GENERIC:
+	    khm_free( req->ptr );
+		return;
+
+	    default:
+		kcm_free( req->ptr );
+		return;
+	}
+}
+
+
