Ejemplo n.º 1
0
//Swap out memory to the disk. The src_addr points to a page worth of user
//memory. This will be read into the swap space. The disk_block pointer
//will get set to the location at which the memory was stored.
void
swap_out (uint32_t *src_addr, block_sector_t *disk_block)
{
  lock_acquire(&st->swap_table_lock);
  //Find available space on disk in the swap space
  block_sector_t block_offset = bitmap_scan_and_flip(st->map, 0,
                                           PGSIZE/BLOCK_SECTOR_SIZE, false);
  if (block_offset == BITMAP_ERROR)
  {
    lock_release(&st->swap_table_lock);
    PANIC ("BITMAP error in scanning swap space for block offset");
  }
  //Update disk_block to the location on disk where the memory is being stored
  lock_release(&st->swap_table_lock);

  //write the memory from the src_addr onto the block
  int i = 0;
  for (i = 0; i<PGSIZE; i += BLOCK_SECTOR_SIZE)
  {
    block_write (st->swap_block, i/BLOCK_SECTOR_SIZE + block_offset,
                 src_addr + i/sizeof(uint32_t));
  }

  *disk_block = block_offset;  
}
Ejemplo n.º 2
0
/* Obtains and returns a group of PAGE_CNT contiguous free pages.
   If PAL_USER is set, the pages are obtained from the user pool,
   otherwise from the kernel pool.  If PAL_ZERO is set in FLAGS,
   then the pages are filled with zeros.  If too few pages are
   available, returns a null pointer, unless PAL_ASSERT is set in
   FLAGS, in which case the kernel panics. */
void *
palloc_get_multiple (enum palloc_flags flags, size_t page_cnt)
{
  struct pool *pool = flags & PAL_USER ? &user_pool : &kernel_pool;
  void *pages;
  size_t page_idx;

  if (page_cnt == 0)
    return NULL;

  lock_acquire (&pool->lock);
  page_idx = bitmap_scan_and_flip (pool->used_map, 0, page_cnt, false);
  lock_release (&pool->lock);

  if (page_idx != BITMAP_ERROR)
    pages = pool->base + PGSIZE * page_idx;
  else
    pages = NULL;

  if (pages != NULL) 
    {
      if (flags & PAL_ZERO)
        memset (pages, 0, PGSIZE * page_cnt);
    }
  else 
    {
      if (flags & PAL_ASSERT)
        PANIC ("palloc_get: out of pages");
    }

  return pages;
}
Ejemplo n.º 3
0
// returns the start sector of the swap slot where upage is written
// all the vacant swap slots are set to FALSE
size_t
swap_write (void *kpage)
{
//  ASSERT (kpage);
//  printf ("Swap write called for %p\n",upage);
  lock_acquire (&swap_table_lock);

  size_t idx = bitmap_scan_and_flip (swap_table, 0, SLOT_SIZE, false);
  if (idx == BITMAP_ERROR) {
    PANIC ("No more swap slot avaiable\n");
  }

  struct disk *swap = disk_get (1,1);
  if (!swap)
    PANIC ("No swap disk found\n");

  int offset;
  for (offset = 0; offset < SLOT_SIZE; offset++) {
    //disk_write (swap, idx + offset, upage + (offset * DISK_SECTOR_SIZE));
    disk_write (swap, idx + offset, kpage + (offset * DISK_SECTOR_SIZE));
  }

  lock_release (&swap_table_lock);
  return idx;
}
Ejemplo n.º 4
0
struct cached_block* get_free_cache_buff(){
	if(INODE_DEBUG) printf("get_free_cache_buff()\n");
	int idx = bitmap_scan_and_flip(cache_bitmap, 0, 1, FREE);
	
	if(idx != BITMAP_ERROR){
		
		struct cached_block* newblock = buffcache + idx;
		if(INODE_DEBUG) printf("get_free_cache_buff(): idx %d buffcache %x newblock %x buffcache+BUFF_CACHE_SIZE %x\n", idx, buffcache, newblock, buffcache+N_BUFFERS);
		
		memset(newblock, 0, sizeof(struct cached_block));
		
		list_push_front(&buffcachelist, &newblock->elem);
		
		
		return newblock;
	}
	else{
		struct cached_block* last_block = list_entry(list_back(&buffcache), struct cached_block, elem);
		cache_flush(NULL, last_block->sector);
		list_remove(&last_block->elem);
		traverse_buffcachelist();
		list_push_front(&buffcachelist, &last_block->elem);
		memset(last_block->data, 0, BLOCK_SECTOR_SIZE);
		last_block->inode=NULL;
		last_block->sector=0;
		if(INODE_DEBUG) printf("get_free_cache_buff(): idx %d buffcache %x lastblock %x buffcache+BUFF_CACHE_SIZE %x\n", idx, buffcache, last_block, buffcache+N_BUFFERS);
		return last_block;
	}
}
Ejemplo n.º 5
0
/* Allocates CNT consecutive sectors from the free map and stores
   the first into *SECTORP.
   Returns true if successful, false if not enough consecutive
   sectors were available or if the free_map file could not be
   written. */
