Changeset 635 for trunk/kernel/mm/kmem.c
- Timestamp:
- Jun 26, 2019, 11:42:37 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/mm/kmem.c
r619 r635 2 2 * kmem.c - kernel memory allocator implementation. 3 3 * 4 * Authors Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016,2017,2018) 4 * Authors Alain Greiner (2016,2017,2018,2019) 6 5 * 7 6 * Copyright (c) UPMC Sorbonne Universites … … 27 26 #include <hal_special.h> 28 27 #include <printk.h> 29 #include < busylock.h>28 #include <cluster.h> 30 29 #include <memcpy.h> 31 30 #include <khm.h> 32 31 #include <ppm.h> 32 #include <kcm.h> 33 33 #include <page.h> 34 #include <cluster.h>35 #include <thread.h>36 #include <process.h>37 #include <chdev.h>38 #include <mapper.h>39 #include <vfs.h>40 #include <fatfs.h>41 #include <ramfs.h>42 #include <user_dir.h>43 #include <remote_sem.h>44 #include <remote_barrier.h>45 #include <remote_mutex.h>46 #include <remote_condvar.h>47 #include <mapper.h>48 #include <grdxt.h>49 #include <vseg.h>50 34 #include <kmem.h> 51 52 /////////////////////////////////53 void kmem_print_kcm_table( void )54 {55 uint32_t index;56 kcm_t * kcm;57 cluster_t * cluster = LOCAL_CLUSTER;58 59 printk("\n *** KCM Pointers Table ***\n");60 61 for( index = 0 ; index < KMEM_TYPES_NR ; index++ )62 {63 kcm = cluster->kcm_tbl[index];64 if( kcm != NULL )65 {66 if( index == kcm->type )67 {68 printk(" - KCM[%s] (at address %x) is OK\n",69 kmem_type_str( index ) , (intptr_t)kcm );70 }71 else72 {73 printk(" - KCM[%s] (at address %x) is KO : has type %s\n",74 kmem_type_str( index ) , (intptr_t)kcm , kmem_type_str( kcm->type ) );75 }76 }77 }78 }79 80 /////////////////////////////////////////81 uint32_t kmem_type_size( uint32_t type )82 {83 if ( type == KMEM_PAGE ) return CONFIG_PPM_PAGE_SIZE;84 else if( type == KMEM_GENERIC ) return 0;85 else if( type == KMEM_KCM ) return sizeof( kcm_t );86 else if( type == KMEM_VSEG ) return sizeof( vseg_t );87 else if( type == KMEM_DEVICE ) return sizeof( chdev_t );88 else if( type == KMEM_MAPPER ) return sizeof( mapper_t );89 else if( type == KMEM_PROCESS ) return sizeof( process_t );90 else if( type == KMEM_CPU_CTX ) return CONFIG_CPU_CTX_SIZE;91 else if( type == KMEM_FPU_CTX ) return CONFIG_FPU_CTX_SIZE;92 else if( type == KMEM_GEN_BARRIER ) return sizeof( generic_barrier_t );93 94 else if( type == KMEM_SMP_BARRIER ) return sizeof( simple_barrier_t );95 else if( type == KMEM_DEVFS_CTX ) return sizeof( fatfs_ctx_t );96 else if( type == KMEM_FATFS_CTX ) return sizeof( fatfs_ctx_t );97 else if( type == KMEM_VFS_CTX ) return sizeof( vfs_ctx_t );98 else if( type == KMEM_VFS_INODE ) return sizeof( vfs_inode_t );99 else if( type == KMEM_VFS_DENTRY ) return sizeof( vfs_dentry_t );100 else if( type == KMEM_VFS_FILE ) return sizeof( vfs_file_t );101 else if( type == KMEM_SEM ) return sizeof( remote_sem_t );102 else if( type == KMEM_CONDVAR ) return sizeof( remote_condvar_t );103 else if( type == KMEM_MUTEX ) return sizeof( remote_mutex_t );104 105 else if( type == KMEM_DIR ) return sizeof( user_dir_t );106 else if( type == KMEM_512_BYTES ) return 512;107 108 else return 0;109 }110 111 /////////////////////////////////////112 char * 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_GEN_BARRIER ) return "KMEM_GEN_BARRIER";124 125 else if( type == KMEM_SMP_BARRIER ) return "KMEM_SMP_BARRIER";126 else if( type == KMEM_DEVFS_CTX ) return "KMEM_DEVFS_CTX";127 else if( type == KMEM_FATFS_CTX ) return "KMEM_FATFS_CTX";128 else if( type == KMEM_VFS_CTX ) return "KMEM_VFS_CTX";129 else if( type == KMEM_VFS_INODE ) return "KMEM_VFS_INODE";130 else if( type == KMEM_VFS_DENTRY ) return "KMEM_VFS_DENTRY";131 else if( type == KMEM_VFS_FILE ) return "KMEM_VFS_FILE";132 else if( type == KMEM_SEM ) return "KMEM_SEM";133 else if( type == KMEM_CONDVAR ) return "KMEM_CONDVAR";134 else if( type == KMEM_MUTEX ) return "KMEM_MUTEX";135 136 else if( type == KMEM_DIR ) return "KMEM_DIR";137 else if( type == KMEM_512_BYTES ) return "KMEM_512_BYTES";138 139 else return "undefined";140 }141 142 /////////////////////////////////////////////////////////////////////////////////////////////143 // This static function dynamically allocates and initializes a specific KCM allocator.144 // It uses the KCM allocator embedded in cluster manager, initialized by cluster_init().145 /////////////////////////////////////////////////////////////////////////////////////////////146 static error_t kmem_create_kcm( uint32_t type )147 {148 kcm_t * kcm;149 150 assert( ((type > 1) && (type < KMEM_TYPES_NR) ) , "illegal KCM type" );151 152 #if DEBUG_KMEM153 thread_t * this = CURRENT_THREAD;154 uint32_t cycle = (uint32_t)hal_get_cycles();155 if( DEBUG_KMEM < cycle )156 printk("\n[%s] thread[%x,%x] enter / KCM type %s missing in cluster %x / cycle %d\n",157 __FUNCTION__, this->process->pid, this->trdid, kmem_type_str( type ), local_cxy, cycle );158 #endif159 160 cluster_t * cluster = LOCAL_CLUSTER;161 162 // allocate memory for the requested KCM allocator163 // from the KCM allocator embedded in cluster descriptor164 kcm = kcm_alloc( &cluster->kcm );165 166 if( kcm == NULL )167 {168 printk("\n[ERROR] in %s : failed to create KCM type %d in cluster %x\n",169 __FUNCTION__ , type , local_cxy );170 return ENOMEM;171 }172 173 // initialize the new KCM allocator174 kcm_init( kcm , type );175 176 // register it in the KCM pointers Table177 cluster->kcm_tbl[type] = kcm;178 179 hal_fence();180 181 #if DEBUG_KMEM182 cycle = (uint32_t)hal_get_cycles();183 if( DEBUG_KMEM < cycle )184 printk("\n[%s] thread[%x,%x] exit / cycle %d\n",185 __FUNCTION__, this->process->pid, this->trdid, cycle );186 #endif187 188 return 0;189 }190 35 191 36 ///////////////////////////////////// 192 37 void * kmem_alloc( kmem_req_t * req ) 193 38 { 194 cluster_t * cluster = LOCAL_CLUSTER; 195 196 uint32_t type; 197 uint32_t flags; 198 uint32_t size; // ln( pages ) if PPM / bytes if KHM / unused if KCM 199 void * ptr; // memory buffer if KHM or KCM / page descriptor if PPM 39 uint32_t type; // KMEM_PPM / KMEM_KCM / KMEM_KHM 40 uint32_t flags; // AF_NONE / AF_ZERO / AF_KERNEL 41 uint32_t order; // PPM: ln(pages) / KCM: ln(bytes) / KHM: bytes 200 42 201 43 type = req->type; 202 size = req->size;44 order = req->order; 203 45 flags = req->flags; 204 46 205 assert( (type < KMEM_TYPES_NR) , "illegal KMEM request type" ); 47 ////////////////////////////////// PPM 48 if( type == KMEM_PPM ) 49 { 50 // allocate the number of requested pages 51 page_t * page_ptr = (void *)ppm_alloc_pages( order ); 52 53 if( page_ptr == NULL ) 54 { 55 printk("\n[ERROR] in %s : PPM failed / order %d / cluster %x\n", 56 __FUNCTION__ , order , local_cxy ); 57 return NULL; 58 } 59 60 xptr_t page_xp = XPTR( local_cxy , page_ptr ); 61 62 // reset page if requested 63 if( flags & AF_ZERO ) page_zero( page_ptr ); 64 65 // get pointer on buffer from the page descriptor 66 void * ptr = GET_PTR( ppm_page2base( page_xp ) ); 206 67 207 68 #if DEBUG_KMEM 208 thread_t * this = CURRENT_THREAD;209 uint32_t cycle = (uint32_t)hal_get_cycles();69 thread_t * this = CURRENT_THREAD; 70 uint32_t cycle = (uint32_t)hal_get_cycles(); 210 71 if( DEBUG_KMEM < cycle ) 211 printk("\n[%s] thread [%x,%x] enter / %s / size %d / cluster %x / cycle %d\n", 72 printk("\n[%s] thread[%x,%x] from PPM / %d page(s) / ppn %x / cxy %x / cycle %d\n", 73 __FUNCTION__, this->process->pid, this->trdid, 74 1<<order, ppm_page2ppn(XPTR(local_cxy,ptr)), local_cxy, cycle ); 75 #endif 76 return ptr; 77 } 78 ///////////////////////////////////// KCM 79 else if( type == KMEM_KCM ) 80 { 81 // allocate memory from KCM 82 void * ptr = kcm_alloc( order ); 83 84 if( ptr == NULL ) 85 { 86 printk("\n[ERROR] in %s : KCM failed / order %d / cluster %x\n", 87 __FUNCTION__ , order , local_cxy ); 88 return NULL; 89 } 90 91 // reset memory if requested 92 if( flags & AF_ZERO ) memset( ptr , 0 , 1<<order ); 93 94 #if DEBUG_KMEM 95 thread_t * this = CURRENT_THREAD; 96 uint32_t cycle = (uint32_t)hal_get_cycles(); 97 if( DEBUG_KMEM < cycle ) 98 printk("\n[%s] thread [%x,%x] from KCM / %d bytes / base %x / cxy %x / cycle %d\n", 99 __FUNCTION__, this->process->pid, this->trdid, 100 1<<order, ptr, local_cxy, cycle ); 101 #endif 102 return ptr; 103 } 104 //////////////////////////////////// KHM 105 else if( type == KMEM_KHM ) 106 { 107 // allocate memory from KHM 108 void * ptr = khm_alloc( &LOCAL_CLUSTER->khm , order ); 109 110 if( ptr == NULL ) 111 { 112 printk("\n[ERROR] in %s : KHM failed / order %d / cluster %x\n", 113 __FUNCTION__ , order , local_cxy ); 114 return NULL; 115 } 116 117 // reset memory if requested 118 if( flags & AF_ZERO ) memset( ptr , 0 , order ); 119 120 #if DEBUG_KMEM 121 thread_t * this = CURRENT_THREAD; 122 uint32_t cycle = (uint32_t)hal_get_cycles(); 123 if( DEBUG_KMEM < cycle ) 124 printk("\n[%s] thread[%x,%x] from KHM / %d bytes / base %x / cxy %x / cycle %d\n", 212 125 __FUNCTION__, this->process->pid, this->trdid, 213 kmem_type_str( type ), size, local_cxy, cycle ); 214 #endif 215 216 // analyse request type 217 if( type == KMEM_PAGE ) // PPM allocator 218 { 219 // allocate the number of requested pages 220 ptr = (void *)ppm_alloc_pages( size ); 221 if( ptr == NULL ) 222 { 223 printk("\n[ERROR] in %s : failed for type %d / size %d in cluster %x\n", 224 __FUNCTION__ , type , size , local_cxy ); 225 return NULL; 226 } 227 228 // reset page if requested 229 if( flags & AF_ZERO ) page_zero( (page_t *)ptr ); 230 231 #if DEBUG_KMEM 232 cycle = (uint32_t)hal_get_cycles(); 233 if( DEBUG_KMEM < cycle ) 234 printk("\n[%s] thread[%x,%x] exit / %d page(s) allocated / ppn %x / cycle %d\n", 235 __FUNCTION__, this->process->pid, this->trdid, 236 1<<size, ppm_page2ppn(XPTR(local_cxy,ptr)), cycle ); 237 #endif 238 239 } 240 else if( type == KMEM_GENERIC ) // KHM allocator 241 { 242 // allocate memory from KHM 243 ptr = khm_alloc( &cluster->khm , size ); 244 if( ptr == NULL ) 245 { 246 printk("\n[ERROR] in %s : failed for type %d / size %d in cluster %x\n", 247 __FUNCTION__ , type , size , local_cxy ); 248 return NULL; 249 } 250 251 // reset memory if requested 252 if( flags & AF_ZERO ) memset( ptr , 0 , size ); 253 254 #if DEBUG_KMEM 255 cycle = (uint32_t)hal_get_cycles(); 256 if( DEBUG_KMEM < cycle ) 257 printk("\n[%s] thread[%x,%x] exit / type %s allocated / base %x / size %d / cycle %d\n", 258 __FUNCTION__, this->process->pid, this->trdid, 259 kmem_type_str( type ), (intptr_t)ptr, size, cycle ); 260 #endif 261 262 } 263 else // KCM allocator 264 { 265 // initialize the KCM allocator if not already done 266 if( cluster->kcm_tbl[type] == NULL ) 267 { 268 // get lock protecting local kcm_tbl[] array 269 busylock_acquire( &cluster->kcm_lock ); 270 271 // create missing KCM 272 error_t error = kmem_create_kcm( type ); 273 274 // release lock protecting local kcm_tbl[] array 275 busylock_release( &cluster->kcm_lock ); 276 277 if ( error ) 278 { 279 printk("\n[ERROR] in %s : cannot create KCM type %d in cluster %x\n", 280 __FUNCTION__, type, local_cxy ); 281 return NULL; 282 } 283 } 284 285 // allocate memory from KCM 286 ptr = kcm_alloc( cluster->kcm_tbl[type] ); 287 if( ptr == NULL ) 288 { 289 printk("\n[ERROR] in %s : failed for type %d / size %d in cluster %x\n", 290 __FUNCTION__ , type , size , local_cxy ); 291 return NULL; 292 } 293 294 // reset memory if requested 295 if( flags & AF_ZERO ) memset( ptr , 0 , kmem_type_size( type ) ); 296 297 #if DEBUG_KMEM 298 cycle = (uint32_t)hal_get_cycles(); 299 if( DEBUG_KMEM < cycle ) 300 printk("\n[%s] thread [%x,%x] exit / type %s allocated / base %x / size %d / cycle %d\n", 301 __FUNCTION__, this->process->pid, this->trdid, kmem_type_str(type), (intptr_t)ptr, 302 kmem_type_size(type), cycle ); 303 #endif 304 305 } 306 307 return ptr; 308 } 126 order, ptr, local_cxy, cycle ); 127 #endif 128 return ptr; 129 } 130 else 131 { 132 printk("\n[ERROR] in %s : illegal allocator type\n", __FUNCTION__); 133 return NULL; 134 } 135 } // end kmem_alloc() 309 136 310 137 ////////////////////////////////// 311 138 void kmem_free( kmem_req_t * req ) 312 139 { 313 if( req->type >= KMEM_TYPES_NR ) 314 { 315 assert( false , "illegal request type\n" ); 316 } 317 318 switch(req->type) 319 { 320 case KMEM_PAGE: 321 ppm_free_pages( (page_t*)req->ptr ); 322 return; 323 324 case KMEM_GENERIC: 325 khm_free( req->ptr ); 326 return; 327 328 default: 329 kcm_free( req->ptr ); 330 return; 331 } 332 } 333 140 uint32_t type = req->type; 141 142 if( type == KMEM_PPM ) 143 { 144 page_t * page = GET_PTR( ppm_base2page( XPTR( local_cxy , req->ptr ) ) ); 145 146 ppm_free_pages( page ); 147 } 148 else if( type == KMEM_KCM ) 149 { 150 kcm_free( req->ptr ); 151 } 152 else if( type == KMEM_KHM ) 153 { 154 khm_free( req->ptr ); 155 } 156 else 157 { 158 printk("\n[ERROR] in %s : illegal allocator type\n", __FUNCTION__); 159 } 160 } // end kmem_free() 161 162 /////////////////////////////////////////// 163 void * kmem_remote_alloc( cxy_t cxy, 164 kmem_req_t * req ) 165 { 166 uint32_t type; // KMEM_PPM / KMEM_KCM / KMEM_KHM 167 uint32_t flags; // AF_ZERO / AF_KERNEL / AF_NONE 168 uint32_t order; // PPM: ln(pages) / KCM: ln(bytes) / KHM: bytes 169 170 type = req->type; 171 order = req->order; 172 flags = req->flags; 173 174 ///////////////////////////////// PPM 175 if( type == KMEM_PPM ) 176 { 177 // allocate the number of requested pages 178 page_t * page_ptr = ppm_remote_alloc_pages( cxy , order ); 179 180 if( page_ptr == NULL ) 181 { 182 printk("\n[ERROR] in %s : failed for PPM / order %d in cluster %x\n", 183 __FUNCTION__ , order , cxy ); 184 return NULL; 185 } 186 187 xptr_t page_xp = XPTR( cxy , page_ptr ); 188 189 // get pointer on buffer from the page descriptor 190 xptr_t base_xp = ppm_page2base( page_xp ); 191 192 // reset page if requested 193 if( flags & AF_ZERO ) hal_remote_memset( base_xp , 0 , CONFIG_PPM_PAGE_SIZE ); 194 195 void * ptr = GET_PTR( base_xp ); 196 197 #if DEBUG_KMEM_REMOTE 198 thread_t * this = CURRENT_THREAD; 199 uint32_t cycle = (uint32_t)hal_get_cycles(); 200 if( DEBUG_KMEM_REMOTE < cycle ) 201 printk("\n[%s] thread[%x,%x] from PPM / %d page(s) / ppn %x / cxy %x / cycle %d\n", 202 __FUNCTION__, this->process->pid, this->trdid, 203 1<<order, ppm_page2ppn(XPTR(local_cxy,ptr)), cxy, cycle ); 204 #endif 205 return ptr; 206 } 207 /////////////////////////////////// KCM 208 else if( type == KMEM_KCM ) 209 { 210 // allocate memory from KCM 211 void * ptr = kcm_remote_alloc( cxy , order ); 212 213 if( ptr == NULL ) 214 { 215 printk("\n[ERROR] in %s : failed for KCM / order %d in cluster %x\n", 216 __FUNCTION__ , order , cxy ); 217 return NULL; 218 } 219 220 // reset memory if requested 221 if( flags & AF_ZERO ) hal_remote_memset( XPTR( cxy , ptr ) , 0 , 1<<order ); 222 223 #if DEBUG_KMEM_REMOTE 224 thread_t * this = CURRENT_THREAD; 225 uint32_t cycle = (uint32_t)hal_get_cycles(); 226 if( DEBUG_KMEM_REMOTE < cycle ) 227 printk("\n[%s] thread [%x,%x] from KCM / %d bytes / base %x / cxy %x / cycle %d\n", 228 __FUNCTION__, this->process->pid, this->trdid, 229 1<<order, ptr, cxy, cycle ); 230 #endif 231 return ptr; 232 } 233 /////////////////////////////////// KHM 234 else if( type == KMEM_KHM ) 235 { 236 printk("\n[ERROR] in %s : remote access not supported for KHM\n", __FUNCTION__ ); 237 return NULL; 238 } 239 else 240 { 241 printk("\n[ERROR] in %s : illegal allocator type\n", __FUNCTION__); 242 return NULL; 243 } 244 } // kmem_remote_malloc() 245 246 //////////////////////////////////////// 247 void kmem_remote_free( cxy_t cxy, 248 kmem_req_t * req ) 249 { 250 uint32_t type = req->type; 251 252 if( type == KMEM_PPM ) 253 { 254 page_t * page = GET_PTR( ppm_base2page( XPTR( cxy , req->ptr ) ) ); 255 256 ppm_remote_free_pages( cxy , page ); 257 } 258 else if( type == KMEM_KCM ) 259 { 260 kcm_remote_free( cxy , req->ptr ); 261 } 262 else if( type == KMEM_KHM ) 263 { 264 printk("\n[ERROR] in %s : remote access not supported for KHM\n", __FUNCTION__ ); 265 } 266 else 267 { 268 printk("\n[ERROR] in %s : illegal allocator type\n", __FUNCTION__); 269 } 270 } // end kmem_remote_free() 271 272 273
Note: See TracChangeset
for help on using the changeset viewer.