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


Ignore:
Timestamp:
Jul 1, 2019, 9:34:16 AM (5 months ago)
Author:
alain
Message:

Fix a bug in list_remote_add_first() and list_remote_add_last() functions,
used by the physical memory allocator, that corrupted the PPM state.

File:
1 edited

Legend:

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

    r635 r636  
    11/*
    2  * ppm.c - Per-cluster Physical Pages Manager implementation
     2 * ppm.c - Physical Pages Manager implementation
    33 *
    44 * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
     
    149149void ppm_free_pages_nolock( page_t * page )
    150150{
    151         page_t   * buddy;            // searched buddy block page descriptor
    152         uint32_t   buddy_index;      // buddy bloc index in page_tbl[]
    153         page_t   * current;          // current (merged) block page descriptor
    154         uint32_t   current_index;    // current (merged) block index in page_tbl[]
    155         uint32_t   current_order;    // current (merged) block order
     151        page_t   * buddy;               // searched buddy page descriptor
     152        uint32_t   buddy_index;         // buddy page index in page_tbl[]
     153        page_t   * current;             // current (merged) page descriptor
     154        uint32_t   current_index;       // current (merged) page index in page_tbl[]
     155        uint32_t   current_order;       // current (merged) page order
    156156
    157157        ppm_t    * ppm         = &LOCAL_CLUSTER->ppm;
     
    159159
    160160assert( !page_is_flag( page , PG_FREE ) ,
    161 "page already released : ppn = %x\n" , ppm_page2ppn(XPTR(local_cxy,page)) );
     161"page already released : ppn = %x\n" , ppm_page2ppn( XPTR( local_cxy , page ) ) );
    162162
    163163assert( !page_is_flag( page , PG_RESERVED ) ,
    164 "reserved page : ppn = %x\n" , ppm_page2ppn(XPTR(local_cxy,page)) );
    165 
    166         // update released page descriptor flags
     164"reserved page : ppn = %x\n" , ppm_page2ppn( XPTR( local_cxy , page ) ) );
     165
     166        // set FREE flag in released page descriptor
    167167        page_set_flag( page , PG_FREE );
    168168
     169    // initialise loop variables
     170    current       = page;
     171    current_order = page->order;
     172        current_index = page - ppm->pages_tbl;
     173
    169174        // search the buddy page descriptor
    170         // - merge with current page descriptor if found
    171         // - exit to release the current page descriptor if not found
    172         current       = page;
    173         current_index = (uint32_t)(page - ppm->pages_tbl);
    174         for( current_order = page->order ;
    175              current_order < CONFIG_PPM_MAX_ORDER ;
    176              current_order++ )
    177         {
     175        // - merge with current page if buddy found
     176        // - exit to release the current page when buddy not found
     177    while( current_order < CONFIG_PPM_MAX_ORDER )
     178    {
     179        // compute buddy page index and page descriptor
    178180                buddy_index = current_index ^ (1 << current_order);
    179181                buddy       = pages_tbl + buddy_index;
    180 
    181         // exit this loop if buddy block not found
    182                 if( !page_is_flag( buddy , PG_FREE ) ||
    183             (buddy->order != current_order) ) break;
    184 
    185                 // remove buddy block from free_list
     182       
     183        // exit loop if buddy not found in current free list
     184                if( !page_is_flag( buddy , PG_FREE ) || (buddy->order != current_order) ) break;
     185
     186        // remove buddy page from current free_list
    186187                list_unlink( &buddy->list );
    187188                ppm->free_pages_nr[current_order] --;
    188189
    189         // reset order field in buddy block page descriptor
     190        // reset order field in buddy page descriptor
    190191                buddy->order = 0;
    191192
    192                 // compute merged block index in page_tbl[]
     193                // compute next (merged) page index in page_tbl[]
    193194                current_index &= buddy_index;
    194         }
    195 
    196         // update pointer and order field for merged block page descriptor
    197         current        = pages_tbl + current_index;
     195
     196        // compute next (merged) page order
     197        current_order++;
     198
     199        // compute next (merged) page descripror
     200        current = pages_tbl + current_index;
     201    }
     202
     203        // update order field for merged page descriptor
    198204        current->order = current_order;
    199205
    200         // insert merged block in free list
     206        // insert merged page in relevant free list
    201207        list_add_first( &ppm->free_pages_root[current_order] , &current->list );
    202208        ppm->free_pages_nr[current_order] ++;
    203209
    204210}  // end ppm_free_pages_nolock()
     211
    205212
    206213////////////////////////////////////////////
     
    216223#if DEBUG_PPM_ALLOC_PAGES
    217224uint32_t cycle = (uint32_t)hal_get_cycles();
     225#endif
     226
     227#if (DEBUG_PPM_ALLOC_PAGES & 1)
    218228if( DEBUG_PPM_ALLOC_PAGES < cycle )
    219 printk("\n[%s] thread[%x,%x] enter for %d page(s) in cluster %x / cycle %d\n",
    220 __FUNCTION__, this->process->pid, this->trdid, 1<<order, local_cxy, cycle );
    221 #endif
    222 
    223 #if(DEBUG_PPM_ALLOC_PAGES & 0x1)
    224 if( DEBUG_PPM_ALLOC_PAGES < cycle )
    225 ppm_remote_display( local_cxy );
     229{
     230    printk("\n[%s] thread[%x,%x] enter for %d page(s) in cluster %x / cycle %d\n",
     231    __FUNCTION__, this->process->pid, this->trdid, 1<<order, local_cxy, cycle );
     232    ppm_remote_display( local_cxy );
     233}
    226234#endif
    227235
     
    309317
    310318#if DEBUG_PPM_ALLOC_PAGES
    311 cycle = (uint32_t)hal_get_cycles();
    312319if( DEBUG_PPM_ALLOC_PAGES < cycle )
    313 printk("\n[%s] thread[%x,%x] exit for %d page(s) in cluster %x / ppn = %x / cycle %d\n",
    314 __FUNCTION__, this->process->pid, this->trdid,
    315 1<<order, local_cxy, ppm_page2ppn(XPTR( local_cxy , found_block )), cycle );
    316 #endif
    317 
    318 #if(DEBUG_PPM_ALLOC_PAGES & 0x1)
    319 if( DEBUG_PPM_ALLOC_PAGES < cycle )
    320 ppm_remote_display( local_cxy );
     320{
     321    printk("\n[%s] thread[%x,%x] allocated %d page(s) in cluster %x / ppn %x / cycle %d\n",
     322    __FUNCTION__, this->process->pid, this->trdid,
     323    1<<order, local_cxy, ppm_page2ppn(XPTR( local_cxy , found_block )), cycle );
     324    ppm_remote_display( local_cxy );
     325}
    321326#endif
    322327
     
    324329
    325330}  // end ppm_alloc_pages()
    326 
    327331
    328332////////////////////////////////////
     
    334338thread_t * this  = CURRENT_THREAD;
    335339uint32_t   cycle = (uint32_t)hal_get_cycles();
     340#endif
     341
     342#if ( DEBUG_PPM_FREE_PAGES & 1 )
    336343if( DEBUG_PPM_FREE_PAGES < cycle )
    337 printk("\n[%s] thread[%x,%x] enter for %d page(s) in cluster %x / ppn %x / cycle %d\n",
    338 __FUNCTION__, this->process->pid, this->trdid,
    339 1<<page->order, local_cxy, ppm_page2ppn(XPTR(local_cxy , page)), cycle );
    340 #endif
    341 
    342 #if(DEBUG_PPM_FREE_PAGES & 0x1)
    343 if( DEBUG_PPM_FREE_PAGES < cycle )
    344 ppm_remote_display( local_cxy );
     344{
     345    printk("\n[%s] thread[%x,%x] enter for %d page(s) in cluster %x / ppn %x / cycle %d\n",
     346    __FUNCTION__, this->process->pid, this->trdid,
     347    1<<page->order, local_cxy, ppm_page2ppn(XPTR(local_cxy , page)), cycle );
     348    ppm_remote_display( local_cxy );
    345349#endif
    346350
     
    360364
    361365#if DEBUG_PPM_FREE_PAGES
    362 cycle = (uint32_t)hal_get_cycles();
    363366if( DEBUG_PPM_FREE_PAGES < cycle )
    364 printk("\n[%s] thread[%x,%x] exit for %d page(s) in cluster %x / ppn %x / cycle %d\n",
    365 __FUNCTION__, this->process->pid, this->trdid,
    366 1<<page->order, local_cxy, ppm_page2ppn(XPTR(local_cxy , page)) , cycle );
    367 #endif
    368 
    369 #if(DEBUG_PPM_FREE_PAGES & 0x1)
    370 if( DEBUG_PPM_FREE_PAGES < cycle )
    371 ppm_remote_display( local_cxy );
     367{
     368    printk("\n[%s] thread[%x,%x] released %d page(s) in cluster %x / ppn %x / cycle %d\n",
     369    __FUNCTION__, this->process->pid, this->trdid,
     370    1<<page->order, local_cxy, ppm_page2ppn(XPTR(local_cxy , page)) , cycle );
     371    ppm_remote_display( local_cxy );
     372}
    372373#endif
    373374
    374375}  // end ppm_free_pages()
     376
     377
     378
    375379
    376380/////////////////////////////////////////////
     
    387391#if DEBUG_PPM_REMOTE_ALLOC_PAGES
    388392uint32_t   cycle = (uint32_t)hal_get_cycles();
     393#endif
     394
     395#if ( DEBUG_PPM_REMOTE_ALLOC_PAGES & 1 )
    389396if( DEBUG_PPM_REMOTE_ALLOC_PAGES < cycle )
    390 printk("\n[%s] thread[%x,%x] enter for %d small page(s) in cluster %x / cycle %d\n",
    391 __FUNCTION__, this->process->pid, this->trdid, 1<<order, cxy, cycle );
    392 #endif
    393 
    394 #if(DEBUG_PPM_REMOTE_ALLOC_PAGES & 0x1)
    395 if( DEBUG_PPM_REMOTE_ALLOC_PAGES < cycle )
    396 ppm_remote_display( cxy );
     397{
     398    printk("\n[%s] thread[%x,%x] enter for %d small page(s) in cluster %x / cycle %d\n",
     399    __FUNCTION__, this->process->pid, this->trdid, 1<<order, cxy, cycle );
     400    ppm_remote_display( cxy );
     401}
    397402#endif
    398403
     
    485490
    486491#if DEBUG_PPM_REMOTE_ALLOC_PAGES
    487 cycle = (uint32_t)hal_get_cycles();
    488492if( DEBUG_PPM_REMOTE_ALLOC_PAGES < cycle )
    489 printk("\n[%s] thread[%x,%x] exit for %d page(s) / ppn = %x in cluster %x / cycle %d\n",
    490 __FUNCTION__, this->process->pid, this->trdid,
    491 1<<order, ppm_page2ppn(XPTR( local_cxy , found_block )), cxy, cycle );
    492 #endif
    493 
    494 #if(DEBUG_PPM_REMOTE_ALLOC_PAGES & 0x1)
    495 if( DEBUG_PPM_REMOTE_ALLOC_PAGES < cycle )
    496 ppm_remote_display( cxy );
     493{
     494    printk("\n[%s] thread[%x,%x] allocated %d page(s) in cluster %x / ppn %x / cycle %d\n",
     495    __FUNCTION__, this->process->pid, this->trdid,
     496    1<<order, cxy, ppm_page2ppn(XPTR( cxy , found_block )), cycle );
     497    ppm_remote_display( cxy );
     498}
    497499#endif
    498500
     
    501503}  // end ppm_remote_alloc_pages()
    502504
    503 //////////////////////////////////////////
    504 void ppm_remote_free_pages( cxy_t     cxy,
    505                             page_t  * page )
     505///////////////////////////////////////////////
     506void ppm_remote_free_pages( cxy_t     page_cxy,
     507                            page_t  * page_ptr )
    506508{
    507509    xptr_t     page_xp;          // extended pointer on released page descriptor
    508     uint32_t   order;            // released block order
    509         page_t   * buddy_ptr;        // searched buddy block page descriptor
    510     uint32_t   buddy_order;      // searched buddy block order
    511         uint32_t   buddy_index;      // buddy block index in page_tbl[]
    512         page_t   * current_ptr;      // current (merged) block page descriptor
    513         uint32_t   current_index;    // current (merged) block index in page_tbl[]
    514         uint32_t   current_order;    // current (merged) block order
     510        page_t   * buddy_ptr;        // searched buddy page descriptor
     511    uint32_t   buddy_order;      // searched buddy page order
     512        uint32_t   buddy_index;      // buddy page index in page_tbl[]
     513        page_t   * current_ptr;      // current (merged) page descriptor
     514        uint32_t   current_index;    // current (merged) page index in page_tbl[]
     515        uint32_t   current_order;    // current (merged) page order
    515516
    516517#if DEBUG_PPM_REMOTE_FREE_PAGES
    517518thread_t * this  = CURRENT_THREAD;
    518519uint32_t   cycle = (uint32_t)hal_get_cycles();
     520#endif
     521
     522#if ( DEBUG_PPM_REMOTE_FREE_PAGES & 1 )
    519523if( DEBUG_PPM_REMOTE_FREE_PAGES < cycle )
    520 printk("\n[%s] thread[%x,%x] enter for %d page(s) / cxy %x / ppn %x / cycle %d\n",
    521 __FUNCTION__, this->process->pid, this->trdid,
    522 1<<page->order, cxy, ppm_page2ppn(XPTR(cxy , page)), cycle );
    523 #endif
    524 
    525 #if(DEBUG_PPM_REMOTE_FREE_PAGES & 0x1)
    526 if( DEBUG_PPM_REMOTE_FREE_PAGES < cycle )
    527 ppm_remote_display( cxy );
     524{
     525    printk("\n[%s] thread[%x,%x] enter for %d page(s) in cluster %x / ppn %x / cycle %d\n",
     526    __FUNCTION__, this->process->pid, this->trdid,
     527    1<<page_ptr->order, page_cxy, ppm_page2ppn(XPTR( page_cxy , page_ptr )), cycle );
     528    ppm_remote_display( page_cxy );
     529}
    528530#endif
    529531
    530532    // build extended pointer on released page descriptor
    531     page_xp = XPTR( cxy , page );
     533    page_xp = XPTR( page_cxy , page_ptr );
    532534   
    533     // get released page order
    534     order = hal_remote_l32( XPTR( cxy , &page->order ) );
    535535
    536536    // get local pointer on PPM (same in all clusters)
     
    538538
    539539    // build extended pointer on lock protecting remote PPM
    540     xptr_t lock_xp = XPTR( cxy , &ppm->free_lock );
     540    xptr_t lock_xp = XPTR( page_cxy , &ppm->free_lock );
    541541
    542542    // get local pointer on remote PPM page_tbl[] array
    543         page_t * pages_tbl = hal_remote_lpt( XPTR( cxy , &ppm->pages_tbl ) );
     543        page_t * pages_tbl = hal_remote_lpt( XPTR( page_cxy , &ppm->pages_tbl ) );
    544544
    545545        // get lock protecting free_pages in remote cluster
     
    547547
    548548assert( !page_remote_is_flag( page_xp , PG_FREE ) ,
    549 "page already released : ppn = %x\n" , ppm_page2ppn(XPTR(local_cxy,page)) );
     549"page already released : ppn = %x\n" , ppm_page2ppn(XPTR( page_cxy , page_ptr ) ) );
    550550
    551551assert( !page_remote_is_flag( page_xp , PG_RESERVED ) ,
    552 "reserved page : ppn = %x\n" , ppm_page2ppn(XPTR(local_cxy,page)) );
    553 
    554         // update released page descriptor flags
     552"reserved page : ppn = %x\n" , ppm_page2ppn(XPTR( page_cxy , page_ptr ) ) );
     553
     554        // set the FREE flag in released page descriptor
    555555        page_remote_set_flag( page_xp , PG_FREE );
    556556
     557    // initialise loop variables
     558    current_ptr   = page_ptr;
     559    current_order = hal_remote_l32( XPTR( page_cxy , &page_ptr->order ) );
     560        current_index = page_ptr - ppm->pages_tbl;
     561
    557562        // search the buddy page descriptor
    558         // - merge with current page descriptor if found
    559         // - exit to release the current page descriptor if not found
    560         current_ptr   = page;
    561         current_index = (uint32_t)(page - ppm->pages_tbl);
    562         for( current_order = order ;
    563              current_order < CONFIG_PPM_MAX_ORDER ;
    564              current_order++ )
    565         {
     563        // - merge with current page descriptor if buddy found
     564        // - exit to release the current page descriptor if buddy not found
     565    while( current_order < CONFIG_PPM_MAX_ORDER )
     566    {
     567        // compute buddy page index and local pointer on page descriptor
    566568                buddy_index = current_index ^ (1 << current_order);
    567569                buddy_ptr   = pages_tbl + buddy_index;
    568 
    569         // get buddy block order
    570         buddy_order = hal_remote_l32( XPTR( cxy , &buddy_ptr->order ) );
    571 
    572         // exit loop if buddy block not found
    573                 if( !page_remote_is_flag( XPTR( cxy , buddy_ptr ) , PG_FREE ) ||
     570       
     571        // exit loop if buddy not found
     572                if( !page_remote_is_flag( XPTR( page_cxy , buddy_ptr ) , PG_FREE ) ||
    574573            (buddy_order != current_order) ) break;
    575574
    576                 // remove buddy from free list in remote cluster
    577                 list_remote_unlink( cxy , &buddy_ptr->list );
    578         hal_remote_atomic_add( XPTR( cxy , &ppm->free_pages_nr[current_order] ) , -1 );
    579 
    580         // reset order field in buddy block page descriptor
    581         hal_remote_s32( XPTR( cxy , &buddy_ptr->order ) , 0 );
    582 
    583                 // compute merged block index in page_tbl[] array
     575        // remove buddy page from its free list in remote cluster
     576                list_remote_unlink( page_cxy , &buddy_ptr->list );
     577        hal_remote_atomic_add( XPTR( page_cxy , &ppm->free_pages_nr[current_order] ) , -1 );
     578
     579        // reset order field in buddy page descriptor
     580        hal_remote_s32( XPTR( page_cxy , &buddy_ptr->order ) , 0 );
     581
     582                // compute next (merged) page index in page_tbl[]
    584583                current_index &= buddy_index;
    585         }
    586 
    587         // update merged page descriptor order field
     584
     585        // compute next (merged) page order
     586        current_order++;
     587
     588        // compute next (merged) page descripror
     589        current_ptr = pages_tbl + current_index;
     590
     591    }  // end loop on order
     592
     593        // update current (merged) page descriptor order field
    588594        current_ptr = pages_tbl + current_index;
    589     hal_remote_s32( XPTR( cxy , &current_ptr->order ) , current_order );
    590 
    591         // insert merged block into relevant free list in remote cluster
    592         list_remote_add_first( cxy , &ppm->free_pages_root[current_order] , &current_ptr->list );
    593     hal_remote_atomic_add( XPTR( cxy , &ppm->free_pages_nr[current_order] ) , 1 );
     595    hal_remote_s32( XPTR( page_cxy , &current_ptr->order ) , current_order );
     596
     597        // insert current (merged) page into relevant free list
     598        list_remote_add_first( page_cxy , &ppm->free_pages_root[current_order] , &current_ptr->list );
     599    hal_remote_atomic_add( XPTR( page_cxy , &ppm->free_pages_nr[current_order] ) , 1 );
    594600
    595601        // release lock protecting free_pages[] array
     
    597603
    598604    // update DQDT
    599     dqdt_decrement_pages( cxy , page->order );
     605    dqdt_decrement_pages( page_cxy , page_ptr->order );
    600606
    601607#if DEBUG_PPM_REMOTE_FREE_PAGES
    602 cycle = (uint32_t)hal_get_cycles();
    603608if( DEBUG_PPM_REMOTE_FREE_PAGES < cycle )
    604 printk("\n[%s] thread[%x,%x] exit for %d page(s) in cluster %x / ppn %x / cycle %d\n",
    605 __FUNCTION__, this->process->pid, this->trdid,
    606 1<<page->order, cxy, ppm_page2ppn(XPTR(cxy , page)), cycle );
    607 #endif
    608 
    609 #if(DEBUG_PPM_REMOTE_FREE_PAGES & 0x1)
    610 if( DEBUG_PPM_REMOTE_FREE_PAGES < cycle )
    611 ppm_remote_display( cxy );
     609{
     610    printk("\n[%s] thread[%x,%x] released %d page(s) in cluster %x / ppn %x / cycle %d\n",
     611    __FUNCTION__, this->process->pid, this->trdid,
     612    1<<page_ptr->order, page_cxy, ppm_page2ppn(XPTR( page_cxy , page_ptr ) ), cycle );
     613    ppm_remote_display( page_cxy );
     614}
    612615#endif
    613616
     
    622625
    623626    ppm_t * ppm = &LOCAL_CLUSTER->ppm;
     627
     628    // get remote PPM general parameters
     629    uint32_t   pages_nr   = hal_remote_l32( XPTR( cxy , &ppm->pages_nr ) );
     630    void     * vaddr_base = hal_remote_lpt( XPTR( cxy , &ppm->vaddr_base ) ); 
     631    void     * pages_tbl  = hal_remote_lpt( XPTR( cxy , &ppm->pages_tbl ) ); 
    624632
    625633    // build extended pointer on lock protecting remote PPM
     
    640648    remote_busylock_acquire( txt_lock_xp );
    641649
    642         nolock_printk("\n***** PPM in cluster %x / %d pages\n", local_cxy , ppm->pages_nr );
     650        nolock_printk("\n***** PPM in cluster %x / %d pages / page_tbl %x / vaddr_base %x\n",
     651    local_cxy, pages_nr, pages_tbl, vaddr_base );
    643652
    644653        for( order = 0 ; order < CONFIG_PPM_MAX_ORDER ; order++ )
     
    647656        uint32_t n = hal_remote_l32( XPTR( cxy , &ppm->free_pages_nr[order] ) );
    648657
    649                 nolock_printk("- order = %d / n = %d\t: ", order , n );
    650 
     658        // display direct free_list[order]
     659                nolock_printk("- forward  : order = %d / n = %d\t: ", order , n );
    651660                LIST_REMOTE_FOREACH( cxy , &ppm->free_pages_root[order] , iter )
    652661                {
    653             // build extended pointer on page descriptor
    654662            page_xp = XPTR( cxy , LIST_ELEMENT( iter , page_t , list ) );
    655 
    656             // display PPN
    657663                        nolock_printk("%x," , ppm_page2ppn( page_xp ) );
    658664                }
    659 
    660665                nolock_printk("\n");
    661666        }
Note: See TracChangeset for help on using the changeset viewer.