Changeset 606 for trunk/kernel/mm/ppm.c
- Timestamp:
- Dec 3, 2018, 12:20:18 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/mm/ppm.c
r585 r606 39 39 #include <mapper.h> 40 40 #include <ppm.h> 41 #include <vfs.h> 41 42 42 43 //////////////////////////////////////////////////////////////////////////////////////// … … 395 396 ////////////////////////////////////////////////////////////////////////////////////// 396 397 397 ///////////////////////////////////////// 398 bool_t ppm_page_do_dirty( page_t * page)398 ////////////////////////////////////////// 399 bool_t ppm_page_do_dirty( xptr_t page_xp ) 399 400 { 400 401 bool_t done = false; 401 402 403 // get page cluster and local pointer 404 page_t * page_ptr = GET_PTR( page_xp ); 405 cxy_t page_cxy = GET_CXY( page_xp ); 406 407 // get local pointer on PPM (same in all clusters) 402 408 ppm_t * ppm = &LOCAL_CLUSTER->ppm; 403 409 404 // lock the PPM dirty_list 405 queuelock_acquire( &ppm->dirty_lock ); 406 407 if( !page_is_flag( page , PG_DIRTY ) ) 410 // build extended pointers on page lock, page flags, and PPM dirty list lock 411 xptr_t page_lock_xp = XPTR( page_cxy , &page_ptr->lock ); 412 xptr_t page_flags_xp = XPTR( page_cxy , &page_ptr->flags ); 413 xptr_t dirty_lock_xp = XPTR( page_cxy , &ppm->dirty_lock ); 414 415 // lock the remote PPM dirty_list 416 remote_queuelock_acquire( dirty_lock_xp ); 417 418 // lock the remote page 419 remote_busylock_acquire( page_lock_xp ); 420 421 // get remote page flags 422 uint32_t flags = hal_remote_l32( page_flags_xp ); 423 424 if( (flags & PG_DIRTY) == 0 ) 408 425 { 409 426 // set dirty flag in page descriptor 410 page_set_flag( page , PG_DIRTY ); 411 412 // register page in PPM dirty list 413 list_add_first( &ppm->dirty_root , &page->list ); 427 hal_remote_s32( page_flags_xp , flags | PG_DIRTY ); 428 429 // The PPM dirty list is a LOCAL list !!! 430 // We must update 4 pointers to insert a new page in this list. 431 // We can use the standard LIST API when the page is local, 432 // but we cannot use the standard API if the page is remote... 433 434 if( page_cxy == local_cxy ) // locally update the PPM dirty list 435 { 436 list_add_first( &ppm->dirty_root , &page_ptr->list ); 437 } 438 else // remotely update the PPM dirty list 439 { 440 // get local and remote pointers on "root" list entry 441 list_entry_t * root = &ppm->dirty_root; 442 xptr_t root_xp = XPTR( page_cxy , root ); 443 444 // get local and remote pointers on "page" list entry 445 list_entry_t * list = &page_ptr->list; 446 xptr_t list_xp = XPTR( page_cxy , list ); 447 448 // get local and remote pointers on first dirty page 449 list_entry_t * dirt = hal_remote_lpt( XPTR( page_cxy, &root->next ) ); 450 xptr_t dirt_xp = XPTR( page_cxy , dirt ); 451 452 // set root.next, list.next, list pred, curr.pred in remote cluster 453 hal_remote_spt( root_xp , list ); 454 hal_remote_spt( list_xp , dirt ); 455 hal_remote_spt( list_xp + sizeof(intptr_t) , root ); 456 hal_remote_spt( dirt_xp + sizeof(intptr_t) , list ); 457 } 458 414 459 done = true; 415 460 } 416 461 417 // unlock the PPM dirty_list 418 queuelock_release( &ppm->dirty_lock ); 462 // unlock the remote page 463 remote_busylock_release( page_lock_xp ); 464 465 // unlock the remote PPM dirty_list 466 remote_queuelock_release( dirty_lock_xp ); 419 467 420 468 return done; 421 } 422 423 /////////////////////////////////////////// 424 bool_t ppm_page_undo_dirty( page_t * page ) 469 470 } // end ppm_page_do_dirty() 471 472 //////////////////////////////////////////// 473 bool_t ppm_page_undo_dirty( xptr_t page_xp ) 425 474 { 426 475 bool_t done = false; 427 476 477 // get page cluster and local pointer 478 page_t * page_ptr = GET_PTR( page_xp ); 479 cxy_t page_cxy = GET_CXY( page_xp ); 480 481 // get local pointer on PPM (same in all clusters) 428 482 ppm_t * ppm = &LOCAL_CLUSTER->ppm; 429 483 430 // lock the dirty_list 431 queuelock_acquire( &ppm->dirty_lock ); 432 433 if( page_is_flag( page , PG_DIRTY) ) 434 { 435 // clear dirty flag in page descriptor 436 page_clear_flag( page , PG_DIRTY ); 437 438 // remove page from PPM dirty list 439 list_unlink( &page->list ); 484 // build extended pointers on page lock, page flags, and PPM dirty list lock 485 xptr_t page_lock_xp = XPTR( page_cxy , &page_ptr->lock ); 486 xptr_t page_flags_xp = XPTR( page_cxy , &page_ptr->flags ); 487 xptr_t dirty_lock_xp = XPTR( page_cxy , &ppm->dirty_lock ); 488 489 // lock the remote PPM dirty_list 490 remote_queuelock_acquire( XPTR( page_cxy , &ppm->dirty_lock ) ); 491 492 // lock the remote page 493 remote_busylock_acquire( page_lock_xp ); 494 495 // get remote page flags 496 uint32_t flags = hal_remote_l32( page_flags_xp ); 497 498 if( (flags & PG_DIRTY) ) // page is dirty 499 { 500 // reset dirty flag in page descriptor 501 hal_remote_s32( page_flags_xp , flags & (~PG_DIRTY) ); 502 503 // The PPM dirty list is a LOCAL list !!! 504 // We must update 4 pointers to remove a page from this list. 505 // we can use the standard LIST API when the page is local, 506 // but we cannot use the standard API if the page is remote... 507 508 if( page_cxy == local_cxy ) // locally update the PPM dirty list 509 { 510 list_unlink( &page_ptr->list ); 511 } 512 else // remotely update the PPM dirty list 513 { 514 // get local and remote pointers on "page" list entry 515 list_entry_t * list = &page_ptr->list; 516 xptr_t list_xp = XPTR( page_cxy , list ); 517 518 // get local and remote pointers on "next" page list entry 519 list_entry_t * next = hal_remote_lpt( list_xp ); 520 xptr_t next_xp = XPTR( page_cxy , next ); 521 522 // get local and remote pointers on "pred" page list entry 523 list_entry_t * pred = hal_remote_lpt( list_xp + sizeof(intptr_t) ); 524 xptr_t pred_xp = XPTR( page_cxy , pred ); 525 526 // set root.next, list.next, list pred, curr.pred in remote cluster 527 hal_remote_spt( pred_xp , next ); 528 hal_remote_spt( list_xp , NULL ); 529 hal_remote_spt( list_xp + sizeof(intptr_t) , NULL ); 530 hal_remote_spt( next_xp + sizeof(intptr_t) , pred ); 531 } 532 440 533 done = true; 441 534 } 442 535 443 // unlock the dirty_list 444 queuelock_release( &ppm->dirty_lock ); 536 // unlock the remote page 537 remote_busylock_release( page_lock_xp ); 538 539 // unlock the remote PPM dirty_list 540 remote_queuelock_release( dirty_lock_xp ); 445 541 446 542 return done; 447 } 448 449 /////////////////////////////// 450 void ppm_sync_all_pages( void ) 451 { 452 page_t * page; 453 ppm_t * ppm = &LOCAL_CLUSTER->ppm; 543 544 } // end ppm_page_undo_dirty() 545 546 ///////////////////////////////// 547 void ppm_sync_dirty_pages( void ) 548 { 549 ppm_t * ppm = &LOCAL_CLUSTER->ppm; 550 551 // get local pointer on PPM dirty_root 552 list_entry_t * dirty_root = &ppm->dirty_root; 553 554 // build extended pointer on PPM dirty_lock 555 xptr_t dirty_lock_xp = XPTR( local_cxy , &ppm->dirty_lock ); 454 556 455 557 // get the PPM dirty_list lock 456 queuelock_acquire( &ppm->dirty_lock);558 remote_queuelock_acquire( dirty_lock_xp ); 457 559 458 560 while( !list_is_empty( &ppm->dirty_root ) ) 459 561 { 460 page = LIST_FIRST( &ppm->dirty_root , page_t , list ); 562 page_t * page = LIST_FIRST( dirty_root , page_t , list ); 563 xptr_t page_xp = XPTR( local_cxy , page ); 564 565 // build extended pointer on page lock 566 xptr_t page_lock_xp = XPTR( local_cxy , &page->lock ); 461 567 462 568 // get the page lock 463 remote_busylock_acquire( XPTR( local_cxy, &page->lock ));569 remote_busylock_acquire( page_lock_xp ); 464 570 465 571 // sync the page 466 vfs_ mapper_move_page( page , false ); // from mapper572 vfs_fs_move_page( page_xp , false ); // from mapper to device 467 573 468 574 // release the page lock 469 remote_busylock_release( XPTR( local_cxy , &page->lock ));575 remote_busylock_release( page_lock_xp ); 470 576 } 471 577 472 578 // release the PPM dirty_list lock 473 queuelock_release( &ppm->dirty_lock ); 474 } 475 579 remote_queuelock_release( dirty_lock_xp ); 580 581 } // end ppm_sync_dirty_pages() 582
Note: See TracChangeset
for help on using the changeset viewer.