bool
free_map_allocate (size_t cnt, block_sector_t *sectorp)
{
  block_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false);
  if (sector != BITMAP_ERROR)
    *sectorp = sector;
  return sector != BITMAP_ERROR;
}
Ejemplo n.º 6
0
Archivo: swap.c Proyecto: kch31411/os
disk_sector_t
swap_get_slot (void)
{
  lock_acquire (&swap_bitmap_lock);
  disk_sector_t ret = bitmap_scan_and_flip (swap_slot, 0, SEC_PER_PG, false);
  lock_release (&swap_bitmap_lock);

  return ret;
}
Ejemplo n.º 7
0
Archivo: swap.c Proyecto: songhan/CS140
/* Allocate one frame in the swap block
 * Returns the swap_frame_number */
size_t
swap_allocate_page ( struct swap_table * swap_table)
{
  lock_acquire (&swap_table->lock_bitmap);
  size_t swap_frame_no = bitmap_scan_and_flip (swap_table->bitmap, 0, 1, false);
  lock_release(&swap_table->lock_bitmap);
  if (swap_frame_no == BITMAP_ERROR)
    PANIC ("out of swap space");
  return swap_frame_no;
}
Ejemplo n.º 8
0
uint32_t swap_out(void *frame)
{
	uint32_t index = bitmap_scan_and_flip(swap_bitmap, 0, 1, 0);

	int i;
	for(i=0;i<SECTOR_PER_PAGE;i++)
		disk_write(swap_disk, (index * SECTOR_PER_PAGE) + i, frame + (i * DISK_SECTOR_SIZE));

	return index;
}
Ejemplo n.º 9
0
static size_t
get_swap_slot (void) {
  lock_acquire (&swap_lock);
  size_t swap_idx = bitmap_scan_and_flip (used_map, 0, 1, false);
  lock_release (&swap_lock);
  if (swap_idx == BITMAP_ERROR) {
    PANIC ("SWAP PARTITION IS FULL");
  }

  return swap_idx * SECTORS_PER_SWAP;
}
Ejemplo n.º 10
0
void *
allocator_alloc (struct allocator *a, size_t amount)
{
  ASSERT (a != NULL);
  if (amount == 0)
    return NULL;
  size_t result = bitmap_scan_and_flip (a->used_map, 0, amount, false);
  if (result == BITMAP_ERROR)
    return NULL;
  return item_pos (a, result);
}
Ejemplo n.º 11
0
/* Allocates a page-sized swap slot, returning the swapid of the allocated
   slot. Panics the kernel if no such free slot exists. */
swapid_t
swap_alloc (void)
{
  ASSERT (swap_block != NULL);
  lock_acquire (&swap_alloc_lock);
  size_t id = bitmap_scan_and_flip (free_blocks, 0, 1, true);
  if (id == BITMAP_ERROR)
    PANIC ("swap_alloc: out of swap space");

  lock_release (&swap_alloc_lock);
  return id;
}
Ejemplo n.º 12
0
/* Given a kernel page address (which corresponds to a frame)
   Swap a frame to swap disk and return the start index of it in swap table.
   If swap table is full, panic the kernel. */
