Ejemplo n.º 1
0
struct frame_entry *
find_victim(void)
{
	cursor = list_begin(&frame_table);
	struct frame_entry *victim = NULL;
	
	while(true)
	{
		struct frame_entry *temp = list_entry(cursor, struct frame_entry, elem);

		if(pagedir_is_accessed(temp->t->pagedir, temp->frame))
		{
			pagedir_set_accessed(temp->t->pagedir, temp->frame, false);
			pagedir_set_accessed(temp->t->pagedir, temp->spe->uaddr, false);
		}
		else
		{
			victim = temp;
			cursor = list_next(cursor);
			if(cursor == list_end(&frame_table))
				cursor = list_begin(&frame_table);
			return victim;
		}

		cursor = list_next(cursor);
		if(cursor == list_end(&frame_table))
			cursor = list_begin(&frame_table);
	}
	return victim;
}
Ejemplo n.º 2
0
/*! Use the clock algorithm to select a frame to evict and execute the
    eviction. */
void * frame_evict(enum palloc_flags flag) {
    struct list_elem *ce;
    struct thread *ct;
    struct frame_table_entry *cf;
    int i;
    
    if (f_table.lock.holder != thread_current())
        lock_acquire(&f_table.lock);    /* Get frame table lock */
    if (list_empty(&f_table.table)) {
        lock_release(&f_table.lock);    /* Nothing to evict */
        return NULL;
    }
    f_table.hand = f_table.hand % list_size(&f_table.table);
    ce = list_begin(&f_table.table);    /* Begin iteration */
    for (i = 0; i < f_table.hand; i++) {
        /* Find where the "hand" points to: that is where the 
           iteration starts */
        ce = list_next(ce);
    }
    while (true) {
        cf = list_entry(ce, struct frame_table_entry, elem);
        ct = cf->owner;
        if (!cf->spt->pinned) {
            /* If pinned, skip this frame */
            if (pagedir_is_accessed(ct->pagedir, cf->spt->upage))
                /* If accessed, clear accessed bit */
                pagedir_set_accessed(ct->pagedir, cf->spt->upage, false);
            else {
                /* Swap out the page! */
                if (cf->spt->type != SPT_MMAP) {
                    cf->spt->fr = NULL;
                    cf->spt->type = SPT_SWAP;
                    cf->spt->swap_index = swap_out(cf->physical_addr);
                }
                /* Write the frame back to the map'd file */
                else if (cf->spt->type == SPT_MMAP &&
                         pagedir_is_dirty(ct->pagedir, cf->spt->upage)) {
                    cf->spt->fr = NULL;
                    file_write_at(cf->spt->file, cf->physical_addr, 
                                  cf->spt->read_bytes, cf->spt->ofs);
                }
                /* Clear the frame */
                list_remove(ce);
                pagedir_clear_page(ct->pagedir, cf->spt->upage);
                palloc_free_page(cf->physical_addr);
                free(cf);
                lock_release(&f_table.lock);
                return palloc_get_page(flag);
            }
        }
        ce = list_next(ce);
        ++f_table.hand;
        if (ce == list_end(&f_table.table)) { /* Iterate circularly */
            ce = list_begin(&f_table.table);
            f_table.hand = 0;
        }
    }
}
Ejemplo n.º 3
0
/**
 * Check if this page was accessed recently
 * Returns true if the PTE for virtual page VPAGE in PD has been
 * accessed recently, that is, between the time the PTE was
 * installed and the last time it was cleared.  Returns false if
 * PD contains no PTE for VPAGE.
 */
bool is_page_accessed (struct supplementary_page_table_entry *page)
{
  ASSERT(page -> supplementary_frame_in_memory != NULL)
  ASSERT(
      lock_held_by_current_thread (
          &page->supplementary_frame_in_memory->this_lock));
  bool access = pagedir_is_accessed (page->sup_thread->pagedir, page->vaddr);
  if (access)
  {
    pagedir_set_accessed (page->sup_thread->pagedir, page->vaddr, false);
  }
  return access;
}
Ejemplo n.º 4
0
void *
frame_evict (enum palloc_flags flags)
{
    lock_acquire (&frame_table_lock);
    struct list_elem *e = list_begin (&frame_table);

    while (true) {
        struct frame_entry *frame_entry = list_entry (e, struct frame_entry, elem);
        struct SP_entry *page_entry = frame_entry->page_entry;
        if (!page_entry->pinned) {
            struct thread *t = frame_entry->thread;
            if (pagedir_is_accessed (t->pagedir, page_entry->page)) {
                pagedir_set_accessed (t->pagedir, page_entry->page, false);
            } else {
                if (pagedir_is_dirty (t->pagedir, page_entry->page) ||
                    page_entry->type == SP_SWAP) {
                    if (page_entry->type == SP_MMAP) {
                        lock_acquire (&filesys_lock);
                        file_write_at (page_entry->file, frame_entry->frame,
                                       page_entry->read_bytes,
                                       page_entry->offset);
                        lock_release (&filesys_lock);
                    } else {
                        page_entry->type = SP_SWAP;
                        page_entry->swap_index = swap_out (frame_entry->frame);
                    }
                }
                page_entry->is_loaded = false;
                list_remove (&frame_entry->elem);
                pagedir_clear_page (t->pagedir, page_entry->page);
                palloc_free_page (frame_entry->frame);
                free (frame_entry);
                lock_release (&frame_table_lock);
                return palloc_get_page (flags);
            }
        }
        e = list_next (e);
        if (e == list_end (&frame_table)) {
            e = list_begin (&frame_table);
        }
    }
}
Ejemplo n.º 5
0
/*
 * select one frame to kick out
 * the page inside it. We implement
 * Clock Algorithm here.
 */
