Changeset 50 for trunk/kernel/mm/kcm.c


Ignore:
Timestamp:
Jun 26, 2017, 3:15:11 PM (5 years ago)
Author:
alain
Message:

bloup

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/mm/kcm.c

    r20 r50  
    33 *
    44 * Author  Ghassan Almaless (2008,2009,2010,2011,2012)
    5  *         Alain Greiner    (2016)
     5 *         Alain Greiner    (2016,2017)
    66 *
    77 * Copyright (c) UPMC Sorbonne Universites
     
    4141// It changes the page status if required.
    4242//////////////////////////////////////////////////////////////////////////////////////
    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.
    4545/////////////////////////////////////////////////////////////////////////////////////
    4646static 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" );
    5054
    5155        // 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" );
     56        int32_t index = bitmap_ffs( kcm_page->bitmap , kcm->blocks_nr );
     57
     58        assert( (index != -1) , __FUNCTION__ , "kcm_page should not be full" );
    5559
    5660        // allocate block
    57         bitmap_clear( page->bitmap , index );
    58 
    59         // increase page refcount
    60         page->refcount ++;
    61 
    62         // change the page to busy no more free block in page
    63         if( page->refcount >= kcm->blocks_nr )
    64         {
    65                 page->active = 0;
    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);
    6771                kcm->active_pages_nr --;
    6872
    69                 list_add_first( &kcm->busy_root , &page->list);
     73                list_add_first( &kcm->busy_root , &kcm_page->list);
    7074                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;
    7587
    7688}  // kcm_get_block()
     
    7890/////////////////////////////////////////////////////////////////////////////////////
    7991// 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.
    8193/////////////////////////////////////////////////////////////////////////////////////
    8294// @ kcm   : pointer on kcm allocator.
     
    8698                            void  * ptr )
    8799{
    88         kcm_page_t * page;
     100        kcm_page_t * kcm_page;
    89101        uint32_t     index;
    90102
    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 --;
    96111
    97112        // 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 );
    102117                kcm->busy_pages_nr --;
    103118
    104                 list_add_last( &kcm->active_root, &page->list );
     119                list_add_last( &kcm->active_root, &kcm_page->list );
    105120                kcm->active_pages_nr ++;
    106                 page->active = 1;
    107         }
    108 
    109         // change the page to free if last block in active page
    110         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);
    114129                kcm->active_pages_nr --;
    115130
    116                 list_add_first( &kcm->free_root , &page->list);
     131                list_add_first( &kcm->free_root , &kcm_page->list);
    117132                kcm->free_pages_nr ++;
    118133        }
     
    121136/////////////////////////////////////////////////////////////////////////////////////
    122137// This static function allocates one page from PPM. It initializes
    123 // the KCM-page descriptor, and introduces the new page into freelist.
     138// the kcm_page descriptor, and introduces the new kcm_page into freelist.
    124139/////////////////////////////////////////////////////////////////////////////////////
    125140static error_t freelist_populate( kcm_t * kcm )
    126141{
    127142        page_t     * page;
    128         kcm_page_t * ptr;
     143        kcm_page_t * kcm_page;
    129144        kmem_req_t   req;
    130145
     
    143158
    144159        // get page base address
    145         ptr = ppm_page2base( page );
     160        kcm_page = (kcm_page_t *)ppm_page2base( page );
    146161
    147162        // 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;
    156170
    157171        // 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 );
    159173        kcm->free_pages_nr ++;
    160174
     
    170184{
    171185        error_t      error;
    172         kcm_page_t * page;
     186        kcm_page_t * kcm_page;
    173187
    174188        // get a new page from PPM if freelist empty
     
    179193        }
    180194
    181         // get first KCM page from freelist and change its status to active
    182         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 );
    184198        kcm->free_pages_nr --;
    185199
    186         return page;
     200        return kcm_page;
    187201
    188202} // freelist_get()
     
    193207                   uint32_t   type )
    194208{
    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" );
    198212
    199213        // initialize lock
     
    211225        list_root_init( &kcm->active_root );
    212226
    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 );
    220229        kcm->block_size = block_size;
    221230
     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
    222235        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 );
    224237
    225238}  // kcm_init()
     
    228241void kcm_destroy( kcm_t * kcm )
    229242{
    230         kcm_page_t   * page;
     243        kcm_page_t   * kcm_page;
    231244        list_entry_t * iter;
    232245
     
    237250        LIST_FOREACH( &kcm->free_root , iter )
    238251        {
    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 );
    240253                list_unlink( iter );
    241254                kcm->free_pages_nr --;
    242                 ppm_free_pages( page->page );
     255                ppm_free_pages( kcm_page->page );
    243256        }
    244257
     
    246259        LIST_FOREACH( &kcm->active_root , iter )
    247260        {
    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 );
    249262                list_unlink( iter );
    250263                kcm->free_pages_nr --;
    251                 ppm_free_pages( page->page );
     264                ppm_free_pages( kcm_page->page );
    252265        }
    253266
     
    255268        LIST_FOREACH( &kcm->busy_root , iter )
    256269        {
    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 );
    258271                list_unlink( iter );
    259272                kcm->free_pages_nr --;
    260                 ppm_free_pages( page->page );
     273                ppm_free_pages( kcm_page->page );
    261274        }
    262275
     
    269282void * kcm_alloc( kcm_t * kcm )
    270283{
    271         kcm_page_t * page;
     284        kcm_page_t * kcm_page;
    272285        void       * ptr = NULL;   // pointer on block
    273286
     
    278291        if( list_is_empty( &kcm->active_root ) )  // no active page => get one
    279292        {
    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 
    283293                // 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;
    286297
    287298                // insert page in active list
    288                 list_add_first( &kcm->active_root , &page->list );
     299                list_add_first( &kcm->active_root , &kcm_page->list );
    289300                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        {
    297310                // 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 );
    299316        }
    300317
    301318        // get a block from selected active page
    302319        // cannot fail, as an active page cannot be full...
    303         ptr  = kcm_get_block( kcm , page );
     320        ptr  = kcm_get_block( kcm , kcm_page );
    304321
    305322        // 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 );
    310324
    311325        return ptr;
    312326
    313 }  // kcm_alloc()
     327}  // end kcm_allo()
    314328
    315329///////////////////////////
    316330void kcm_free( void * ptr )
    317331{
    318         kcm_page_t * page;
     332        kcm_page_t * kcm_page;
    319333        kcm_t      * kcm;
    320334
    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;
    325339
    326340        // get lock
     
    332346        // release lock
    333347        spinlock_unlock( &kcm->lock );
    334 }
     348
     349}  // end kcm_free()
    335350
    336351////////////////////////////
Note: See TracChangeset for help on using the changeset viewer.