size_t 
swap_to_disk (uint8_t *kpage)
{
	if (!lock_held_by_current_thread (&swap_table_lock))
	  lock_acquire (&swap_table_lock);
	size_t index = bitmap_scan_and_flip (swap_table, 0, 1, false);
	if (index == BITMAP_ERROR)
	  PANIC ("Swap table is full");
	int i = 0;
	for (i = 0; i < 8; i++) 
	  block_write (swap_block, index * 8 + i, kpage + i * BLOCK_SECTOR_SIZE);
	lock_release (&swap_table_lock);
	return index;
}
Ejemplo n.º 13
0
//switches from main memory to swap disk
size_t swap_out (void *frame){
  if (!swap_block || !swap_map)
      PANIC("Need swap partition but no swap partition present!"); //Goes into panic mode if there is no swap block or 									     map basically the partition does not exist
  lock_acquire(&swap_lock); //Acquires the lock status
  size_t free_index = bitmap_scan_and_flip(swap_map, 0, 1, SWAP_FREE);
  if (free_index == BITMAP_ERROR)
      PANIC("Swap partition is full!"); //Goes into panic mode when there is a bitmap error for the particular index which basically means the partition is now full 
  size_t i;
  for (i = 0; i < SECTORS_PER_PAGE; i++){ //Block writer 
      block_write(swap_block, free_index * SECTORS_PER_PAGE + i,
      (uint8_t *) frame + i * BLOCK_SECTOR_SIZE);
    }
  lock_release(&swap_lock); //Releases swap lock status
  return free_index; //Returns the free index
}
Ejemplo n.º 14
0
/* Allocates CNT consecutive sectors from the free map and stores
   the first into *SECTORP.
   Returns true if successful, false if not enough consecutive
   sectors were available or if the free_map file could not be
   written. */
bool
free_map_allocate (size_t cnt, block_sector_t *sectorp)
{
    block_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false);
    if (sector != BITMAP_ERROR
            && free_map_file != NULL
            && !bitmap_write (free_map, free_map_file))
    {
        bitmap_set_multiple (free_map, sector, cnt, false);
        sector = BITMAP_ERROR;
    }
    if (sector != BITMAP_ERROR)
        *sectorp = sector;
    return sector != BITMAP_ERROR;
}
Ejemplo n.º 15
0
/* move data from frame to swap slot */
size_t vm_swap_out(void *page){
    lock_acquire(&swap_lock);

    size_t idx = bitmap_scan_and_flip(swap_partition, 0, 1, false);
    if (idx == BITMAP_ERROR){
        /* No free slot */
        lock_release(&swap_lock);
        PANIC("Swap partition is full\n");
    }

    size_t i;
    for (i = 0; i < SECTORS_PER_PAGE ; i++)
        block_write(swap_slot, (idx * SECTORS_PER_PAGE) + i, page + (i * BLOCK_SECTOR_SIZE));
    
    lock_release(&swap_lock);
    return idx;
}
Ejemplo n.º 16
0
/* Swaps out page P, which must have a locked frame. */
bool swap_out(void *f) {
	if (!swap_device || !swap_bitmap) {
		PANIC("No swap partition available!");
	}
	lock_acquire(&swap_lock);
	size_t free_index = bitmap_scan_and_flip(swap_bitmap, 0, 1, SWAP_FREE);
	lock_release(&swap_lock);

	if (free_index == BITMAP_ERROR) {
		PANIC("Swap partition is full!");
	}
	size_t i;
	for (i = 0; i < SECTORS_PER_PAGE; i++) {
		block_write(swap_device, free_index * SECTORS_PER_PAGE + i,
				(uint8_t *) f + i * BLOCK_SECTOR_SIZE);
	}
	return free_index;
}
Ejemplo n.º 17
0
/* Allocates CNT consecutive sectors from the free map and stores
   the first into *SECTORP.
   Returns true if successful, false if not enough consecutive
   sectors were available or if the free_map file could not be
   written. */
