Beispiel #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;
}
Beispiel #2
0
void *
frame_evict() {
    ASSERT(lock_held_by_current_thread(&vm_lock));
    uint32_t e_ptr = frametable.evict_ptr;
    while(1) {
            if (frametable.frametable[frametable.evict_ptr].pin == false &&
                frametable.frametable[frametable.evict_ptr].pte != (void*) 0xFFFFFFFF) {
                    struct pagetable_entry* old_pte = frametable.frametable[frametable.evict_ptr].pte;
                    struct thread *t = thread_from_tid(frametable.frametable[frametable.evict_ptr].tid);
                    if (old_pte->accessed) {
                        pagedir_set_accessed(t->pagedir,
                                        pg_no_to_addr(frametable.frametable[frametable.evict_ptr].virt_address), false);
                        continue;
                    }

                    // First we MUST mark the page as not present so that no
                    // further accesses and modifications of the page content
                    // are possible
                    pagedir_set_not_present(t->pagedir,
                                    pg_no_to_addr(frametable.frametable[frametable.evict_ptr].virt_address));
                    if (old_pte->writable) {
                        struct spage_table_entry ecmp, *e;
                        struct hash_elem *elem;
                        ecmp.vaddr = pg_no_to_addr(frametable.frametable[frametable.evict_ptr].virt_address);
                        elem = hash_find(&t->sup_pagetable, &ecmp.elem);
                        if (elem == NULL) {
                            //swap
                            struct swaptable_entry * st_e =
                                    create_swaptable_entry(pagenum_to_page(frametable.evict_ptr));
                            swap_add(st_e);
                            spage_map_swap(pg_no_to_addr(
                                        frametable.frametable[frametable.evict_ptr].virt_address), st_e, t);
                        }
                        else {
                            e = hash_entry(elem, struct spage_table_entry, elem);
                            if (e->flags & SPTE_MMAP && old_pte->dirty) {
                                //flush
                                spage_flush_mmap(e, pagenum_to_page(frametable.evict_ptr));
                                //reset dirty bit
                                pagedir_set_dirty(t->pagedir, e->vaddr, false);
                            }
                            else if (!(e->flags & SPTE_MMAP)) {
                                //file backed writable entry
                                PANIC("SWAP of page with spage entry!");
                            }
                        }
                    }
                    frametable.frametable[frametable.evict_ptr].pte = (void*) 0xFFFFFFFF;
                    void* tmp = pagenum_to_page(frametable.evict_ptr);
                    log_debug("### Evict page at 0x%08x ###\n", (uint32_t) tmp);
                    frametable.evict_ptr = (frametable.evict_ptr + 1) % frametable.size;
                    return tmp;
            }
                        // jump to next position
            frametable.evict_ptr = (frametable.evict_ptr + 1) % frametable.size;
            if (e_ptr == frametable.evict_ptr)
                PANIC("Nothing to evict and nothing swappable");
       }

}
Beispiel #3
0
bool page_load(struct page *p, void *fp_addr)
{
	lock_acquire(&load);
	p->kpage = get_frame(PAL_USER);

	lock_release(&load);
	set_page_frame(p->kpage, p);

	pin_frame(p->kpage);

	if(p->kpage == NULL)
	{
		unpin_frame(p->kpage);
		return false;
	}

	bool temp = true;

	if(p->type == S)
	{
		temp = swap_load(p->kpage, p);
	}
	else if(p->type == F)
	{
		temp = file_load(p->kpage, p);
	}
	else
	{
		temp = zero_load(p->kpage);
	}

	if(!temp)
	{
		unpin_frame(p->kpage);
		return false;
	}

	pagedir_clear_page(p->dir, fp_addr);
	if(!pagedir_set_page(p->dir, fp_addr, p->kpage, p->write))
	{
		unpin_frame(p->kpage);
		return false;
	}
	else if(!pagedir_get_page(p->dir, fp_addr))
	{
		unpin_frame(p->kpage);
		return false;
	}

	p->load = true;

	pagedir_set_dirty(p->dir, fp_addr, false);
	pagedir_set_accessed(p->dir, fp_addr, true);

	unpin_frame(p->kpage);

	return true;
}
Beispiel #4
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;
        }
    }
}
Beispiel #5
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;
}
Beispiel #6
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);
        }
    }
}
Beispiel #7
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;
}
Beispiel #8
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;
    }
}
Beispiel #9
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);
}
Beispiel #10
0
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");
}
Beispiel #11
0
static void clock_daemon(void *aux) {
//	printf("starting clock\n");
	struct frame *head, *tail;
	bool got_frame = false;
/*	while(true)
		thread_yield();*/
//	sema_down(&clockwaiting);
//	int i;
	while(1) {
//		printf("locking\n");
		lock_acquire(&clocklock);
//		printf("Checking list is empty\n");
		if(list_empty(&clocklist)) {
//			printf("Releasing lock\n");
			lock_release(&clocklock);
//			printf("Sleeping\n");
			timer_msleep(CLOCK_WAIT_MS);
//			thread_yield();
//			printf("Woke up\n");
			continue;
		}
//		printf("List is not empty\n");
		if(clockmodified) {
//			printf("clockmodified");
			head = tail = get_clock_frame(list_begin(&clocklist));
//			i = 0;
		}
//		printf("clock got lock\n");
		for(int i = 0; i < CLOCK_DIFF_COUNT; i++) {
//			printf("in for loop");
//			if(!clockmodified)
//				i = CLOCK_WAIT_COUNT;
//			printf("clock on frame %p: checking semaphore at %p\n", current, &current->evicting);
			/* Clear head's accessed bit. */
			if(lock_try_acquire(&head->evicting)) {
//				printf("\t\tgot head sema\n");
				pagedir_set_accessed(head->page->thread->pagedir, head->page->vaddr, false);//TODO check if it is being moved
				lock_release(&head->evicting);
			}
			/* If clock hands have reached proper angle, use tail hand. */
			if(!clockmodified/*i >= CLOCK_WAIT_COUNT*/) {
				/* Check if frame has been changed accessed since head passed. */
				if(lock_try_acquire(&tail->evicting)) {
					if(!pagedir_is_writeable/*accessed*/(tail->page->thread->pagedir, tail->page->vaddr)) {
						/* Wait for clock frame to be cleared then set it to tail. */
//						if(sema_try_down(&clockwaiting))
						lock_acquire(&clockcondlock);
						if(clockwaiters > 0 && clockrecieved) {
							printf("Found non accessed dir\n");
							clock_frame = tail;
							clockrecieved = false;
							got_frame = true;
							cond_signal(&clockwaiting, &clockcondlock);
						}
						lock_release(&clockcondlock);
//							sema_up(&clockready);
//						break;
						//						}
					}
					if(!got_frame) {
						lock_release(&tail->evicting);
					} else {
						got_frame = true;
					}
				}
				tail = get_next_clock_frame(tail);
			}
//			printf("getting next frame\n");
			head = get_next_clock_frame(head);
//			printf("sleeping\n");
		}
		clockmodified = false;
		lock_release(&clocklock);
		timer_msleep(CLOCK_WAIT_MS);
//		thread_yield();
	}
	PANIC("Frame eviction daemon quit!\n");
}