/* Swap in a page on disk or on swap space, or initilize a zero page*/ bool swap_in (struct frame_struct *pframe) { struct block *device; size_t length = pframe->length; block_sector_t sector_no = pframe->sector_no; uint32_t pos = pframe->flag & POSBITS; uint32_t is_all_zero = pframe->flag & FS_ZERO; /* Get a frame, from memory or by evict another frame */ uint8_t *kpage = palloc_get_page (PAL_USER | PAL_ZERO); if (kpage == NULL) { /* Evict to get a frame */ kpage = sup_pt_evict_frame (); if (kpage == NULL) { return false; } } /* If zero page, just write a page of 0's */ if (is_all_zero) { memset (kpage, 0, PGSIZE); sup_pt_set_swap_in (pframe, kpage); return true; } /* On disk */ if (pos == POS_DISK) { /* Register filesys as block device */ device = fs_device; /* Whether a newly loaded exec file page or a swapped out mem-mapped file page they are not dirty */ pframe->flag &= ~FS_DIRTY; } /* On swap */ else if (pos == POS_SWAP) { /* Register swap as block device */ device = sp_device; } else { /* Already in memeory, other processes race to swap_in the frame */ palloc_free_page (kpage); return false; } if (device == fs_device) lock_acquire (&glb_lock_filesys); else lock_acquire (&glb_lock_swapsys); /* Read from disk or swap */ block_sector_t i; for (i = 0; i < PGSIZE / BLOCK_SECTOR_SIZE; i++) { block_read (device, sector_no + i, kpage + BLOCK_SECTOR_SIZE * i); } if (device == fs_device) lock_release (&glb_lock_filesys); else lock_release (&glb_lock_swapsys); /* Set remaining of the page to 0, only necessary for disk */ if ((length < PGSIZE) && (device == fs_device)) memset (kpage + length, 0, PGSIZE - length); /* Free swap table entries */ if (device == sp_device) { lock_acquire (&swap_set_lock); bitmap_set_multiple (swap_free_map, sector_no, PGSIZE / BLOCK_SECTOR_SIZE, false); lock_release (&swap_set_lock); } /* Update sup_pt entry information */ sup_pt_set_swap_in (pframe, kpage); return true; }
/* Makes CNT sectors starting at SECTOR available for use. */ void free_map_release (disk_sector_t sector, size_t cnt) { ASSERT (bitmap_all (free_map, sector, cnt)); bitmap_set_multiple (free_map, sector, cnt, false); bitmap_write (free_map, free_map_file); }