Changeset 50 for trunk/kernel/mm/kcm.c
- Timestamp:
- Jun 26, 2017, 3:15:11 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/mm/kcm.c
r20 r50 3 3 * 4 4 * Author Ghassan Almaless (2008,2009,2010,2011,2012) 5 * Alain Greiner (2016 )5 * Alain Greiner (2016,2017) 6 6 * 7 7 * Copyright (c) UPMC Sorbonne Universites … … 41 41 // It changes the page status if required. 42 42 ////////////////////////////////////////////////////////////////////////////////////// 43 // @ kcm : pointer on kcm allocator.44 // @ ptr: pointer on active kcm page to use.43 // @ kcm : pointer on kcm allocator. 44 // @ kcm_page : pointer on active kcm page to use. 45 45 ///////////////////////////////////////////////////////////////////////////////////// 46 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" ); 47 kcm_page_t * kcm_page ) 48 { 49 kcm_dmsg("\n[INFO] %s : enters for %s / page %x / count = %d / active = %d\n", 50 __FUNCTION__ , kmem_type_str( kcm->type ) , 51 (intptr_t)kcm_page , kcm_page->count , kcm_page->active ); 52 53 assert( kcm_page->active , __FUNCTION__ , "kcm_page should be active" ); 50 54 51 55 // get first block available 52 int32_t index = bitmap_ffs( page->bitmap , kcm->blocks_nr );53 54 assert( (index != -1) , __FUNCTION__ , "kcm 56 int32_t index = bitmap_ffs( kcm_page->bitmap , kcm->blocks_nr ); 57 58 assert( (index != -1) , __FUNCTION__ , "kcm_page should not be full" ); 55 59 56 60 // allocate block 57 bitmap_clear( page->bitmap , index );58 59 // increase page refcount60 page->refcount ++;61 62 // change the page to busyno more free block in page63 if( page->refcount >= kcm->blocks_nr )64 { 65 66 list_unlink( & page->list);61 bitmap_clear( kcm_page->bitmap , index ); 62 63 // increase kcm_page count 64 kcm_page->count ++; 65 66 // change the kcm_page to busy if no more free block in page 67 if( kcm_page->count >= kcm->blocks_nr ) 68 { 69 kcm_page->active = 0; 70 list_unlink( &kcm_page->list); 67 71 kcm->active_pages_nr --; 68 72 69 list_add_first( &kcm->busy_root , & page->list);73 list_add_first( &kcm->busy_root , &kcm_page->list); 70 74 kcm->busy_pages_nr ++; 71 page->busy = 1; 72 } 73 74 return (page->base + index * kcm->block_size ); 75 kcm_page->busy = 1; 76 } 77 78 // compute return pointer 79 void * ptr = (void *)((intptr_t)kcm_page + CONFIG_KCM_SLOT_SIZE 80 + (index * kcm->block_size) ); 81 82 kcm_dmsg("\n[INFO] %s : allocated one block %s / ptr = %x / page = %x / count = %d\n", 83 __FUNCTION__ , kmem_type_str( kcm->type ) , (uint32_t)ptr , 84 (intptr_t)kcm_page , kcm_page->count ); 85 86 return ptr; 75 87 76 88 } // kcm_get_block() … … 78 90 ///////////////////////////////////////////////////////////////////////////////////// 79 91 // This static function releases a previously allocated block. 80 // It changes the page status if required.92 // It changes the kcm_page status if required. 81 93 ///////////////////////////////////////////////////////////////////////////////////// 82 94 // @ kcm : pointer on kcm allocator. … … 86 98 void * ptr ) 87 99 { 88 kcm_page_t * page;100 kcm_page_t * kcm_page; 89 101 uint32_t index; 90 102 91 page = (kcm_page_t*)((intptr_t)ptr & CONFIG_PPM_PAGE_MASK); 92 index = ((uint8_t*)ptr - page->base) / kcm->block_size; 93 94 bitmap_set( page->bitmap , index ); 95 page->refcount --; 103 // compute pointer on kcm_page from block pointer 104 kcm_page = (kcm_page_t*)((intptr_t)ptr & ~CONFIG_PPM_PAGE_MASK); 105 106 // compute block index from block pointer 107 index = ((uint8_t *)ptr - (uint8_t *)kcm_page - CONFIG_KCM_SLOT_SIZE) / kcm->block_size; 108 109 bitmap_set( kcm_page->bitmap , index ); 110 kcm_page->count --; 96 111 97 112 // change the page to active if it was busy 98 if( page->busy )99 { 100 page->busy = 0;101 list_unlink( & page->list );113 if( kcm_page->busy ) 114 { 115 kcm_page->busy = 0; 116 list_unlink( &kcm_page->list ); 102 117 kcm->busy_pages_nr --; 103 118 104 list_add_last( &kcm->active_root, & page->list );119 list_add_last( &kcm->active_root, &kcm_page->list ); 105 120 kcm->active_pages_nr ++; 106 page->active = 1;107 } 108 109 // change the page to free if last block in active page110 if( ( page->active) && (page->refcount == 0) )111 { 112 page->active = 0;113 list_unlink( & page->list);121 kcm_page->active = 1; 122 } 123 124 // change the kcm_page to free if last block in active page 125 if( (kcm_page->active) && (kcm_page->count == 0) ) 126 { 127 kcm_page->active = 0; 128 list_unlink( &kcm_page->list); 114 129 kcm->active_pages_nr --; 115 130 116 list_add_first( &kcm->free_root , & page->list);131 list_add_first( &kcm->free_root , &kcm_page->list); 117 132 kcm->free_pages_nr ++; 118 133 } … … 121 136 ///////////////////////////////////////////////////////////////////////////////////// 122 137 // This static function allocates one page from PPM. It initializes 123 // the KCM-page descriptor, and introduces the newpage into freelist.138 // the kcm_page descriptor, and introduces the new kcm_page into freelist. 124 139 ///////////////////////////////////////////////////////////////////////////////////// 125 140 static error_t freelist_populate( kcm_t * kcm ) 126 141 { 127 142 page_t * page; 128 kcm_page_t * ptr;143 kcm_page_t * kcm_page; 129 144 kmem_req_t req; 130 145 … … 143 158 144 159 // get page base address 145 ptr =ppm_page2base( page );160 kcm_page = (kcm_page_t *)ppm_page2base( page ); 146 161 147 162 // initialize KCM-page descriptor 148 bitmap_set_range( ptr->bitmap , 0 , kcm->blocks_nr ); 149 150 ptr->busy = 0; 151 ptr->active = 0; 152 ptr->refcount = 0; 153 ptr->base = (uint8_t*)ptr + kcm->block_size; 154 ptr->kcm = kcm; 155 ptr->page = page; 163 bitmap_set_range( kcm_page->bitmap , 0 , kcm->blocks_nr ); 164 165 kcm_page->busy = 0; 166 kcm_page->active = 0; 167 kcm_page->count = 0; 168 kcm_page->kcm = kcm; 169 kcm_page->page = page; 156 170 157 171 // introduce new page in free-list 158 list_add_first( &kcm->free_root , & ptr->list );172 list_add_first( &kcm->free_root , &kcm_page->list ); 159 173 kcm->free_pages_nr ++; 160 174 … … 170 184 { 171 185 error_t error; 172 kcm_page_t * page;186 kcm_page_t * kcm_page; 173 187 174 188 // get a new page from PPM if freelist empty … … 179 193 } 180 194 181 // get first KCM page from freelist and change its status to active182 page = LIST_FIRST( &kcm->free_root, kcm_page_t , list );183 list_unlink( & page->list );195 // get first KCM page from freelist and unlink it 196 kcm_page = LIST_FIRST( &kcm->free_root, kcm_page_t , list ); 197 list_unlink( &kcm_page->list ); 184 198 kcm->free_pages_nr --; 185 199 186 return page;200 return kcm_page; 187 201 188 202 } // freelist_get() … … 193 207 uint32_t type ) 194 208 { 195 uint32_t blocks_nr; 196 uint32_t block_size; 197 uint32_t remaining;209 // the kcm_page descriptor mut fit in the KCM slot 210 assert( (sizeof(kcm_page_t) <= CONFIG_KCM_SLOT_SIZE) , 211 __FUNCTION__ , "KCM slot too small\n" ); 198 212 199 213 // initialize lock … … 211 225 list_root_init( &kcm->active_root ); 212 226 213 // initialize block size and number of blocks per page 214 block_size = ARROUND_UP( kmem_type_size( type ) , 64 ); 215 blocks_nr = CONFIG_PPM_PAGE_SIZE / block_size; 216 remaining = CONFIG_PPM_PAGE_SIZE % block_size; 217 blocks_nr = (remaining >= sizeof(kcm_page_t)) ? blocks_nr : blocks_nr - 1; 218 219 kcm->blocks_nr = blocks_nr; 227 // initialize block size 228 uint32_t block_size = ARROUND_UP( kmem_type_size( type ) , CONFIG_KCM_SLOT_SIZE ); 220 229 kcm->block_size = block_size; 221 230 231 // initialize number of blocks per page 232 uint32_t blocks_nr = (CONFIG_PPM_PAGE_SIZE - CONFIG_KCM_SLOT_SIZE) / block_size; 233 kcm->blocks_nr = blocks_nr; 234 222 235 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 );236 __FUNCTION__ , kmem_type_str( type ) , kcm->block_size , kcm->blocks_nr ); 224 237 225 238 } // kcm_init() … … 228 241 void kcm_destroy( kcm_t * kcm ) 229 242 { 230 kcm_page_t * page;243 kcm_page_t * kcm_page; 231 244 list_entry_t * iter; 232 245 … … 237 250 LIST_FOREACH( &kcm->free_root , iter ) 238 251 { 239 page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );252 kcm_page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list ); 240 253 list_unlink( iter ); 241 254 kcm->free_pages_nr --; 242 ppm_free_pages( page->page );255 ppm_free_pages( kcm_page->page ); 243 256 } 244 257 … … 246 259 LIST_FOREACH( &kcm->active_root , iter ) 247 260 { 248 page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );261 kcm_page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list ); 249 262 list_unlink( iter ); 250 263 kcm->free_pages_nr --; 251 ppm_free_pages( page->page );264 ppm_free_pages( kcm_page->page ); 252 265 } 253 266 … … 255 268 LIST_FOREACH( &kcm->busy_root , iter ) 256 269 { 257 page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list );270 kcm_page = (kcm_page_t *)LIST_ELEMENT( iter , kcm_page_t , list ); 258 271 list_unlink( iter ); 259 272 kcm->free_pages_nr --; 260 ppm_free_pages( page->page );273 ppm_free_pages( kcm_page->page ); 261 274 } 262 275 … … 269 282 void * kcm_alloc( kcm_t * kcm ) 270 283 { 271 kcm_page_t * page;284 kcm_page_t * kcm_page; 272 285 void * ptr = NULL; // pointer on block 273 286 … … 278 291 if( list_is_empty( &kcm->active_root ) ) // no active page => get one 279 292 { 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 293 // get a page from free list 284 page = freelist_get( kcm ); 285 if( page == NULL ) return NULL; 294 kcm_page = freelist_get( kcm ); 295 296 if( kcm_page == NULL ) return NULL; 286 297 287 298 // insert page in active list 288 list_add_first( &kcm->active_root , & page->list );299 list_add_first( &kcm->active_root , &kcm_page->list ); 289 300 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 301 kcm_page->active = 1; 302 303 kcm_dmsg("\n[INFO] %s : enters for type %s at cycle %d / new page = %x / count = %d\n", 304 __FUNCTION__ , kmem_type_str( kcm->type ) , hal_time_stamp() , 305 (intptr_t)kcm_page , kcm_page->count ); 306 307 } 308 else // get first page from active list 309 { 297 310 // get page pointer from active list 298 page = (kcm_page_t *)LIST_FIRST( &kcm->active_root , kcm_page_t , list ); 311 kcm_page = (kcm_page_t *)LIST_FIRST( &kcm->active_root , kcm_page_t , list ); 312 313 kcm_dmsg("\n[INFO] %s : enters for type %s at cycle %d / page = %x / count = %d\n", 314 __FUNCTION__ , kmem_type_str( kcm->type ) , hal_time_stamp() , 315 (intptr_t)kcm_page , kcm_page->count ); 299 316 } 300 317 301 318 // get a block from selected active page 302 319 // cannot fail, as an active page cannot be full... 303 ptr = kcm_get_block( kcm , page );320 ptr = kcm_get_block( kcm , kcm_page ); 304 321 305 322 // release lock 306 spinlock_unlock(&kcm->lock); 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 ); 323 spinlock_unlock( &kcm->lock ); 310 324 311 325 return ptr; 312 326 313 } // kcm_alloc()327 } // end kcm_allo() 314 328 315 329 /////////////////////////// 316 330 void kcm_free( void * ptr ) 317 331 { 318 kcm_page_t * page;332 kcm_page_t * kcm_page; 319 333 kcm_t * kcm; 320 334 321 if( ptr == NULL ) return;322 323 page = (kcm_page_t *)((intptr_t)ptr &CONFIG_PPM_PAGE_MASK);324 kcm =page->kcm;335 assert( (ptr != NULL) , __FUNCTION__ , "pointer cannot be NULL" ); 336 337 kcm_page = (kcm_page_t *)((intptr_t)ptr & ~CONFIG_PPM_PAGE_MASK); 338 kcm = kcm_page->kcm; 325 339 326 340 // get lock … … 332 346 // release lock 333 347 spinlock_unlock( &kcm->lock ); 334 } 348 349 } // end kcm_free() 335 350 336 351 ////////////////////////////
Note: See TracChangeset
for help on using the changeset viewer.