bool
free_map_allocate (size_t cnt, block_sector_t *sectorp)
{
  block_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false);
  if (sector != BITMAP_ERROR
      && free_map_file != NULL
      && !bitmap_write (free_map, free_map_file))
    {
      bitmap_set_multiple (free_map, sector, cnt, false); 
      sector = BITMAP_ERROR;
    }
  if (sector != BITMAP_ERROR){
    *sectorp = sector;
    char zeroes[BLOCK_SECTOR_SIZE]; //Assignment 4
    block_write(fs_device, sector,zeroes); //Assignment 4
  }
    
  return sector != BITMAP_ERROR;
}
Ejemplo n.º 18
0
uint32_t swap_write (const void *from)
{
  uint32_t res, i;
  lock_acquire (&swap_lock);
  {
    size_t ind = bitmap_scan_and_flip (swap_bitmap, 0, 1, false);
    if (ind== BITMAP_ERROR)
    {
      PANIC ("no more swap space");
    }
    res = ind;
    for (i = 0u; i < blocks_per_page; i++)
    {
      block_write (swap_block, ind * blocks_per_page + i,
        (const char *)from + i * BLOCK_SECTOR_SIZE);
    }
  }
  lock_release (&swap_lock);
  return res;
}
Ejemplo n.º 19
0
size_t
pick_slot_and_swap (void *page)
{
  /* Finds the first slot which has value false (so it's free) and flips it,
     returning the index */
  size_t index = bitmap_scan_and_flip (swap_slot_map, 0, 1, false);

  /* Write the ith BLOCK_SECTOR_SIZE bytes of the page to the block device. We
     have a mapping of SECTORS_PER_PAGE block sectors for every bit in the
     bitmap, so we can just multiply the index we got back by SECTORS_PER_PAGE
     to find the correct block sector to write to, and then increment this
     block sector index in each loop iteration */
  int i = 0;
  for (; i < SECTORS_PER_PAGE; ++i)
    {
      block_write (block_device, (index * SECTORS_PER_PAGE) + i,
                   page + (BLOCK_SECTOR_SIZE * i));
    }
  return index;
}
Ejemplo n.º 20
0
//Swap into memory from the disk. Swap_in must only be called if swap_out was
//previously called, and disk_block must be the same disk_block from swap_out.
//dest_addr should point to a page worth of memory to swap data into.
void
swap_in (uint32_t *dest_addr, block_sector_t *disk_block)
{
  int i = 0;
  block_sector_t block_offset = *disk_block;
  //Read in a page worth of memory
  for(i = 0; i<PGSIZE; i += BLOCK_SECTOR_SIZE)
  {
    block_read (st->swap_block, i/BLOCK_SECTOR_SIZE + block_offset,
                dest_addr + i/sizeof(uint32_t));
  }

  //Update the swap_table that this disk space is free again
  lock_acquire(&st->swap_table_lock);
  block_sector_t idx = bitmap_scan_and_flip(st->map, block_offset,
                                            PGSIZE/BLOCK_SECTOR_SIZE, true);
  //Assert that the page read in was previously marked as in use
  ASSERT(idx == block_offset);
  lock_release(&st->swap_table_lock);
}
Ejemplo n.º 21
0
void add_page_to_swapfile(struct page_info* p) {
	lock_acquire(&swap_lock);

	// Find the first open 4KB slot in the swap file
	unsigned int index = bitmap_scan_and_flip(swapmap, 0, 1, false);
	ASSERT(index != BITMAP_ERROR);
	ASSERT(bitmap_test(swapmap, index));  // should be true i.e. occupied

	// Write out the passed-in page to that 4KB slot
	// We're going to need to write out eight sectors, one at a time
	block_sector_t sector_index = index * SECTORS_PER_PAGE;
	int i;
	for(i = 0; i < SECTORS_PER_PAGE; i++) {
		block_sector_t target_sector = sector_index + i;
		void* source_buf = (uint8_t *)p->virtual_address + (i * BLOCK_SECTOR_SIZE);
		block_write(swap_block, target_sector, source_buf);
	}

	p->swap_info.swap_index = index;
	lock_release(&swap_lock);
}
Ejemplo n.º 22
0
/* Allocates CNT consecutive sectors from the free map and stores
   the first into *SECTORP.
   Returns true if successful, false if all sectors were
   available. */
bool
free_map_allocate (size_t cnt, disk_sector_t *sectorp) 
{
  // lås id 6
  lock_acquire(&free_map_lock);

  disk_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false);
  if (sector != BITMAP_ERROR
      && free_map_file != NULL
      && !bitmap_write (free_map, free_map_file))
    {
      bitmap_set_multiple (free_map, sector, cnt, false); 
      sector = BITMAP_ERROR;
    }
  if (sector != BITMAP_ERROR)
    *sectorp = sector;

  lock_release(&free_map_lock);


  return sector != BITMAP_ERROR;
}
Ejemplo n.º 23
0
static uint32_t 
_cache_find_ensured (struct block *block, block_sector_t sector)
{
  lock_acquire (&cache_lock);
  int i;
  for (i = 0; i < CACHE_SIZE; ++i) 
    {
      if (cache[i].block == block && cache[i].sector == sector)
	{
	  lock_acquire (&cache[i].cs_lock);
	  lock_release (&cache_lock);
	  return i;
	}
    }
  uint32_t index = bitmap_scan_and_flip (used_slots, 0, 1, false); 
  if (index == BITMAP_ERROR)
    index = _cache_evict ();
  _cache_fetch (index, block, sector);
  lock_acquire (&cache[index].cs_lock);
  lock_release (&cache_lock);
  return index;
}
Ejemplo n.º 24
0
/**
 * function swaps the given page frame to the swap_disk_partition
 */
