📈
ucore-analysis
  • Introduction
  • lab1
    • boot
      • bootasm
      • bootmain
    • kern
      • debug
        • kmonitor
        • panic
      • init
        • init
      • libs
        • readline
      • mm
        • pmm
      • trap
        • trap
        • trapentry
        • vectors
    • libs
    • tools
  • lab解析
    • lab1
      • 练习1
      • 练习2
      • 练习3
      • 练习4
      • 练习6
      • 扩展练习
      • Piazza优质问题/笔记收集
    • lab2
      • 练习1
      • 练习2
      • 练习3
    • lab3
    • lab4
    • lab5
    • lab6
    • lab7
    • lab8
  • uCore代码
    • boot
      • asm.h
      • bootasm.S
      • bootmain.c
      • (lab1) bootasm.S
    • kern
      • debug
        • assert.h
        • kdebug.c
        • kdebug.h
        • kmonitor.c
        • kmonitor.h
        • panic.c
        • stab.h
        • (lab1) kdebug.c
      • driver
        • clock.c
        • clock.h
        • console.c
        • console.h
        • ide.c
        • ide.h
        • intr.c
        • intr.h
        • kbdreg.h
        • picirq.c
        • picirq.h
      • fs
        • devs
          • dev.c
          • dev_disk0.c
          • dev.h
          • dev_stdin.c
          • dev_stdout.c
        • sfs
          • bitmap.c
          • bitmap.h
          • sfs.c
          • sfs_fs.c
          • sfs.h
          • sfs_inode.c
          • sfs_io.c
          • sfs_lock.c
        • swap
          • swapfs.c
          • swapfs.h
        • vfs
          • inode.c
          • inode.h
          • README.md
          • vfs.c
          • vfsdev.c
          • vfsfile.c
          • vfs.h
          • vfslookup.c
          • vfspath.c
        • file.c
        • file.h
        • fs.c
        • fs.h
        • iobuf.c
        • iobuf.h
        • sysfile.c
        • sysfile.h
      • init
        • entry.S
        • init.c
        • (lab1) init.c
      • libs
        • readline.c
        • stdio.c
        • string.c
      • mm
        • default_pmm.c
        • default_pmm.h
        • kmalloc.c
        • kmalloc.h
        • memlayout.h
        • mmu.h
        • pmm.c
        • pmm.h
        • swap.c
        • swap_fifo.c
        • swap_fifo.h
        • swap.h
        • vmm.c
        • vmm.h
        • (lab2) pmm.c
        • (lab3) vmm.c
      • process
        • entry.S
        • proc.c
        • proc.h
        • switch.S
        • (lab4) proc.c
        • (lab5) proc.c
      • schedule
        • default_sched.c
        • default_sched.h
        • default_sched_stride.c
        • sched.c
        • sched.h
      • sync
        • check_sync.c
        • monitor.c
        • monitor.h
        • sem.c
        • sem.h
        • sync.h
        • wait.c
        • wait.h
      • syscall
        • syscall.c
        • syscall.h
      • trap
        • trap.c
        • trapentry.S
        • trap.h
        • vectors.S
        • (lab1) trap.c
    • libs
      • atomic.h
      • defs.h
      • dirent.h
      • elf.h
      • error.h
      • hash.c
      • list.h
      • printfmt.c
      • rand.c
      • skew_heap.h
      • stat.h
      • stdarg.h
      • stdio.h
      • stdlib.h
      • string.c
      • string.h
      • unistd.h
      • x86.h
    • tools
      • boot.ld
      • function.mk
      • gdbinit
      • grade.sh
      • kernel.ld
      • mksfs.c
      • sign.c
      • user.ld
      • vector.c
    • user
      • libs
        • dir.c
        • dir.h
        • file.c
        • file.h
        • initcode.S
        • lock.h
        • panic.c
        • stdio.c
        • syscall.c
        • syscall.h
        • ulib.c
        • ulib.h
        • umain.c
      • badarg.c
      • badsegment.c
      • divzero.c
      • exit.c
      • faultread.c
      • faultreadkernel.c
      • forktest.c
      • forktree.c
      • hello.c
      • ls.c
      • matrix.c
      • pgdir.c
      • priority.c
      • sfs_filetest1.c
      • sh.c
      • sleep.c
      • sleepkill.c
      • softint.c
      • spin.c
      • testbss.c
      • waitkill.c
      • yield.c
    • Makefile
    • (lab1) Makefile
  • 附录:工具使用
    • 如何编辑该文档
    • 讨论区的维护方法
    • 使用Travis CI自动化更新gitbook
Powered by GitBook
On this page

Was this helpful?

  1. uCore代码
  2. kern
  3. mm

swap.c

