source: trunk/kernel/mm/kmem.c @ 14

Last change on this file since 14 was 14, checked in by alain, 8 years ago

Bugs fix.

File size: 9.0 KB
Line 
1/*
2 * kmem.c - kernel memory allocator implementation.
3 *
4 * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
5 *          Mohamed Lamine Karaoui (2015)
6 *          Alain Greiner (2016)
7 *
8 * Copyright (c) UPMC Sorbonne Universites
9 *
10 * This file is part of ALMOS-MKH.
11 *
12 * ALMOS-MKH is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; version 2.0 of the License.
15 *
16 * ALMOS-MKH is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26#include <kernel_config.h>
27#include <hal_types.h>
28#include <hal_special.h>
29#include <printk.h>
30#include <spinlock.h>
31#include <readlock.h>
32#include <memcpy.h>
33#include <khm.h>
34#include <ppm.h>
35#include <page.h>
36#include <cluster.h>
37#include <thread.h>
38#include <process.h>
39#include <chdev.h>
40#include <mapper.h>
41#include <vfs.h>
42#include <fatfs.h>
43#include <ramfs.h>
44#include <remote_sem.h>
45#include <remote_barrier.h>
46#include <mapper.h>
47#include <grdxt.h>
48#include <vseg.h>
49#include <kmem.h>
50
51///////////////////////////
52void kmem_print_kcm_table()
53{
54    uint32_t    index;
55    kcm_t     * kcm;
56    cluster_t * cluster = LOCAL_CLUSTER;
57
58    printk("\n    *** KCM Pointers Table ***\n");
59
60    for( index = 0 ; index < KMEM_TYPES_NR ; index++ )
61    {
62        kcm = cluster->kcm_tbl[index];
63        if( kcm != NULL )
64        {
65            if( index == kcm->type ) 
66            {
67                printk("     - KCM[%s] (at address %x) is OK\n",
68                       kmem_type_str( index ) , (intptr_t)kcm );
69            }
70            else 
71            {
72                printk("     - KCM[%s] (at address %x) is KO : has type %s\n",
73                       kmem_type_str( index ) , (intptr_t)kcm , kmem_type_str( kcm->type ) );
74            }           
75        }
76    }
77}  // end kmem_print_kcm_table()
78
79/////////////////////////////////////////
80uint32_t  kmem_type_size( uint32_t type )
81{
82    if     ( type == KMEM_PAGE )          return CONFIG_PPM_PAGE_SIZE;
83    else if( type == KMEM_GENERIC )       return 0;
84    else if( type == KMEM_KCM )           return sizeof( kcm_t );
85    else if( type == KMEM_VSEG )          return sizeof( vseg_t );
86    else if( type == KMEM_DEVICE )        return sizeof( chdev_t );
87    else if( type == KMEM_MAPPER )        return sizeof( mapper_t );
88    else if( type == KMEM_PROCESS )       return sizeof( process_t );
89    else if( type == KMEM_CPU_CTX )       return sizeof( hal_cpu_context_t );
90    else if( type == KMEM_FPU_CTX )       return sizeof( hal_fpu_context_t );
91
92    else if( type == KMEM_FATFS_INODE )   return sizeof( fatfs_inode_t );
93    else if( type == KMEM_FATFS_CTX )     return sizeof( fatfs_ctx_t );
94    else if( type == KMEM_RAMFS_INODE )   return sizeof( ramfs_inode_t );
95    else if( type == KMEM_RAMFS_CTX )     return sizeof( ramfs_ctx_t );
96    else if( type == KMEM_VFS_CTX )       return sizeof( vfs_ctx_t );
97    else if( type == KMEM_VFS_INODE )     return sizeof( vfs_inode_t );
98    else if( type == KMEM_VFS_DENTRY )    return sizeof( vfs_dentry_t );
99    else if( type == KMEM_VFS_FILE )      return sizeof( vfs_file_t );
100    else if( type == KMEM_SEM )           return sizeof( remote_sem_t );
101    else                                  return 0;
102} 
103
104/////////////////////////////////////
105char * kmem_type_str( uint32_t type )
106{
107    if     ( type == KMEM_PAGE )          return "KMEM_PAGE";
108    else if( type == KMEM_GENERIC )       return "KMEM_GENERIC";
109    else if( type == KMEM_KCM )           return "KMEM_KCM";
110    else if( type == KMEM_VSEG )          return "KMEM_VSEG";
111    else if( type == KMEM_DEVICE )        return "KMEM_DEVICE";
112    else if( type == KMEM_MAPPER )        return "KMEM_MAPPER";
113    else if( type == KMEM_PROCESS )       return "KMEM_PROCESS";
114    else if( type == KMEM_CPU_CTX )       return "KMEM_CPU_CTX";
115    else if( type == KMEM_FPU_CTX )       return "KMEM_FPU_CTX";
116
117    else if( type == KMEM_FATFS_INODE )   return "KMEM_FATFS_INODE";
118    else if( type == KMEM_FATFS_CTX )     return "KMEM_FATFS_CTX";
119    else if( type == KMEM_RAMFS_INODE )   return "KMEM_RAMFS_INODE";
120    else if( type == KMEM_RAMFS_CTX )     return "KMEM_RAMFS_CTX";
121    else if( type == KMEM_VFS_CTX )       return "KMEM_VFS_CTX";
122    else if( type == KMEM_VFS_INODE )     return "KMEM_VFS_INODE";
123    else if( type == KMEM_VFS_DENTRY )    return "KMEM_VFS_DENTRY"; 
124    else if( type == KMEM_VFS_FILE )      return "KMEM_VFS_FILE";
125    else if( type == KMEM_SEM )           return "KMEM_SEM";
126    else                                  return "undefined";
127}
128
129/////////////////////////////////////////////////////////////////////////////////////////////
130// This static function dynamically allocates and initializes a specific KCM allocator.
131// It uses the KCM allocator embedded in cluster manager, initialized by cluster_init().
132/////////////////////////////////////////////////////////////////////////////////////////////
133static error_t kmem_create_kcm( uint32_t type )
134{
135        kcm_t    * kcm;
136
137    assert( ((type > 1) && (type < KMEM_TYPES_NR) ) , __FUNCTION__ , "illegal KCM type" );
138
139        kmem_dmsg("\n[INFO] %s : enters / KCM type %s missing in cluster %x\n",
140                      __FUNCTION__ , kmem_type_str( type ) , local_cxy );
141
142    cluster_t * cluster = LOCAL_CLUSTER;
143
144    // allocates memory for the requested KCM allocator
145    // from the KCM allocator embedded in cluster descriptor
146        kcm = kcm_alloc( &cluster->kcm );
147
148        if( kcm == NULL )
149    {
150                printk("\n[ERROR] in %s : failed to create KCM type %d in cluster %x\n",
151               __FUNCTION__ , type , local_cxy );
152        return ENOMEM;
153    }
154
155    // initializes the new KCM allocator
156        kcm_init( kcm , type );
157
158    // register it if the KCM pointers Table
159        cluster->kcm_tbl[type] = kcm;
160
161        hal_wbflush();
162
163        kmem_dmsg("\n[INFO] %s : exit / KCM type %s created in cluster %x\n",
164                      __FUNCTION__ , kmem_type_str( type ) , local_cxy );
165
166        return 0;
167
168}  // end kmem_create_kcm()
169
170 
171
172/////////////////////////////////////
173void * kmem_alloc( kmem_req_t * req )
174{
175        cluster_t * cluster = LOCAL_CLUSTER;
176
177        uint32_t    type;
178        uint32_t    flags;
179        uint32_t    size;    // ln( pages ) if PPM / bytes if KHM / unused if KCM
180        void      * ptr;     // memory buffer if KHM or KCM / page descriptor if PPM
181
182
183        type  = req->type;
184        size  = req->size;
185        flags = req->flags;
186 
187        assert( (type < KMEM_TYPES_NR) , __FUNCTION__ , "illegal KMEM request type" );
188 
189        kmem_dmsg("\n[INFO] %s : enters in cluster %x for type %s / size %d\n",
190                      __FUNCTION__ , local_cxy , kmem_type_str( type ) , size );
191
192    // analyse request type
193        if( type ==  KMEM_PAGE )                       // PPM allocator
194    {       
195        // allocate the number of requested pages
196                ptr = (void *)ppm_alloc_pages( size );
197
198        // reset page if required
199                if( flags & AF_ZERO ) page_zero( (page_t *)ptr );
200   
201        kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / page = %x / base = %x\n",
202                  __FUNCTION__, local_cxy , kmem_type_str( type ) , 
203                  (intptr_t)ptr , (intptr_t)ppm_page2base( ptr ) );
204        }
205    else if( type == KMEM_GENERIC )                // KHM allocator
206    {
207        // allocate memory from KHM
208                ptr = khm_alloc( &cluster->khm , size );
209
210        // reset memory if requested
211                if( flags & AF_ZERO ) memset( ptr , 0 , size );
212
213        kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / base = %x\n",
214                  __FUNCTION__, local_cxy , kmem_type_str( type ) , (intptr_t)ptr );
215        }
216    else                                           // KCM allocator
217    {
218        // initialize the KCM allocator if not already done
219            if( cluster->kcm_tbl[type] == NULL )
220            { 
221            spinlock_lock( &cluster->kcm_lock );
222                        error_t error = kmem_create_kcm( type );
223            spinlock_unlock( &cluster->kcm_lock );
224            if ( error ) return NULL;
225            }
226
227        // allocate memory from KCM
228        ptr = kcm_alloc( cluster->kcm_tbl[type] );
229
230        // reset memory if requested
231                if( flags & AF_ZERO ) memset( ptr , 0 , kmem_type_size( type ) );
232
233        kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / base = %x\n",
234                  __FUNCTION__, local_cxy , kmem_type_str( type ) , (intptr_t)ptr );
235        }
236
237    if( ptr == NULL )
238    {
239            printk("\n[ERROR] in %s : failed for type %d / size %d in cluster %x\n", 
240               __FUNCTION__ , type , size , local_cxy );
241 
242            return NULL;
243    }
244
245        return ptr;
246
247} // end kmem_alloc()
248
249//////////////////////////////////
250void kmem_free( kmem_req_t * req )
251{
252        if( req->type >= KMEM_TYPES_NR )
253    {
254        printk("\n[PANIC] in %s : illegal request type\n", __FUNCTION__ );
255        hal_core_sleep();
256    }
257 
258        switch(req->type)
259        {
260            case KMEM_PAGE:
261                ppm_free_pages( (page_t*)req->ptr );
262                return;
263
264            case KMEM_GENERIC:
265            khm_free( req->ptr );
266                return;
267
268            default:
269                kcm_free( req->ptr );
270                return;
271        }
272}
273
274
Note: See TracBrowser for help on using the repository browser.