struct frame_table_entry* clock_kick(){
	struct list_elem *elem;
clock:
	elem = list_begin(&frame_table);
	while (elem != list_end(&frame_table)) {
		struct frame_table_entry* fte;
		fte = list_entry(elem, struct frame_table_entry, elem);
		ASSERT(fte!=NULL);
		if(!pagedir_is_accessed(fte->owner->pagedir,fte->pg_vaddr)
				&& fte->pinned == false){
			return fte;
		}else{
			pagedir_set_accessed(fte->owner->pagedir,fte->pg_vaddr,0);
		}
		elem = list_next(elem);
	}
	goto clock;
	NOT_REACHED();
	return NULL;
}
Ejemplo n.º 6
0
struct frame_table_entry*
frame_evict_choose_secondchance (void)
{
  struct frame_table_entry *fte = frame_evict_choose_fifo ();

  if (pagedir_is_accessed (fte->owner->pagedir, fte->uaddr))
    {
      pagedir_set_accessed (fte->owner->pagedir, fte->uaddr, false);

      lock_acquire (&frame_table_lock);
      list_remove (&fte->elem);
      list_push_front (&frame_table, &fte->elem);
      lock_release (&frame_table_lock);

      return frame_evict_choose_secondchance ();
    }
  else
    {
      return fte;
    }
}
Ejemplo n.º 7
0
/* The implementation of LRU 'clock' algorithm follows.. we make use of the PTE's accessed bit and dirty bit:
 on any read or write to a page  ==> accessed bit = 1;
 on any write ==> dirty bit = 1;

 Step 1: We navigate through the pages in a circular order.. i.e., if we hit the end of the frame list,
 we circle back to the start and continue our processing..

 Step 2: If the accessed bit is 'accessed', turn it to 'not accessed', skip the page and proceed to look-up the next one in the list

 Step 3: If the accessed bit is 'not accessed', we can proceed with our page replacement */
void evict_page() {
	struct list_elem *e;
	int count = 0;
	lock_acquire(&ftable_lock);
	for (e = list_begin(&frame_list); e != list_end(&frame_list);
			e = list_next(e)) {
		struct frame *frame = list_entry(e, struct frame, frame_list_elem);
		// printf ("\n%d , %d", count, list_size(&frame_list) - 1);
		if (count != list_size(&frame_list) - 1) {
			// get the accessed flag for the current page
			bool accessed_flag = pagedir_is_accessed(
					frame->page->frame_holder_thread->pagedir, frame->page->addr);
			if (accessed_flag)
				pagedir_set_accessed(frame->page->frame_holder_thread->pagedir,
						frame->page->addr, !accessed_flag);
			else {
				// we need to page replace.. i.e.,
				// step 1: remove the existing page from the frame (swap_out call)
				// step 2: remove the existing page from the page directory
				// step 3: set the accessed flag of the page to 'accessed'
				// step 4: free the page and free the frame, for subsequent use
				list_remove(e);
				swap_out(frame->page);
				frame->page->swap_flag = 1;
				pagedir_clear_page(frame->page->frame_holder_thread->pagedir,
						frame->page->addr);
				palloc_free_page(frame->base);
				free(frame);
				// frame->page->swap_flag = 1;
				break;
			}
			count++;
		} else {
			count = 0;
			e = list_begin(&frame_list);
		}
	}
	lock_release(&ftable_lock);
}
Ejemplo n.º 8
0
Archivo: frame.c Proyecto: chutchUCD/OS
struct frame_table_entry* pick_frame_to_evict( uint32_t *pagedir )
{
  size_t n = hash_size(&frame_map);
  if(n == 0) PANIC("Frame table is empty, can't happen - there is a leak somewhere");

  size_t it;
  for(it = 0; it <= n + n; ++ it) // prevent infinite loop. 2n iterations is enough
  {
    struct frame_table_entry *e = clock_frame_next();
    // if pinned, continue
    if(e->pinned) continue;
    // if referenced, give a second chance.
    else if( pagedir_is_accessed(pagedir, e->upage)) {
      pagedir_set_accessed(pagedir, e->upage, false);
      continue;
    }

    // OK, here is the victim : unreferenced since its last chance
    return e;
  }

  PANIC ("Can't evict any frame -- Not enough memory!\n");
}