#include <swap.h>
#include <swapfs.h>
#include <swap_fifo.h>
#include <stdio.h>
#include <string.h>
#include <memlayout.h>
#include <pmm.h>
#include <mmu.h>
#include <default_pmm.h>
#include <kdebug.h>

// the valid vaddr for check is between 0~CHECK_VALID_VADDR-1
#define CHECK_VALID_VIR_PAGE_NUM 5
#define BEING_CHECK_VALID_VADDR 0X1000
#define CHECK_VALID_VADDR (CHECK_VALID_VIR_PAGE_NUM+1)*0x1000
// the max number of valid physical page for check
#define CHECK_VALID_PHY_PAGE_NUM 4
// the max access seq number
#define MAX_SEQ_NO 10

static struct swap_manager *sm;
size_t max_swap_offset;

volatile int swap_init_ok = 0;

unsigned int swap_page[CHECK_VALID_VIR_PAGE_NUM];

unsigned int swap_in_seq_no[MAX_SEQ_NO],swap_out_seq_no[MAX_SEQ_NO];

static void check_swap(void);

int
swap_init(void)
{
     swapfs_init();

     if (!(1024 <= max_swap_offset && max_swap_offset < MAX_SWAP_OFFSET_LIMIT))
     {
          panic("bad max_swap_offset %08x.\n", max_swap_offset);
     }


     sm = &swap_manager_fifo;
     int r = sm->init();

     if (r == 0)
     {
          swap_init_ok = 1;
          cprintf("SWAP: manager = %s\n", sm->name);
          check_swap();
     }

     return r;
}

int
swap_init_mm(struct mm_struct *mm)
{
     return sm->init_mm(mm);
}

int
swap_tick_event(struct mm_struct *mm)
{
     return sm->tick_event(mm);
}

int
swap_map_swappable(struct mm_struct *mm, uintptr_t addr, struct Page *page, int swap_in)
{
     return sm->map_swappable(mm, addr, page, swap_in);
}

int
swap_set_unswappable(struct mm_struct *mm, uintptr_t addr)
{
     return sm->set_unswappable(mm, addr);
}

volatile unsigned int swap_out_num=0;

int
swap_out(struct mm_struct *mm, int n, int in_tick)
{
     int i;
     for (i = 0; i != n; ++ i)
     {
          uintptr_t v;
          //struct Page **ptr_page=NULL;
          struct Page *page;
          // cprintf("i %d, SWAP: call swap_out_victim\n",i);
          int r = sm->swap_out_victim(mm, &page, in_tick);
          if (r != 0) {
                    cprintf("i %d, swap_out: call swap_out_victim failed\n",i);
                  break;
          }          
          //assert(!PageReserved(page));

          //cprintf("SWAP: choose victim page 0x%08x\n", page);

          v=page->pra_vaddr; 
          pte_t *ptep = get_pte(mm->pgdir, v, 0);
          assert((*ptep & PTE_P) != 0);

          if (swapfs_write( (page->pra_vaddr/PGSIZE+1)<<8, page) != 0) {
                    cprintf("SWAP: failed to save\n");
                    sm->map_swappable(mm, v, page, 0);
                    continue;
          }
          else {
                    cprintf("swap_out: i %d, store page in vaddr 0x%x to disk swap entry %d\n", i, v, page->pra_vaddr/PGSIZE+1);
                    *ptep = (page->pra_vaddr/PGSIZE+1)<<8;
                    free_page(page);
          }

          tlb_invalidate(mm->pgdir, v);
     }
     return i;
}

int
swap_in(struct mm_struct *mm, uintptr_t addr, struct Page **ptr_result)
{
     struct Page *result = alloc_page();
     assert(result!=NULL);

     pte_t *ptep = get_pte(mm->pgdir, addr, 0);
     // cprintf("SWAP: load ptep %x swap entry %d to vaddr 0x%08x, page %x, No %d\n", ptep, (*ptep)>>8, addr, result, (result-pages));

     int r;
     if ((r = swapfs_read((*ptep), result)) != 0)
     {
        assert(r!=0);
     }
     cprintf("swap_in: load disk swap entry %d with swap_page in vadr 0x%x\n", (*ptep)>>8, addr);
     *ptr_result=result;
     return 0;
}



static inline void
check_content_set(void)
{
     *(unsigned char *)0x1000 = 0x0a;
     assert(pgfault_num==1);
     *(unsigned char *)0x1010 = 0x0a;
     assert(pgfault_num==1);
     *(unsigned char *)0x2000 = 0x0b;
     assert(pgfault_num==2);
     *(unsigned char *)0x2010 = 0x0b;
     assert(pgfault_num==2);
     *(unsigned char *)0x3000 = 0x0c;
     assert(pgfault_num==3);
     *(unsigned char *)0x3010 = 0x0c;
     assert(pgfault_num==3);
     *(unsigned char *)0x4000 = 0x0d;
     assert(pgfault_num==4);
     *(unsigned char *)0x4010 = 0x0d;
     assert(pgfault_num==4);
}

