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

Last change on this file since 176 was 159, checked in by max@…, 7 years ago

style

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 <remote_mutex.h>
47#include <remote_condvar.h>
48#include <mapper.h>
49#include <grdxt.h>
50#include <vseg.h>
51#include <kmem.h>
52
53///////////////////////////
54void kmem_print_kcm_table()
55{
56        uint32_t    index;
57        kcm_t     * kcm;
58        cluster_t * cluster = LOCAL_CLUSTER;
59
60        printk("\n    *** KCM Pointers Table ***\n");
61
62        for( index = 0 ; index < KMEM_TYPES_NR ; index++ )
63        {
64                kcm = cluster->kcm_tbl[index];
65                if( kcm != NULL )
66                {
67                        if( index == kcm->type )
68                        {
69                                printk("     - KCM[%s] (at address %x) is OK\n",
70                                       kmem_type_str( index ) , (intptr_t)kcm );
71                        }
72                        else
73                        {
74                                printk("     - KCM[%s] (at address %x) is KO : has type %s\n",
75                                       kmem_type_str( index ) , (intptr_t)kcm , kmem_type_str( kcm->type ) );
76                        }
77                }
78        }
79}
80
81/////////////////////////////////////////
82uint32_t  kmem_type_size( uint32_t type )
83{
84        if     ( type == KMEM_PAGE )          return CONFIG_PPM_PAGE_SIZE;
85        else if( type == KMEM_GENERIC )       return 0;
86        else if( type == KMEM_KCM )           return sizeof( kcm_t );
87        else if( type == KMEM_VSEG )          return sizeof( vseg_t );
88        else if( type == KMEM_DEVICE )        return sizeof( chdev_t );
89        else if( type == KMEM_MAPPER )        return sizeof( mapper_t );
90        else if( type == KMEM_PROCESS )       return sizeof( process_t );
91        else if( type == KMEM_CPU_CTX )       return sizeof( hal_cpu_context_t );
92        else if( type == KMEM_FPU_CTX )       return sizeof( hal_fpu_context_t );
93        else if( type == KMEM_BARRIER )       return sizeof( remote_barrier_t );
94
95        else if( type == KMEM_FATFS_INODE )   return sizeof( fatfs_inode_t );
96        else if( type == KMEM_FATFS_CTX )     return sizeof( fatfs_ctx_t );
97        else if( type == KMEM_DEVFS_INODE )   return sizeof( devfs_inode_t );
98        else if( type == KMEM_MUTEX )         return sizeof( remote_mutex_t );
99        else if( type == KMEM_VFS_CTX )       return sizeof( vfs_ctx_t );
100        else if( type == KMEM_VFS_INODE )     return sizeof( vfs_inode_t );
101        else if( type == KMEM_VFS_DENTRY )    return sizeof( vfs_dentry_t );
102        else if( type == KMEM_VFS_FILE )      return sizeof( vfs_file_t );
103        else if( type == KMEM_SEM )           return sizeof( remote_sem_t );
104        else if( type == KMEM_CONDVAR )       return sizeof( remote_condvar_t );
105
106        else if( type == KMEM_512_BYTES )     return 512;
107
108        else                                  return 0;
109}
110
111/////////////////////////////////////
112char * kmem_type_str( uint32_t type )
113{
114        if     ( type == KMEM_PAGE )          return "KMEM_PAGE";
115        else if( type == KMEM_GENERIC )       return "KMEM_GENERIC";
116        else if( type == KMEM_KCM )           return "KMEM_KCM";
117        else if( type == KMEM_VSEG )          return "KMEM_VSEG";
118        else if( type == KMEM_DEVICE )        return "KMEM_DEVICE";
119        else if( type == KMEM_MAPPER )        return "KMEM_MAPPER";
120        else if( type == KMEM_PROCESS )       return "KMEM_PROCESS";
121        else if( type == KMEM_CPU_CTX )       return "KMEM_CPU_CTX";
122        else if( type == KMEM_FPU_CTX )       return "KMEM_FPU_CTX";
123        else if( type == KMEM_BARRIER )       return "KMEM_BARRIER";
124
125        else if( type == KMEM_FATFS_INODE )   return "KMEM_FATFS_INODE";
126        else if( type == KMEM_FATFS_CTX )     return "KMEM_FATFS_CTX";
127        else if( type == KMEM_DEVFS_INODE )   return "KMEM_DEVFS_INODE";
128        else if( type == KMEM_MUTEX )         return "KMEM_MUTEX";
129        else if( type == KMEM_VFS_CTX )       return "KMEM_VFS_CTX";
130        else if( type == KMEM_VFS_INODE )     return "KMEM_VFS_INODE";
131        else if( type == KMEM_VFS_DENTRY )    return "KMEM_VFS_DENTRY";
132        else if( type == KMEM_VFS_FILE )      return "KMEM_VFS_FILE";
133        else if( type == KMEM_SEM )           return "KMEM_SEM";
134        else if( type == KMEM_SEM )           return "KMEM_CONDVAR";
135
136        else if( type == KMEM_512_BYTES )     return "KMEM_512_BYTES";
137
138        else                                  return "undefined";
139}
140
141/////////////////////////////////////////////////////////////////////////////////////////////
142// This static function dynamically allocates and initializes a specific KCM allocator.
143// It uses the KCM allocator embedded in cluster manager, initialized by cluster_init().
144/////////////////////////////////////////////////////////////////////////////////////////////
145static error_t kmem_create_kcm( uint32_t type )
146{
147        kcm_t    * kcm;
148
149        assert( ((type > 1) && (type < KMEM_TYPES_NR) ) , __FUNCTION__ , "illegal KCM type" );
150
151        kmem_dmsg("\n[INFO] %s : enters / KCM type %s missing in cluster %x\n",
152                  __FUNCTION__ , kmem_type_str( type ) , local_cxy );
153
154        cluster_t * cluster = LOCAL_CLUSTER;
155
156        // allocates memory for the requested KCM allocator
157        // from the KCM allocator embedded in cluster descriptor
158        kcm = kcm_alloc( &cluster->kcm );
159
160        if( kcm == NULL )
161        {
162                printk("\n[ERROR] in %s : failed to create KCM type %d in cluster %x\n",
163                       __FUNCTION__ , type , local_cxy );
164                return ENOMEM;
165        }
166
167        // initializes the new KCM allocator
168        kcm_init( kcm , type );
169
170        // register it if the KCM pointers Table
171        cluster->kcm_tbl[type] = kcm;
172
173        hal_fence();
174
175        kmem_dmsg("\n[INFO] %s : exit / KCM type %s created in cluster %x\n",
176                  __FUNCTION__ , kmem_type_str( type ) , local_cxy );
177
178        return 0;
179}
180
181/////////////////////////////////////
182void * kmem_alloc( kmem_req_t * req )
183{
184        cluster_t * cluster = LOCAL_CLUSTER;
185
186        uint32_t    type;
187        uint32_t    flags;
188        uint32_t    size;    // ln( pages ) if PPM / bytes if KHM / unused if KCM
189        void      * ptr;     // memory buffer if KHM or KCM / page descriptor if PPM
190
191
192        type  = req->type;
193        size  = req->size;
194        flags = req->flags;
195
196        assert( (type < KMEM_TYPES_NR) , __FUNCTION__ , "illegal KMEM request type" );
197
198        kmem_dmsg("\n[INFO] %s : enters in cluster %x for type %s\n",
199                      __FUNCTION__ , local_cxy , kmem_type_str( type ) );
200
201        // analyse request type
202        if( type ==  KMEM_PAGE )                       // PPM allocator
203        {
204                // allocate the number of requested pages
205                ptr = (void *)ppm_alloc_pages( size );
206
207                // reset page if requested
208                if( flags & AF_ZERO ) page_zero( (page_t *)ptr );
209
210                kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / page = %x / base = %x\n",
211                          __FUNCTION__, local_cxy , kmem_type_str( type ) ,
212                          (intptr_t)ptr , (intptr_t)ppm_page2base( ptr ) );
213        }
214        else if( type == KMEM_GENERIC )                // KHM allocator
215        {
216                // allocate memory from KHM
217                ptr = khm_alloc( &cluster->khm , size );
218
219                // reset memory if requested
220                if( flags & AF_ZERO ) memset( ptr , 0 , size );
221
222                kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / base = %x / size = %d\n",
223                          __FUNCTION__, local_cxy , kmem_type_str( type ) ,
224                          (intptr_t)ptr , req->size );
225        }
226        else                                           // KCM allocator
227        {
228                // initialize the KCM allocator if not already done
229                if( cluster->kcm_tbl[type] == NULL )
230                {
231                        spinlock_lock( &cluster->kcm_lock );
232                        error_t error = kmem_create_kcm( type );
233                        spinlock_unlock( &cluster->kcm_lock );
234                        if ( error ) return NULL;
235                }
236
237                // allocate memory from KCM
238                ptr = kcm_alloc( cluster->kcm_tbl[type] );
239
240                // reset memory if requested
241                if( flags & AF_ZERO ) memset( ptr , 0 , kmem_type_size( type ) );
242
243                kmem_dmsg("\n[INFO] %s : exit in cluster %x for type %s / base = %x / size = %d\n",
244                          __FUNCTION__, local_cxy , kmem_type_str( type ) ,
245                          (intptr_t)ptr , kmem_type_size( type ) );
246        }
247
248        if( ptr == NULL )
249        {
250                printk("\n[ERROR] in %s : failed for type %d / size %d in cluster %x\n",
251                   __FUNCTION__ , type , size , local_cxy );
252
253                return NULL;
254        }
255
256        return ptr;
257}
258
259//////////////////////////////////
260void kmem_free( kmem_req_t * req )
261{
262        if( req->type >= KMEM_TYPES_NR )
263        {
264                printk("\n[PANIC] in %s : illegal request type\n", __FUNCTION__ );
265                hal_core_sleep();
266        }
267
268        switch(req->type)
269        {
270                case KMEM_PAGE:
271                ppm_free_pages( (page_t*)req->ptr );
272                return;
273
274                case KMEM_GENERIC:
275                khm_free( req->ptr );
276                return;
277
278                default:
279                kcm_free( req->ptr );
280                return;
281        }
282}
283
Note: See TracBrowser for help on using the repository browser.