Changeset 567 for trunk/kernel/mm/page.c


Ignore:
Timestamp:
Oct 5, 2018, 12:01:52 AM (4 years ago)
Author:
alain
Message:

Complete restructuration of kernel locks.

File:
1 edited

Legend:

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

    r486 r567  
    2727#include <hal_atomic.h>
    2828#include <list.h>
    29 #include <xlist.h>
     29#include <queuelock.h>
    3030#include <memcpy.h>
    31 #include <thread.h>
    32 #include <scheduler.h>
    33 #include <cluster.h>
    34 #include <ppm.h>
    35 #include <mapper.h>
    3631#include <printk.h>
    3732#include <vfs.h>
    3833#include <process.h>
    3934#include <page.h>
     35
    4036
    4137////////////////////////////////////////
     
    4945        page->forks    = 0;
    5046
    51         spinlock_init( &page->lock );
     47        remote_busylock_init( XPTR( local_cxy , &page->lock ), LOCK_PAGE_STATE );
     48
    5249        list_entry_init( &page->list );
    53     xlist_root_init( XPTR( local_cxy , &page->wait_root ) );
    5450}
    5551
     
    7369{
    7470    return ( (page->flags & value) ? 1 : 0 );
    75 }
    76 
    77 //////////////////////////////////////
    78 bool_t page_do_dirty( page_t * page )
    79 {
    80         bool_t done = false;
    81 
    82         ppm_t * ppm = &LOCAL_CLUSTER->ppm;
    83 
    84         // lock the PPM dirty_list
    85         spinlock_lock( &ppm->dirty_lock );
    86 
    87         if( !page_is_flag( page , PG_DIRTY ) )
    88         {
    89                 // set dirty flag in page descriptor
    90                 page_set_flag( page , PG_DIRTY );
    91 
    92                 // register page in PPM dirty list
    93                 list_add_first( &ppm->dirty_root , &page->list );
    94                 done = true;
    95         }
    96 
    97         // unlock the PPM dirty_list
    98         spinlock_unlock( &ppm->dirty_lock );
    99 
    100         return done;
    101 }
    102 
    103 ////////////////////////////////////////
    104 bool_t page_undo_dirty( page_t * page )
    105 {
    106         bool_t done = false;
    107 
    108         ppm_t * ppm = &LOCAL_CLUSTER->ppm;
    109 
    110         // lock the dirty_list
    111         spinlock_lock( &ppm->dirty_lock );
    112 
    113         if( page_is_flag( page , PG_DIRTY) )
    114         {
    115                 // clear dirty flag in page descriptor
    116                 page_clear_flag( page , PG_DIRTY );
    117 
    118                 // remove page from PPM dirty list
    119                 list_unlink( &page->list );
    120                 done = true;
    121         }
    122 
    123         // unlock the dirty_list
    124         spinlock_unlock( &ppm->dirty_lock );
    125 
    126         return done;
    127 }
    128 
    129 /////////////////////
    130 void sync_all_pages( void )
    131 {
    132         page_t   * page;
    133         ppm_t    * ppm = &LOCAL_CLUSTER->ppm;
    134 
    135         // lock the dirty_list
    136         spinlock_lock( &ppm->dirty_lock );
    137 
    138         while( !list_is_empty( &ppm->dirty_root ) )
    139         {
    140                 page = LIST_FIRST( &ppm->dirty_root ,  page_t , list );
    141 
    142                 // unlock the dirty_list
    143                 spinlock_unlock( &ppm->dirty_lock );
    144 
    145                 // lock the page
    146                 page_lock( page );
    147 
    148                 // sync the page
    149                 vfs_mapper_move_page( page , false );  // from mapper
    150 
    151                 // unlock the page
    152                 page_unlock( page );
    153 
    154                 // lock the dirty_list
    155                 spinlock_lock( &ppm->dirty_lock );
    156         }
    157 
    158         // unlock the dirty_list
    159         spinlock_unlock( &ppm->dirty_lock );
    160 
    161 }
    162 
    163 ///////////////////////////////
    164 void page_lock( page_t * page )
    165 {
    166         // take the spinlock protecting the PG_LOCKED flag
    167         spinlock_lock( &page->lock );
    168 
    169         if( page_is_flag( page , PG_LOCKED ) )  // page is already locked
    170         {
    171                 // get pointer on calling thread
    172                 thread_t * thread = CURRENT_THREAD;
    173 
    174                 // register thread in the page waiting queue
    175                 xlist_add_last( XPTR( local_cxy , &page->wait_root ),
    176                                 XPTR( local_cxy , &thread->wait_list ) );
    177 
    178                 // release the spinlock
    179                 spinlock_unlock( &page->lock );
    180 
    181                 // deschedule the calling thread
    182                 thread_block( XPTR( local_cxy , thread ) , THREAD_BLOCKED_PAGE );
    183                 sched_yield("cannot lock a page");
    184         }
    185         else                                    // page is not locked
    186         {
    187                 // set the PG_LOCKED flag
    188                 page_set_flag( page , PG_LOCKED );
    189 
    190                 // release the spinlock
    191                 spinlock_unlock( &page->lock );
    192         }
    193 }
    194 
    195 /////////////////////////////////
    196 void page_unlock( page_t * page )
    197 {
    198         // take the spinlock protecting the PG_LOCKED flag
    199         spinlock_lock( &page->lock );
    200 
    201         // check the page waiting list
    202         bool_t is_empty = xlist_is_empty( XPTR( local_cxy , &page->wait_root ) );
    203 
    204         if( is_empty == false )    // at least one waiting thread => resume it
    205         {
    206                 // get an extended pointer on the first waiting thread
    207                 xptr_t root_xp   = XPTR( local_cxy , &page->wait_root );
    208                 xptr_t thread_xp = XLIST_FIRST_ELEMENT( root_xp , thread_t , wait_list );
    209 
    210                 // reactivate the first waiting thread
    211                 thread_unblock( thread_xp , THREAD_BLOCKED_PAGE );
    212         }
    213         else                      // no waiting thread => clear the PG_LOCKED flag
    214         {
    215                 page_clear_flag( page , PG_LOCKED );
    216         }
    217 
    218         // release the spinlock
    219         spinlock_unlock( &page->lock );
    22071}
    22172
Note: See TracChangeset for help on using the changeset viewer.