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


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

Various bugs.

File:
1 edited

Legend:

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

    r1 r7  
    9191static void ppm_free_pages_nolock( page_t * page )
    9292{
     93        page_t   * buddy;            // searched buddy page descriptor
     94        uint32_t   buddy_index;      // buddy page index
     95        page_t   * current;          // current (merged) page descriptor
     96        uint32_t   current_index;    // current (merged) page index
     97        uint32_t   current_order;    // current (merget) page order
     98
    9399    ppm_t    * ppm         = &LOCAL_CLUSTER->ppm;
    94100    page_t   * pages_tbl   = ppm->pages_tbl;
    95     uint32_t   page_order  = page->order;
    96     uint32_t   page_index  = (uint32_t)(page - ppm->pages_tbl);
    97 
    98         page_t   * block;
    99         uint32_t   block_index;
    100         uint32_t   current_order;
    101 
    102     // update page descriptor flag
     101
     102    // update released page descriptor flags
    103103        page_set_flag( page , PG_FREE );
    104104
    105     // update free_lists
    106         for( current_order = page_order ; current_order < CONFIG_PPM_MAX_ORDER ; current_order++ )
     105    // search the buddy page descriptor
     106    // - merge with current page descriptor if found
     107    // - exit to release the current page descriptor if not found
     108    current       = page ,
     109    current_index = (uint32_t)(page - ppm->pages_tbl);
     110        for( current_order = page->order ;
     111         current_order < CONFIG_PPM_MAX_ORDER ;
     112         current_order++ )
    107113    {
    108                 block_index = page_index ^ (1 << current_order);
    109                 block = pages_tbl + block_index;
    110    
    111                 if( page_is_flag( block , PG_FREE ) || (block->order != current_order) ) break;
    112 
    113                 list_unlink( &block->list );
     114                buddy_index = current_index ^ (1 << current_order);
     115                buddy       = pages_tbl + buddy_index;
     116   
     117                if( !page_is_flag( buddy , PG_FREE ) || (buddy->order != current_order) ) break;
     118
     119        // remove buddy from free list
     120                list_unlink( &buddy->list );
    114121                ppm->free_pages_nr[current_order] --;
    115122        ppm->total_free_pages -= (1 << current_order);
    116123   
    117                 block->order = 0;
    118                 page_index &= block_index;
    119         }
    120  
    121         block        = pages_tbl + page_index;
    122         block->order = current_order;
    123 
    124         list_add_first( &ppm->free_pages_root[current_order] , &block->list );
     124        // merge buddy with current
     125                buddy->order = 0;
     126                current_index &= buddy_index;
     127        }
     128 
     129    // update merged page descriptor order
     130        current        = pages_tbl + current_index;
     131        current->order = current_order;
     132
     133    // insert current in free list
     134        list_add_first( &ppm->free_pages_root[current_order] , &current->list );
    125135        ppm->free_pages_nr[current_order] ++;
    126136    ppm->total_free_pages += (1 << current_order);
     
    128138}  // end ppm_free_pages_nolock()
    129139
    130 /////////////////////////////////
     140//////////////////////////////
    131141void ppm_init( ppm_t    * ppm,
    132142               uint32_t   pages_nr,        // total pages number
     
    148158                ppm->free_pages_nr[i] = 0;
    149159        }
     160
     161#if( CONFIG_PPM_DEBUG )
     162ppm_print( ppm , "after reset" );
     163#endif
    150164 
    151165    // initialize dirty_list as empty
     
    166180        // set pages numbers
    167181        ppm->pages_nr      = pages_nr;
    168     ppm->pages_offset  = pages_offset;
     182    ppm->pages_offset  = reserved_pages;
    169183
    170184    // initialises all page descriptors in pages_tbl[]
    171     // TODO Peut-on accélérer ces monstrueuses boucle ? [AG]
    172185        for( i = 0 ; i < pages_nr ; i++ )
    173186    {
    174187        page_init( &ppm->pages_tbl[i] );
     188
     189        // TODO optimisation : make only a partial init [AG]
     190        // complete the initialisation when page is allocated [AG]
     191        // ppm->pages_tbl[i].flags = 0;
    175192    }
    176193
    177     // set PG_RESERVED flag for reserved pages (kernel code & pages_tbl[])
     194    // - set PG_RESERVED flag for reserved pages (kernel code & pages_tbl[])
     195    // - release all other pages to populate the free lists
    178196        for( i = 0 ; i < reserved_pages ; i++)
    179197    {
    180198        page_set_flag( &ppm->pages_tbl[i] , PG_RESERVED );
    181199    }
    182 
    183     // initialise the free lists by releasing all non reserved pages
    184         for( i = 0 ; i < pages_nr ; i++ )
    185         {
    186                 page_t * page = &ppm->pages_tbl[i];
    187                 if( page_is_flag( page , PG_RESERVED) ) ppm_free_pages_nolock( page );
    188         }
     200        for( i = reserved_pages ; i < pages_nr ; i++ )
     201        {
     202            ppm_free_pages_nolock( &ppm->pages_tbl[i] );
     203
     204        // TODO optimisation : decompose this enormous set of small pages
     205        // to a set big pages with various order values
     206        }
     207
     208    // check consistency
     209    ppm_assert_order( ppm );
     210
     211    kinit_dmsg("\n[INFO] %s : done in cluster %x at cycle %d\n",
     212               __FUNCTION__ , local_cxy , hal_time_stamp() );
     213
     214#if( CONFIG_PPM_DEBUG )
     215ppm_print( ppm , "after init" );
     216#endif
     217   
    189218} // end ppm_init()
    190219
     
    198227    ppm_t    * ppm = &LOCAL_CLUSTER->ppm;
    199228
    200         if( ppm->signature != PPM_SIGNATURE )
    201     {
    202         printk("\n[PANIC] in %s : PPM non initialised in cluster %x\n",
    203                __FUNCTION__ , local_cxy );
    204         hal_core_sleep();
    205     }
    206 
    207         if( order >= CONFIG_PPM_MAX_ORDER )
    208     {
    209         printk("\n[PANIC] in %s : illegal order argument in cluster %x\n",
    210                __FUNCTION__ , local_cxy );
    211         hal_core_sleep();
    212     }
     229        assert( (ppm->signature == PPM_SIGNATURE) , __FUNCTION__ , "PPM non initialised" );
     230
     231        assert( (order < CONFIG_PPM_MAX_ORDER) , __FUNCTION__ , "illegal order argument" );
    213232
    214233        page_t * block = NULL;
     234
     235    ppm_dmsg("\n[INFO] %s : enters / order = %d\n",
     236             __FUNCTION__ , order );
     237
     238#if( CONFIG_PPM_DEBUG )
     239ppm_print( ppm , "before allocation" );
     240#endif
    215241
    216242    // take lock protecting free lists
    217243        spinlock_lock( &ppm->free_lock );
    218244
    219     // find a block larger or equal to requested size
     245    // find a free block equal or larger to requested size
    220246        for( current_order = order ; current_order < CONFIG_PPM_MAX_ORDER ; current_order ++ )
    221247        {
     
    264290        spinlock_unlock( &ppm->free_lock );
    265291 
     292    ppm_dmsg("\n[INFO] %s : base = %x / order = %d\n",
     293             __FUNCTION__ , (uint32_t)ppm_page2base( block ) , order );
     294
     295#if CONFIG_PPM_DEBUG
     296ppm_print( ppm , "after allocation" );
     297#endif
     298
    266299        return block;
    267300}  // end pmm_alloc-pages()
     
    282315}
    283316
    284 /////////////////////////////
    285 void ppm_print( ppm_t * ppm )
     317////////////////////////////
     318void ppm_print( ppm_t * ppm,
     319                char  * string )
    286320{
    287321        uint32_t       order;
     
    292326        spinlock_lock( &ppm->free_lock );
    293327
    294         printk("***  PPM state in cluster %x : pages = %d / offset = %d / free = %d ***\n",
    295                local_cxy , ppm->pages_nr , ppm->pages_offset , ppm->total_free_pages );
     328        printk("\n***  PPM state in cluster %x %s : pages = %d / offset = %d / free = %d ***\n",
     329               local_cxy , string , ppm->pages_nr , ppm->pages_offset , ppm->total_free_pages );
    296330       
    297331        for( order = 0 ; order < CONFIG_PPM_MAX_ORDER ; order++ )
    298332        {
    299                 printk("- order = %d / free_pages = %d  [\n",
     333                printk("- order = %d / free_pages = %d  [",
    300334               order , ppm->free_pages_nr[order] );
    301335               
     
    311345    // release lock protecting free lists
    312346        spinlock_unlock( &ppm->free_lock );
    313 }
    314 
    315 ////////////////////////////////////////
    316 void ppm_assert_order(struct ppm_s *ppm)
     347
     348}  // end ppm_print()
     349 
     350//////////////////////////u/////////
     351void ppm_assert_order( ppm_t * ppm )
    317352{
    318353        uint32_t       order;
     
    328363                        page = LIST_ELEMENT( iter , page_t , list );
    329364
    330                         if( page->order != order )
    331             {
    332                     printk("%s detected inconsistency at order %d, page %d\n",
    333                            __FUNCTION__, order , page - ppm->pages_tbl );
    334             }
     365                        assert( (page->order == order) , __FUNCTION__ , "PPM inconsistency" );
    335366                }
    336367        }
    337         return;
    338 }
    339 
     368
     369}  // end ppm_assert_order()
     370
Note: See TracChangeset for help on using the changeset viewer.