static inline int
check_content_access(void)
{
    int ret = sm->check_swap();
    return ret;
}

struct Page * check_rp[CHECK_VALID_PHY_PAGE_NUM];
pte_t * check_ptep[CHECK_VALID_PHY_PAGE_NUM];
unsigned int check_swap_addr[CHECK_VALID_VIR_PAGE_NUM];

extern free_area_t free_area;

#define free_list (free_area.free_list)
#define nr_free (free_area.nr_free)

static void
check_swap(void)
{
    //backup mem env
     int ret, count = 0, total = 0, i;
     list_entry_t *le = &free_list;
     while ((le = list_next(le)) != &free_list) {
        struct Page *p = le2page(le, page_link);
        assert(PageProperty(p));
        count ++, total += p->property;
     }
     assert(total == nr_free_pages());
     cprintf("BEGIN check_swap: count %d, total %d\n",count,total);

     //now we set the phy pages env     
     struct mm_struct *mm = mm_create();
     assert(mm != NULL);

     extern struct mm_struct *check_mm_struct;
     assert(check_mm_struct == NULL);

     check_mm_struct = mm;

     pde_t *pgdir = mm->pgdir = boot_pgdir;
     assert(pgdir[0] == 0);

     struct vma_struct *vma = vma_create(BEING_CHECK_VALID_VADDR, CHECK_VALID_VADDR, VM_WRITE | VM_READ);
     assert(vma != NULL);

     insert_vma_struct(mm, vma);

     //setup the temp Page Table vaddr 0~4MB
     cprintf("setup Page Table for vaddr 0X1000, so alloc a page\n");
     pte_t *temp_ptep=NULL;
     temp_ptep = get_pte(mm->pgdir, BEING_CHECK_VALID_VADDR, 1);
     assert(temp_ptep!= NULL);
     cprintf("setup Page Table vaddr 0~4MB OVER!\n");

     for (i=0;i<CHECK_VALID_PHY_PAGE_NUM;i++) {
          check_rp[i] = alloc_page();
          assert(check_rp[i] != NULL );
          assert(!PageProperty(check_rp[i]));
     }
     list_entry_t free_list_store = free_list;
     list_init(&free_list);
     assert(list_empty(&free_list));

     //assert(alloc_page() == NULL);

     unsigned int nr_free_store = nr_free;
     nr_free = 0;
     for (i=0;i<CHECK_VALID_PHY_PAGE_NUM;i++) {
        free_pages(check_rp[i],1);
     }
     assert(nr_free==CHECK_VALID_PHY_PAGE_NUM);

     cprintf("set up init env for check_swap begin!\n");
     //setup initial vir_page<->phy_page environment for page relpacement algorithm 


     pgfault_num=0;

     check_content_set();
     assert( nr_free == 0);         
     for(i = 0; i<MAX_SEQ_NO ; i++) 
         swap_out_seq_no[i]=swap_in_seq_no[i]=-1;

     for (i= 0;i<CHECK_VALID_PHY_PAGE_NUM;i++) {
         check_ptep[i]=0;
         check_ptep[i] = get_pte(pgdir, (i+1)*0x1000, 0);
         //cprintf("i %d, check_ptep addr %x, value %x\n", i, check_ptep[i], *check_ptep[i]);
         assert(check_ptep[i] != NULL);
         assert(pte2page(*check_ptep[i]) == check_rp[i]);
         assert((*check_ptep[i] & PTE_P));          
     }
     cprintf("set up init env for check_swap over!\n");
     // now access the virt pages to test  page relpacement algorithm 
     ret=check_content_access();
     assert(ret==0);

     //restore kernel mem env
     for (i=0;i<CHECK_VALID_PHY_PAGE_NUM;i++) {
         free_pages(check_rp[i],1);
     } 

     //free_page(pte2page(*temp_ptep));
    free_page(pde2page(pgdir[0]));
     pgdir[0] = 0;
     mm->pgdir = NULL;
     mm_destroy(mm);
     check_mm_struct = NULL;

     nr_free = nr_free_store;
     free_list = free_list_store;


     le = &free_list;
     while ((le = list_next(le)) != &free_list) {
         struct Page *p = le2page(le, page_link);
         count --, total -= p->property;
     }
     cprintf("count is %d, total is %d\n",count,total);
     //assert(count == 0);

     cprintf("check_swap() succeeded!\n");
}
Previouspmm.hNextswap_fifo.c

Last updated 5 years ago

Was this helpful?