bool swap_page_out_to_disk_from_frame (struct supplementary_page_table_entry *page)
{
  int i = 0;
  size_t open_index;
  ASSERT (page -> supplementary_frame_in_memory != NULL);
  ASSERT (lock_held_by_current_thread (&page -> supplementary_frame_in_memory ->this_lock));

  if (swap_sectors_btmp == NULL)
  {
    PANIC("NO swap sectors bitmap available!!! :(");
  }

  // Get any free empty swap-sector index - to which we will write our page-frame data
  lock_acquire (&swap_lock);
  open_index = bitmap_scan_and_flip (swap_sectors_btmp, 0, 1, 0);
  lock_release (&swap_lock);

  if (open_index != BITMAP_ERROR)
  {
    page->area_swap = open_index;

    for (i = 0; i < NUM_OF_PER_PAGE_SECTORS; i++)
    {
      block_write (swap_partition,
          ( page->area_swap * NUM_OF_PER_PAGE_SECTORS ) + i,
          page->supplementary_frame_in_memory-> base_vir_address + i * BLOCK_SECTOR_SIZE);
    }

    // set that sector_bit_index in bitmap to 1
    bitmap_set (swap_sectors_btmp, page->area_swap, true);

    page->sup_file = NULL;
    page->swap_write = false;
    page->rw_bytes = 0;
    page->file_offset = 0;
    return true;
  }
  return false;
}
Ejemplo n.º 25
0
/* Obtains a single free page and returns its kernel virtual
   address.
   If PAL_USER is set, the page is obtained from the user pool,
   otherwise from the kernel pool.  If PAL_ZERO is set in FLAGS,
   then the page is filled with zeros.  If no pages are
   available, returns a null pointer, unless PAL_ASSERT is set in
   FLAGS, in which case the kernel panics. */
void *
palloc_page (enum palloc_flags flags, void * upage, bool writable) 
{
   bool success = false;
   if(!(flags & PAL_USER))
   PANIC ("This function cannot be called without PAL_USER flag set\n");

   struct pool *pool = &frame_table.frame_pool;
   size_t page_idx;

   // empty page, and set to used
   lock_acquire (&pool->lock);
   page_idx = bitmap_scan_and_flip (pool->used_map, 0, 1, false);
   lock_release (&pool->lock);

   /* sets the members of cur_frame struct after is it allocated */
   struct frame_entry * cur_frame;
   cur_frame = frame_table.frames + page_idx;
   cur_frame->pid = thread_current()->tid;
   cur_frame->page_num = pg_no(upage);
   cur_frame->reference = true;  
   cur_frame->dirty = false;
   cur_frame->resident = true;
   success = install_page (upage, cur_frame->kpage, writable);

   if(DBG)printf("success after in mapping upage %p to kpage %p in palloc page = %d\n", upage, cur_frame->kpage, success);

   // execute flags
   if(!success)
   {
      if (flags & PAL_ASSERT)
         PANIC ("palloc_get: out of pages"); // change this?
      return NULL;
   }
   else if (flags & PAL_ZERO)
      memset (upage, 0, PGSIZE);

   return cur_frame->kpage;
}
Ejemplo n.º 26
0
size_t swap_out (void *frame)
{
	if (!swap_block || !swap_map)
	{
		PANIC("Need swap partition but no swap partition present!");
	}
	lock_acquire(&swap_lock);
	size_t free_index = bitmap_scan_and_flip(swap_map, 0, 1, SWAP_FREE);

	if (free_index == BITMAP_ERROR)
	{
		PANIC("Swap partition is full!");
	}

	size_t i;
	for (i = 0; i < SECTORS_PER_PAGE; i++)
	{ 
		block_write(swap_block, free_index * SECTORS_PER_PAGE + i,
				(uint8_t *) frame + i * BLOCK_SECTOR_SIZE);
	}
	lock_release(&swap_lock);
	return free_index;
}
Ejemplo n.º 27
0
/*
 * copy page in at kpg_vaddr to a slot, and return
 * slot's number. if no slot available, PANIC!
 */
