Changeset 7 for trunk/kernel/mm/kcm.c
- Timestamp:
- Apr 26, 2017, 2:15:50 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/mm/kcm.c
r1 r7 33 33 #include <page.h> 34 34 #include <cluster.h> 35 #include <kmem.h> 35 36 #include <kcm.h> 36 37 37 /////////////////////////////////////////////////////////////////////////////////////38 // Extern global variable (defined in kmem.c file)39 /////////////////////////////////////////////////////////////////////////////////////40 41 extern uint32_t kmem_size_tbl[KMEM_TYPES_NR];42 43 44 /////////////////////////////////////////////////////////////////////////////////////45 // This function allocates one page from local PPM.46 /////////////////////////////////////////////////////////////////////////////////////47 static page_t * kcm_page_alloc( kcm_t * kcm )48 {49 page_t * page;50 kmem_req_t req;51 52 req.type = KMEM_PAGE;53 req.size = 0;54 req.flags = AF_KERNEL;55 page = kmem_alloc( &req );56 57 if( page == NULL )58 {59 printk("\n[ERROR] in %s failed to allocate page in cluster %d\n",60 __FUNCTION__ , local_cxy );61 }62 63 return page;64 }65 66 38 ////////////////////////////////////////////////////////////////////////////////////// 67 // This static function returns pointer on a llocated block from an active page.39 // This static function returns pointer on an allocated block from an active page. 68 40 // It returns NULL if no block available in selected page. 69 41 // It changes the page status if required. 70 42 ////////////////////////////////////////////////////////////////////////////////////// 71 static void * get_block( kcm_t * kcm, 72 kcm_page_t * page ) 73 { 74 int32_t index = bitmap_ffs( page->bitmap , sizeof(page->bitmap) ); 75 76 // the page should be active 77 if( page->active == 0 ) 78 { 79 printk("\n[PANIC] in %s : kcm page should be active\n", __FUNCTION__ ); 80 hal_core_sleep(); 81 } 82 83 // the page should not be full 84 if( index == -1 ) 85 { 86 printk("\n[PANIC] in %s : kcm page should be active\n", __FUNCTION__ ); 87 hal_core_sleep(); 88 } 43 // @ kcm : pointer on kcm allocator. 44 // @ ptr : pointer on active kcm page to use. 45 ///////////////////////////////////////////////////////////////////////////////////// 46 static void * kcm_get_block( kcm_t * kcm, 47 kcm_page_t * page ) 48 { 49 assert( page->active , __FUNCTION__ , "kcm page should be active" ); 50 51 // get first block available 52 int32_t index = bitmap_ffs( page->bitmap , kcm->blocks_nr ); 53 54 assert( (index != -1) , __FUNCTION__ , "kcm page should not be full" ); 89 55 56 // allocate block 90 57 bitmap_clear( page->bitmap , index ); 58 59 // increase page refcount 91 60 page->refcount ++; 92 61 93 // change the page to busy if lastblock in page62 // change the page to busy no more free block in page 94 63 if( page->refcount >= kcm->blocks_nr ) 95 64 { … … 103 72 } 104 73 105 return (page->blk_tbl + index * kcm->block_size ); 106 } 74 return (page->base + index * kcm->block_size ); 75 76 } // kcm_get_block() 107 77 108 78 ///////////////////////////////////////////////////////////////////////////////////// … … 110 80 // It changes the page status if required. 111 81 ///////////////////////////////////////////////////////////////////////////////////// 112 static void put_block ( kcm_t * kcm, 113 void * ptr ) 82 // @ kcm : pointer on kcm allocator. 83 // @ ptr : pointer on block to be released. 84 ///////////////////////////////////////////////////////////////////////////////////// 85 static void kcm_put_block ( kcm_t * kcm, 86 void * ptr ) 114 87 { 115 88 kcm_page_t * page; … … 117 90 118 91 page = (kcm_page_t*)((intptr_t)ptr & CONFIG_PPM_PAGE_MASK); 119 index = ((uint8_t*)ptr - page->b lk_tbl) / kcm->block_size;92 index = ((uint8_t*)ptr - page->base) / kcm->block_size; 120 93 121 94 bitmap_set( page->bitmap , index ); … … 144 117 kcm->free_pages_nr ++; 145 118 } 146 } 147 148 ///////////////////////////////////////////////////////////////////////////////////// 149 // This static function tries to allocateone page from PPM. It initializes119 } // kcm_put_block() 120 121 ///////////////////////////////////////////////////////////////////////////////////// 122 // This static function allocates one page from PPM. It initializes 150 123 // the KCM-page descriptor, and introduces the new page into freelist. 151 124 ///////////////////////////////////////////////////////////////////////////////////// … … 154 127 page_t * page; 155 128 kcm_page_t * ptr; 129 kmem_req_t req; 156 130 157 131 // get one page from local PPM 158 page = kcm_page_alloc( kcm ); 159 if( page == NULL ) return ENOMEM; 160 161 // get physical page base address 132 req.type = KMEM_PAGE; 133 req.size = 0; 134 req.flags = AF_KERNEL; 135 page = kmem_alloc( &req ); 136 137 if( page == NULL ) 138 { 139 printk("\n[ERROR] in %s : failed to allocate page in cluster %d\n", 140 __FUNCTION__ , local_cxy ); 141 return ENOMEM; 142 } 143 144 // get page base address 162 145 ptr = ppm_page2base( page ); 163 146 … … 168 151 ptr->active = 0; 169 152 ptr->refcount = 0; 170 ptr->b lk_tbl= (uint8_t*)ptr + kcm->block_size;153 ptr->base = (uint8_t*)ptr + kcm->block_size; 171 154 ptr->kcm = kcm; 172 155 ptr->page = page; … … 177 160 178 161 return 0; 179 } 162 163 } // freelist_populate() 180 164 181 165 ///////////////////////////////////////////////////////////////////////////////////// … … 185 169 static kcm_page_t * freelist_get( kcm_t * kcm ) 186 170 { 187 error_t err ;171 error_t error; 188 172 kcm_page_t * page; 189 173 … … 191 175 if( kcm->free_pages_nr == 0 ) 192 176 { 193 err = freelist_populate( kcm );194 if( err ) return NULL;177 error = freelist_populate( kcm ); 178 if( error ) return NULL; 195 179 } 196 180 … … 199 183 list_unlink( &page->list ); 200 184 kcm->free_pages_nr --; 201 page->active = 1;202 203 list_add_first( &kcm->active_root , &page->list);204 kcm->active_pages_nr ++;205 page->active = 1;206 185 207 186 return page; 208 } 209 210 211 //////////////////////////////////// 212 error_t kcm_init( kcm_t * kcm, 213 uint32_t type ) 187 188 } // freelist_get() 189 190 191 ////////////////////////////// 192 void kcm_init( kcm_t * kcm, 193 uint32_t type ) 214 194 { 215 195 uint32_t blocks_nr; 216 196 uint32_t block_size; 217 197 uint32_t remaining; 218 kcm_page_t * page; 219 198 199 // initialize lock 220 200 spinlock_init( &kcm->lock ); 221 201 … … 231 211 list_root_init( &kcm->active_root ); 232 212 233 // initialize block size and number of blocks per page, 234 // using the global kmem_size_tbl[] array 235 block_size = ARROUND_UP( kmem_size_tbl[type] , 64 ); 213 // initialize block size and number of blocks per page 214 block_size = ARROUND_UP( kmem_type_size( type ) , 64 ); 236 215 blocks_nr = CONFIG_PPM_PAGE_SIZE / block_size; 237 216 remaining = CONFIG_PPM_PAGE_SIZE % block_size; … … 240 219 kcm->blocks_nr = blocks_nr; 241 220 kcm->block_size = block_size; 242 243 // get one page from free_list244 page = freelist_get( kcm );245 if( page == NULL ) return ENOMEM;246 221 247 // register page in active list 248 list_add_first( &kcm->active_root , &page->list ); 249 page->active = 1; 250 kcm->active_pages_nr ++; 251 252 return 0; 253 } 222 kcm_dmsg("\n[INFO] %s : KCM %s initialised / block_size = %d / blocks_nr = %d\n", 223 __FUNCTION__ , kmem_type_str( type ) , block_size , blocks_nr ); 224 225 } // kcm_init() 254 226 255 227 /////////////////////////////// … … 292 264 spinlock_unlock( &kcm->lock ); 293 265 294 295 } 266 } // kcm_destroy() 296 267 297 268 /////////////////////////////// … … 304 275 spinlock_lock( &kcm->lock ); 305 276 306 // get block307 if( list_is_empty( &kcm->active_root ) ) // no active page 277 // get an active page 278 if( list_is_empty( &kcm->active_root ) ) // no active page => get one 308 279 { 280 kcm_dmsg("\n[INFO] %s : enters for type %s but no active page => get one\n", 281 __FUNCTION__ , kmem_type_str( kcm->type ) ); 282 283 // get a page from free list 284 page = freelist_get( kcm ); 285 if( page == NULL ) return NULL; 286 287 // insert page in active list 288 list_add_first( &kcm->active_root , &page->list ); 289 kcm->active_pages_nr ++; 290 page->active = 1; 291 } 292 else // get first page from active list 293 { 294 kcm_dmsg("\n[INFO] %s : enters for type %s with an active page\n", 295 __FUNCTION__ , kmem_type_str( kcm->type ) ); 296 297 // get page pointer from active list 309 298 page = (kcm_page_t *)LIST_FIRST( &kcm->active_root , kcm_page_t , list ); 310 ptr = get_block( kcm , page );311 299 } 312 else // active page cannot be full 313 { 314 page = LIST_FIRST( &kcm->active_root , kcm_page_t , list ); 315 ptr = get_block( kcm , page ); 316 } 300 301 // get a block from selected active page 302 // cannot fail, as an active page cannot be full... 303 ptr = kcm_get_block( kcm , page ); 317 304 318 305 // release lock 319 306 spinlock_unlock(&kcm->lock); 320 307 308 kcm_dmsg("\n[INFO] %s : allocated one block of type %s / ptr = %x\n", 309 __FUNCTION__ , kmem_type_str( kcm->type ) , (uint32_t)ptr ); 310 321 311 return ptr; 322 } 312 313 } // kcm_alloc() 323 314 324 315 /////////////////////////// … … 337 328 338 329 // release block 339 put_block( kcm , ptr );330 kcm_put_block( kcm , ptr ); 340 331 341 332 // release lock … … 346 337 void kcm_print (kcm_t * kcm) 347 338 { 348 printk("*** KCM type = % d/ free_pages = %d / busy_pages = %d / active_pages = %d\n",349 k cm->type,339 printk("*** KCM type = %s / free_pages = %d / busy_pages = %d / active_pages = %d\n", 340 kmem_type_str( kcm->type ) , 350 341 kcm->free_pages_nr , 351 342 kcm->busy_pages_nr ,
Note: See TracChangeset
for help on using the changeset viewer.