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


Ignore:
Timestamp:
Apr 26, 2017, 2:15:50 PM (7 years ago)
Author:
alain
Message:

Various bugs.

File:
1 edited

Legend:

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

    r1 r7  
    3333#include <page.h>
    3434#include <cluster.h>
     35#include <kmem.h>
    3536#include <kcm.h>
    3637
    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 
    6638//////////////////////////////////////////////////////////////////////////////////////
    67 // This static function returns pointer on allocated block from an active page.
     39// This static function returns pointer on an allocated block from an active page.
    6840// It returns NULL if no block available in selected page.
    6941// It changes the page status if required.
    7042//////////////////////////////////////////////////////////////////////////////////////
    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/////////////////////////////////////////////////////////////////////////////////////
     46static 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" );
    8955 
     56    // allocate block
    9057        bitmap_clear( page->bitmap , index );
     58
     59    // increase page refcount
    9160        page->refcount ++;
    9261
    93     // change the page to busy if last block in page
     62    // change the page to busy no more free block in page
    9463    if( page->refcount >= kcm->blocks_nr )
    9564    {
     
    10372    }
    10473
    105         return (page->blk_tbl + index * kcm->block_size );
    106 }
     74        return (page->base + index * kcm->block_size );
     75
     76}  // kcm_get_block()
    10777
    10878/////////////////////////////////////////////////////////////////////////////////////
     
    11080// It changes the page status if required.
    11181/////////////////////////////////////////////////////////////////////////////////////
    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/////////////////////////////////////////////////////////////////////////////////////
     85static void kcm_put_block ( kcm_t * kcm,
     86                            void  * ptr )
    11487{
    11588        kcm_page_t * page;
     
    11790 
    11891        page = (kcm_page_t*)((intptr_t)ptr & CONFIG_PPM_PAGE_MASK);
    119         index = ((uint8_t*)ptr - page->blk_tbl) / kcm->block_size;
     92        index = ((uint8_t*)ptr - page->base) / kcm->block_size;
    12093 
    12194        bitmap_set( page->bitmap , index );
     
    144117                kcm->free_pages_nr ++;
    145118        }
    146 }
    147 
    148 /////////////////////////////////////////////////////////////////////////////////////
    149 // This static function tries to allocate one page from PPM. It initializes
     119}  // kcm_put_block()
     120
     121/////////////////////////////////////////////////////////////////////////////////////
     122// This static function allocates one page from PPM. It initializes
    150123// the KCM-page descriptor, and introduces the new page into freelist.
    151124/////////////////////////////////////////////////////////////////////////////////////
     
    154127        page_t     * page;
    155128        kcm_page_t * ptr;
     129    kmem_req_t   req;
    156130
    157131    // 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
    162145        ptr = ppm_page2base( page );
    163146
     
    168151        ptr->active        = 0;
    169152        ptr->refcount      = 0;
    170         ptr->blk_tbl       = (uint8_t*)ptr + kcm->block_size;
     153        ptr->base          = (uint8_t*)ptr + kcm->block_size;
    171154        ptr->kcm           = kcm;
    172155        ptr->page          = page;
     
    177160 
    178161        return 0;
    179 }
     162
     163}  // freelist_populate()
    180164
    181165/////////////////////////////////////////////////////////////////////////////////////
     
    185169static kcm_page_t * freelist_get( kcm_t * kcm )
    186170{
    187         error_t      err;
     171        error_t      error;
    188172        kcm_page_t * page;
    189173
     
    191175        if( kcm->free_pages_nr == 0 )
    192176        {
    193         err = freelist_populate( kcm );
    194         if( err ) return NULL;
     177        error = freelist_populate( kcm );
     178        if( error       ) return NULL;
    195179        }
    196180
     
    199183        list_unlink( &page->list );
    200184        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;
    206185
    207186        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//////////////////////////////
     192void kcm_init( kcm_t    * kcm,
     193                   uint32_t   type )
    214194{
    215195        uint32_t     blocks_nr;
    216196        uint32_t     block_size;
    217197        uint32_t     remaining;
    218         kcm_page_t * page;
    219 
     198
     199    // initialize lock
    220200        spinlock_init( &kcm->lock );
    221201
     
    231211        list_root_init( &kcm->active_root );
    232212
    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 );
    236215        blocks_nr       = CONFIG_PPM_PAGE_SIZE / block_size;
    237216        remaining       = CONFIG_PPM_PAGE_SIZE % block_size;
     
    240219        kcm->blocks_nr  = blocks_nr;
    241220        kcm->block_size = block_size;
    242 
    243     // get one page from free_list
    244         page = freelist_get( kcm );
    245         if( page == NULL ) return ENOMEM;
    246221     
    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()
    254226
    255227///////////////////////////////
     
    292264    spinlock_unlock( &kcm->lock );
    293265
    294    
    295 }
     266}  // kcm_destroy()
    296267
    297268///////////////////////////////
     
    304275        spinlock_lock( &kcm->lock );
    305276   
    306     // get block
    307     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
    308279    {
     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
    309298                page = (kcm_page_t *)LIST_FIRST( &kcm->active_root , kcm_page_t , list );
    310         ptr  = get_block( kcm , page );
    311299    }
    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 );
    317304
    318305    // release lock 
    319306        spinlock_unlock(&kcm->lock);
    320307
     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
    321311        return ptr;
    322 }
     312
     313}  // kcm_alloc()
    323314
    324315///////////////////////////
     
    337328
    338329    // release block
    339         put_block( kcm , ptr );
     330        kcm_put_block( kcm , ptr );
    340331
    341332    // release lock 
     
    346337void kcm_print (kcm_t * kcm)
    347338{
    348         printk("*** KCM type = %d / free_pages = %d / busy_pages = %d / active_pages = %d\n",
    349            kcm->type ,
     339        printk("*** KCM type = %s / free_pages = %d / busy_pages = %d / active_pages = %d\n",
     340           kmem_type_str( kcm->type ) ,
    350341           kcm->free_pages_nr ,
    351342           kcm->busy_pages_nr ,
Note: See TracChangeset for help on using the changeset viewer.