uint32_t swap_store_pg(uint8_t* kpg_vaddr){
	size_t slot_idx;
	ASSERT(swap_blk!=NULL);
	bool already_locked = lock_held_by_current_thread (&swap_lock);
	if (!already_locked) {
		lock_acquire(&swap_lock);
	}
	ASSERT(kpg_vaddr!=NULL);
	slot_idx = bitmap_scan_and_flip (swap_table, 0, 1, false);
	if (slot_idx != BITMAP_ERROR){
		int i;
		for(i=0;i<8;i++){
			block_write (swap_blk,
					slot_idx*8+i,
					kpg_vaddr+i*BLOCK_SECTOR_SIZE);
		}
	}else
	  PANIC("No space for swap!");
	if (!already_locked) {
		lock_release(&swap_lock);
	}
	return slot_idx;
}
Ejemplo n.º 28
0
/* Gets a physical frame if available and maps it to a page
   obtained from the user pool
*/
void *get_frame(int flags)
{
  //Check bitmap to see if free frame available
  struct thread *t = thread_current();
  size_t idx = bitmap_scan_and_flip (fr_table->bm_frames, 0, 1, false);
  void * free_frame;
  //If available, fetch a page from user pool by calling palloc_get_page
  if(idx != BITMAP_ERROR)
    {
       free_frame = palloc_get_page(flags);
       if(!free_frame)
	 {
	   /* Evict frame - shouldn't happen here since we scan
		   the bitmap first*/
         }
    }
  else
    {
     //if fetch failed, PANIC for now. Implement evict later.
       PANIC("out of frames!");
    }
  //else, set the appropriate bit in the ft bitmap (already done)
  //malloc free frame. map page to frame. Insert frame to hash table.
  struct frame_entry *frame = malloc(sizeof(struct frame_entry));
  if(!frame)
    {
       PANIC("Malloc failed:Out of memory!");
    }
  frame->frame = free_frame;
  frame->pagedir = t->pagedir;
  hash_insert (&fr_table->ft, &frame->hash_elem);

  //If bitset, frame used. Else, frame available
  return free_frame;
  //Return page address
}
Ejemplo n.º 29
0
/* TODO need better comment swap out */
bool swap_out (struct frame_struct *pframe)
{  
  struct block *device = NULL;
  block_sector_t sector_no = 0;

  uint8_t *kpage = pframe->vaddr;
  if (kpage == NULL)
  {
    /* Virtual address invalid */
    return false;
  }  
  uint32_t pos = POS_MEM;
  uint32_t type = pframe->flag & TYPEBITS;
  uint32_t dirty = sup_pt_fs_is_dirty (pframe);
  uint32_t is_all_zero = pframe->flag & FS_ZERO;

  /* Zero and not dirty page need not swap out */
  if (is_all_zero && !dirty)
  {
    pframe->flag = (pframe->flag & POSMASK) | POS_DISK;
    return true;
  }
  else 
  {
    pframe->flag &= ~FS_ZERO;
  }

  if (type == TYPE_Stack)
  {
    device = sp_device;
    lock_acquire (&swap_set_lock);
    sector_no = bitmap_scan_and_flip (swap_free_map, 0,
                                      PGSIZE / BLOCK_SECTOR_SIZE, false);
    lock_release (&swap_set_lock);
    pos = POS_SWAP;
    goto write;
  }
    
  /* Write memory mapped file to disk */
  if (type == TYPE_MMFile)
  {
    if (dirty)
    {
      device = fs_device;
      sector_no = pframe->sector_no;
      pos = POS_DISK;
      goto write;
    } else 
    {
      sup_pt_set_swap_out (pframe, pframe->sector_no, true); 
      lock_release (&pframe->frame_lock);
      return true;
    }
  }

  /* For executable, if dirty, write to swap space, otherwise do nothing. */
  if (type == TYPE_Executable) 
  {
    if (dirty)
    {
      device = sp_device;
      lock_acquire (&swap_set_lock);
      sector_no = bitmap_scan_and_flip (swap_free_map, 0,
                                        PGSIZE / BLOCK_SECTOR_SIZE, false);
      lock_release (&swap_set_lock);
      goto write;
    } else
    {
      sup_pt_set_swap_out (pframe, pframe->sector_no, true); 
      lock_release (&pframe->frame_lock);   
      return true;
    }
  }

write:

  /* Write to disk or swap device */
  if (device == fs_device)
    lock_acquire (&glb_lock_filesys);
  else 
    lock_acquire (&glb_lock_swapsys);

  int i;
  for (i = 0; i < PGSIZE / BLOCK_SECTOR_SIZE; i++)
  {
    block_write (device, sector_no + i, kpage + BLOCK_SECTOR_SIZE * i); 
  }

  if (device == fs_device)
    lock_release (&glb_lock_filesys);
  else 
    lock_release (&glb_lock_swapsys);  

  sup_pt_set_swap_out (pframe, sector_no, (pos == POS_DISK));
  lock_release (&pframe->frame_lock);	
  return true;
}