예제 #1
0
파일: frame.c 프로젝트: xuruiyang/CS5600
struct frame_table_entry* frame_get_new_page (bool zero){
	uint8_t *kpage;
	struct frame_table_entry *fte = NULL;
redo:
	if(zero){
		kpage = palloc_get_page (PAL_USER|PAL_ZERO);
	}else{
		kpage = palloc_get_page (PAL_USER);
	}
	if(kpage!=NULL){
	ASSERT (is_kernel_vaddr (kpage));
		/*
		 * TODO:
		 * add new page into frame control here,
		 * after all info be recorded, return the
		 * page table entry. uaddr should be added
		 * by latter...
		 */
		fte = malloc(sizeof(struct frame_table_entry));
		fte->kpg_vaddr = kpage;
		fte->owner = thread_current();
		fte->pinned = true;
		list_push_back (&frame_table, &fte->elem);
//		printf("thread %d released frame_lock\n",thread_current()->tid);
		return fte;
	}else{
		//evict a page to swap(0)
		frame_evict_page();
		goto redo;
	}
}
예제 #2
0
파일: frame.c 프로젝트: chutchUCD/OS
/**
 * Allocate a new frame,
 * and return the address of the associated page.
 */
void*
vm_frame_allocate (enum palloc_flags flags, void *upage)
{
  lock_acquire (&frame_lock);

  void *frame_page = palloc_get_page (PAL_USER | flags);
  if (frame_page == NULL) {
    // page allocation failed.

    /* first, swap out the page */
    struct frame_table_entry *f_evicted = pick_frame_to_evict( thread_current()->pagedir );

#if DEBUG
    printf("f_evicted: %x th=%x, pagedir = %x, up = %x, kp = %x, hash_size=%d\n", f_evicted, f_evicted->t,
        f_evicted->t->pagedir, f_evicted->upage, f_evicted->kpage, hash_size(&frame_map));
#endif
    ASSERT (f_evicted != NULL && f_evicted->t != NULL);

    // clear the page mapping, and replace it with swap
    ASSERT (f_evicted->t->pagedir != (void*)0xcccccccc);
    pagedir_clear_page(f_evicted->t->pagedir, f_evicted->upage);

    bool is_dirty = false;
    is_dirty = is_dirty || pagedir_is_dirty(f_evicted->t->pagedir, f_evicted->upage);
    is_dirty = is_dirty || pagedir_is_dirty(f_evicted->t->pagedir, f_evicted->kpage);

    swap_index_t swap_idx = vm_swap_out( f_evicted->kpage );
    vm_supt_set_swap(f_evicted->t->supt, f_evicted->upage, swap_idx);
    vm_supt_set_dirty(f_evicted->t->supt, f_evicted->upage, is_dirty);
    vm_frame_do_free(f_evicted->kpage, true); // f_evicted is also invalidated

    frame_page = palloc_get_page (PAL_USER | flags);
    ASSERT (frame_page != NULL); // should success in this chance
  }

  struct frame_table_entry *frame = malloc(sizeof(struct frame_table_entry));
  if(frame == NULL) {
    // frame allocation failed. a critical state or panic?
    lock_release (&frame_lock);
    return NULL;
  }

  frame->t = thread_current ();
  frame->upage = upage;
  frame->kpage = frame_page;
  frame->pinned = true;         // can't be evicted yet

  // insert into hash table
  hash_insert (&frame_map, &frame->helem);
  list_push_back (&frame_list, &frame->lelem);

  lock_release (&frame_lock);
  return frame_page;
}
예제 #3
0
파일: frame.c 프로젝트: linearhw/pintos
/* Allocate frame */
void *vm_alloc_frame(enum palloc_flags flag, struct supp_page_entry *s){
    if ((flag & PAL_USER) == 0)
        return NULL;
    void *page = palloc_get_page(flag);
    if (!page){
        /* No more free space */
        struct vm_frame *f = vm_evict_frame(s);
        page = palloc_get_page(flag);
        f->page = page;
    }
    else
        vm_add_frame(page, s);
    return page;
}
예제 #4
0
void *frame_alloc(enum palloc_flags flag, struct page *pg){

	if(flag<4 ) //user 영역이 아님
		return NULL;

	void *frame = palloc_get_page(flag);

	if( frame)
	{
		frame_add_to_table(frame, pg);
	}
	else
	{
		while(!frame)
		{
			frame=frame_victim(flag);
			lock_release(&frame_table_lock);

		}
		
		frame_add_to_table(frame, pg);
	}
	return frame;

}
예제 #5
0
파일: frame.c 프로젝트: gypintos/np4
void *fm_allocate (enum palloc_flags flags, bool lock) {
  lock_acquire(&frame_table_lock);
  void *kaddr = palloc_get_page(PAL_USER | flags);
  struct frame *fm;
  if (kaddr == NULL){
    fm = select_fm();
    fm->isPinned = true;
    fm->locked = lock;
    kaddr = fm->k_addr;
    struct hash *ht_thread_uaddr = &fm->ht_thread_uaddr;
    hash_first(&fm->iter_htu, ht_thread_uaddr);
    struct thread_uaddr *thread_uaddr;
    while (hash_next(&fm->iter_htu)){
      thread_uaddr = hash_entry(hash_cur(&fm->iter_htu), struct thread_uaddr, elem);
      struct page* p = find_page(thread_uaddr->uaddr, thread_uaddr->t);
      p->isLoaded = false;
      pagedir_clear_page(thread_uaddr->t->pagedir, p->vaddr);
      if (p->type == STACK){
        page_to_swap(p);
      } else if (p->type == SEGMENT){
        if (p->writable && (if_fm_dirty(fm) || p->isDirty)){
          p->isDirty = true;
          page_to_swap(p);
        }
      } else {
        write_mmap_page_to_file(p);
      }
    }
    hash_clear(&fm->ht_thread_uaddr, remove_thread_uaddr);
  } else {
예제 #6
0
/* Returns the address of the page table entry for virtual
   address VADDR in page directory PD.
   If PD does not have a page table for VADDR, behavior depends
   on CREATE.  If CREATE is true, then a new page table is
   created and a pointer into it is returned.  Otherwise, a null
   pointer is returned. */
uint32_t *
lookup_page (uint32_t *pd, const void *vaddr, bool create)
{
  uint32_t *pt, *pde;

  ASSERT (pd != NULL);

  /* Shouldn't create new kernel virtual mappings. */
  ASSERT (!create || is_user_vaddr (vaddr));

  /* Check for a page table for VADDR.
     If one is missing, create one if requested. */
  pde = pd + pd_no (vaddr);
  if (*pde == 0) 
    {
      if (create)
        {
          pt = palloc_get_page (PAL_ZERO);
          if (pt == NULL) 
            return NULL; 
      
          *pde = pde_create (pt);
        }
      else
        return NULL;
    }

  /* Return the page table entry. */
  pt = pde_get_pt (*pde);
  return &pt[pt_no (vaddr)];
}
예제 #7
0
void* frame_victim (enum palloc_flags flag)
{

	lock_acquire(&frame_table_lock);


	struct list_elem *e= list_begin(&frame_table);

//list_
	
	
	victim_frame=list_pop_front(&frame_table);
	if(victim_frame ==NULL)
	{
	}
	else
	{
		victim_frame->page->valid=false;
		pagedir_clear_page(victim_frame->thread->pagedir, victim_frame->page->vaddr);
		palloc_free_page(victim_frame->frame);
		return palloc_get_page(flag);
	}

	lock_release(&frame_table_lock);

}
예제 #8
0
/*! Obtain a frame, either through palloc() or through eviction */
struct frame_table_entry *obtain_frame(enum palloc_flags flag, 
                                       struct supp_table *pte) {
    void *page;
    struct frame_table_entry *newframe;

    page = palloc_get_page(flag);
    if (!page)
        page = frame_evict(flag);
    if (!page) 
        PANIC("run out of frames!\n");

    /*! Allocate a frame table entry and initialize it */
    newframe = (struct frame_table_entry *)\
               malloc(sizeof(struct frame_table_entry));
    if (!newframe)
        PANIC("malloc failure\n");
    newframe->physical_addr = page;
    newframe->owner = thread_current();
    newframe->spt = pte;
    if (f_table.lock.holder != thread_current())
        lock_acquire(&f_table.lock);
    list_push_back(&f_table.table, &newframe->elem);
    lock_release(&f_table.lock);
    return newframe;
}
예제 #9
0
파일: frame.c 프로젝트: satyacha/Pintos
/* Tries to allocate and lock a frame for PAGE.
 Returns the frame if successful, false on failure. */
struct frame *
frame_alloc_and_lock(struct page *page) {
	struct frame *new_frame;
	uint8_t *kpage;
	while (true) {
		kpage = palloc_get_page(PAL_USER);
		if (kpage != NULL) {
			lock_acquire(&ftable_lock);
			new_frame = (struct frame *) malloc(sizeof(struct frame));
			if (page->swap_flag != 1)
				page->swap_flag = 0;
			page->frame_holder_thread = thread_current();
			new_frame->page = page;
			new_frame->base = kpage;
			list_insert(list_end(&frame_list), &new_frame->frame_list_elem);
			// new_frame->page->swap_flag = 0;
			lock_release(&ftable_lock);
			break;
		} else {
			// lock_release(&ftable_lock);
			// PANIC("No free page available");
			// page eviction comes here
			// printf("\nEntered EVICT PAGE section");
			evict_page();
			// page->swap_flag = 1;
			// printf("\nExited EVICT PAGE section");
		}
	}
	return new_frame;
}
예제 #10
0
파일: frame.c 프로젝트: coweatyou/school
/* Allocates an unused user frame.  If there  */
struct frame *frame_alloc() {
  struct frame *f = NULL;
  
  lock_acquire(&ft_lock);
  void *pg = palloc_get_page(PAL_USER);

  if(pg == NULL) {
  	/* If there are no frames left, evict a page. */
    f = get_frame_for_eviction();
    lock_release(&ft_lock);
    lock_acquire(&f->page->moving);//TODO this should never block. need to use a monitor instead to synch between the evictor and call to page_free()
    evict(f);
  } else {
  	/* Initialize new frame. */
    f = malloc(sizeof(struct frame));
    f->addr = pg;
    lock_init(&f->evicting);
    lock_acquire(&f->evicting);

    /* Add frame to frame table. */
    hash_insert(&frame_table, &f->elem);
    lock_release(&ft_lock);
  }
  return f;
}
예제 #11
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;
        }
    }
}
예제 #12
0
파일: frame.c 프로젝트: rahulabc/jawpintos
/* Allocates and returns a page.
   First tries palloc, if fails, evicts a frame 
   and returns the newly available frame */
void *
frame_get_page (enum palloc_flags flags)
{
  lock_acquire (&frame_lock);
  void *kpage = palloc_get_page (flags);
  if (kpage == NULL)
    kpage = swap_evict ();
  lock_release (&frame_lock);
  return kpage;
}
예제 #13
0
/* Tries to allocate and lock a frame for PAGE.
   Returns the frame if successful, false on failure. */
struct frame *
frame_alloc_and_lock (struct page *page) 
{
void *temp;

    temp=palloc_get_page(PAL_USER);
   if(temp!=NULL)
     {
      struct frame *f=malloc(sizeof(struct frame));
      lock_init(&f->lock);
      f->page=page;
      f->base=temp;
     lock_acquire(&framelock);
     list_push_front(&frametable,&f->elem);
     lock_release(&framelock);
      return f;
     }
   
      
struct list_elem *e1;
e1=list_begin(&frametable);

while(1)
{
lock_acquire(&framelock);
struct frame *fr;
fr=malloc(sizeof(struct frame));
/*fr=list_entry(e1,struct frame,elem);*/
/* bool 
temp=pagedir_is_accessed((fr->page->thread)->pagedir,fr->page->addr);
  if(temp)
   {        
pagedir_set_accessed((fr->page->thread)->pagedir,fr->page->addr,false);*/  
     e1=list_next(e1);
        if(e1==list_end(&frametable))
          {
          e1=list_begin(&frametable);
          }    
     continue;
    }
struct frame *fr;
  if(fr->page->iswrite)
     {/* fr->page->mode=swap_out(*/
      }
  else
     {
     }
    fr->page=page;  

   lock_release(&framelock);
   return fr;
      

}
예제 #14
0
파일: tss.c 프로젝트: xuruiyang/CS5600
/* Initializes the kernel TSS. */
void
tss_init (void)
{
    /* Our TSS is never used in a call gate or task gate, so only a
       few fields of it are ever referenced, and those are the only
       ones we initialize. */
    tss = palloc_get_page (PAL_ASSERT | PAL_ZERO);
    tss->ss0 = SEL_KDSEG;
    tss->bitmap = 0xdfff;
    tss_update ();
}
예제 #15
0
bool from_file (struct spage_entry *se)
{
  struct thread *t = thread_current ();

  struct file *file = se->myfile;
  off_t ofs = se->ofs;
  uint8_t upage = se->upage;
  uint32_t read_bytes = se->read_bytes;
  uint32_t zero_bytes = se->zero_bytes;
  bool writable = se->writable;

  ASSERT ((read_bytes + zero_bytes) % PGSIZE == 0);
  ASSERT (pg_ofs (upage) == 0);
  ASSERT (ofs % PGSIZE == 0);

//  lock_acquire (&filesys_lock);
  file_seek (file, ofs);
//  lock_release (&filesys_lock);

  if ( !(read_bytes > 0 || zero_bytes > 0) )
    return false; 
    
      /* Calculate how to fill this page.
         We will read PAGE_READ_BYTES bytes from FILE
         and zero the final PAGE_ZERO_BYTES bytes. */  
      size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
      size_t page_zero_bytes = PGSIZE - page_read_bytes;

      /* Get a page of memory. */  
      uint8_t *kpage = palloc_get_page (PAL_USER);
      if (kpage == NULL)
        return false;

      /* Load this page. */  
//      lock_acquire (&filesys_lock);
      if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes)
        {
//          lock_release (&filesys_lock);
          palloc_free_page (kpage);
          return false; 
        }
//          lock_release (&filesys_lock);
      memset (kpage + page_read_bytes, 0, page_zero_bytes);

      /* Add the page to the process's address space. */  
      if (!install_page (upage, kpage, writable)) 
        {
          palloc_free_page (kpage);
          return false; 
        }

  return true;
}
예제 #16
0
/* Creates a new kernel thread named NAME with the given initial
   PRIORITY, which executes FUNCTION passing AUX as the argument,
   and adds it to the ready queue.  Returns the thread identifier
   for the new thread, or TID_ERROR if creation fails.

   If thread_start() has been called, then the new thread may be
   scheduled before thread_create() returns.  It could even exit
   before thread_create() returns.  Contrariwise, the original
   thread may run for any amount of time before the new thread is
   scheduled.  Use a semaphore or some other form of
   synchronization if you need to ensure ordering.

   The code provided sets the new thread's `priority' member to
   PRIORITY, but no actual priority scheduling is implemented.
   Priority scheduling is the goal of Problem 1-3. */
tid_t
thread_create (const char *name, int priority,
               thread_func *function, void *aux) 
{
  struct thread *t;
  struct kernel_thread_frame *kf;
  struct switch_entry_frame *ef;
  struct switch_threads_frame *sf;
  tid_t tid;
  enum intr_level old_level;

  ASSERT (function != NULL);

  /* Allocate thread. */
  t = palloc_get_page (PAL_ZERO);
  if (t == NULL)
    return TID_ERROR;

  /* Initialize thread. */
  init_thread (t, name, priority);
  tid = t->tid = allocate_tid ();

  /* Prepare thread for first run by initializing its stack.
     Do this atomically so intermediate values for the 'stack' 
     member cannot be observed. */
  old_level = intr_disable ();

  /* Stack frame for kernel_thread(). */
  kf = alloc_frame (t, sizeof *kf);
  kf->eip = NULL;
  kf->function = function;
  kf->aux = aux;

  /* Stack frame for switch_entry(). */
  ef = alloc_frame (t, sizeof *ef);
  ef->eip = (void (*) (void)) kernel_thread;

  /* Stack frame for switch_threads(). */
  sf = alloc_frame (t, sizeof *sf);
  sf->eip = switch_entry;
  sf->ebp = 0;

  intr_set_level (old_level);

  /* Add to run queue. */
  thread_unblock (t);

  //we need to call thread yield now to check if this thread
  //has the highest priority
  thread_yield();

  return tid;
}
예제 #17
0
void page_replacement(void *vaddr)
{
  uint32_t *paddr,*lru_page;
  
  if ((paddr = palloc_get_page(PAL_USER)) != NULL)
    swap_in(vaddr, paddr);
  else
  {
    lru_page = lru_get_page();

    swap_out(lru_page);
    swap_in(vaddr,lru_page);
  }
}
예제 #18
0
파일: load.c 프로젝트: Drakenhielm/Pintos
/* Create a minimal stack by mapping a zeroed page at the top of
   user virtual memory. */
static bool
setup_stack (void **esp) 
{
  uint8_t *kpage;
  bool success = false;

  kpage = palloc_get_page (PAL_USER | PAL_ZERO);
  if (kpage != NULL) 
    {
      success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true);
      if (success)
        *esp = PHYS_BASE;
      else
        palloc_free_page (kpage);
    }
  return success;
}
예제 #19
0
void stack_growth(void *vaddr){
  uint32_t *paddr,*lru_page;
  
  if ((paddr = palloc_get_page(PAL_ZERO)) != NULL) {
		fte_create(paddr, false);
		install_page_ext (pg_round_down(vaddr), paddr, true);
		set_page_valid(pg_round_down(vaddr), paddr);
	}
  else
  {
    lru_page = lru_get_page();

    swap_out(lru_page);
		set_page_valid(pg_round_down(vaddr), lru_page);
  }

}
예제 #20
0
파일: page.c 프로젝트: wlgus3018/pintos.vm
struct page *alloc_page (enum palloc_flags flags)
{
	struct page *page;
	void *kaddr = palloc_get_page(flags);

	while (kaddr == NULL)
	{
		kaddr = try_to_free_pages(flags);
	}

	page = (struct page*)malloc(sizeof(struct page));
	page->kaddr = kaddr;
	page->thread = thread_current();

	add_page_to_lru_list(page);

	return page;
}
예제 #21
0
파일: load.c 프로젝트: Drakenhielm/Pintos
/* Loads a segment starting at offset OFS in FILE at address
   UPAGE.  In total, READ_BYTES + ZERO_BYTES bytes of virtual
   memory are initialized, as follows:

        - READ_BYTES bytes at UPAGE must be read from FILE
          starting at offset OFS.

        - ZERO_BYTES bytes at UPAGE + READ_BYTES must be zeroed.

   The pages initialized by this function must be writable by the
   user process if WRITABLE is true, read-only otherwise.

   Return true if successful, false if a memory allocation error
   or disk read error occurs. */
static bool
load_segment (struct file *file, off_t ofs, uint8_t *upage,
              uint32_t read_bytes, uint32_t zero_bytes, bool writable) 
{
  ASSERT ((read_bytes + zero_bytes) % PGSIZE == 0);
  ASSERT (pg_ofs (upage) == 0);
  ASSERT (ofs % PGSIZE == 0);

  file_seek (file, ofs);
  while (read_bytes > 0 || zero_bytes > 0) 
    {
      /* Calculate how to fill this page.
         We will read PAGE_READ_BYTES bytes from FILE
         and zero the final PAGE_ZERO_BYTES bytes. */
      size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
      size_t page_zero_bytes = PGSIZE - page_read_bytes;

      /* Get a page of memory. */
      uint8_t *kpage = palloc_get_page (PAL_USER);
      if (kpage == NULL)
        return false;

      /* Load this page. */
      if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes)
        {
          palloc_free_page (kpage);
          return false; 
        }
      memset (kpage + page_read_bytes, 0, page_zero_bytes);

      /* Add the page to the process's address space. */
      if (!install_page (upage, kpage, writable)) 
        {
          palloc_free_page (kpage);
          return false; 
        }

      /* Advance. */
      read_bytes -= page_read_bytes;
      zero_bytes -= page_zero_bytes;
      upage += PGSIZE;
    }
  return true;
}
예제 #22
0
/* Initialize the frame manager. */
void
frame_init (void) 
{
  void *base;

  lock_init (&scan_lock);
  
  frames = malloc (sizeof *frames * init_ram_pages);
  if (frames == NULL)
    PANIC ("out of memory allocating page frames");

  while ((base = palloc_get_page (PAL_USER)) != NULL) 
    {
      struct frame *f = &frames[frame_cnt++];
      lock_init (&f->lock);
      f->base = base;
      f->page = NULL;
    }
}
예제 #23
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);
        }
    }
}
예제 #24
0
/* Given a virtual address (page) find a frame to put the page in and return 
   the physical address of the frame */
void*
frame_obtain (enum palloc_flags flags, void* uaddr)
{
  struct frame_table_entry* fte;
  /* Try and obtain frame in user memory */
  void *kaddr = palloc_get_page (flags);

  
  /* Successfully obtained frame */
  if (kaddr != NULL)
    {
      /* Create new frame table entry mapping the given page to the 
         allocated frame */
      fte = (struct frame_table_entry *) malloc 
                (sizeof (struct frame_table_entry));

      fte->owner = thread_current ();
      fte->kaddr = kaddr;
      fte->uaddr = pg_round_down (uaddr);

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

      return fte->kaddr;
    }

  /* Failed to obtain frame */
  else
    {
      /* Perform eviction to release a frame and try allocation again */
      if (PAGE_EVICTION)
      {
        return frame_evict (uaddr);
      }
      else
      {
        PANIC ("Failed to allocate frame - eviction disabled.");
      }
    }

}
예제 #25
0
void *
frame_alloc (enum palloc_flags flags, struct SP_entry *page_entry)
{
    if ((flags & PAL_USER) == 0) {
        return NULL;
    }
    void *frame = palloc_get_page (flags);
    if (frame) {
        frame_add (frame, page_entry);
    } else {
        while (!frame) {
            frame = frame_evict (flags);
        }
        if (!frame) {
            PANIC ("Frame evict failed. Swap is full!");
        }
        frame_add (frame, page_entry);
    }
    return frame;
}
예제 #26
0
파일: swap.c 프로젝트: IVY-bug/Pintos4
void *
swap (void)
{
  struct frame_entry *victim_frame = find_victim();
  
  struct spage_entry *victim_spage_entry = victim_frame->spe;
  uint32_t sectornum = swap_out(victim_frame->frame);

  pagedir_clear_page(victim_frame->t->pagedir,victim_spage_entry->uaddr);
  
  victim_spage_entry->indisk = true;
  victim_spage_entry->sec_no = sectornum;
  
  palloc_free_page(victim_frame->frame);
  falloc_free_frame(victim_frame->frame);

  void *kpage = palloc_get_page(PAL_USER|PAL_ZERO);
  ASSERT(kpage != NULL);
  
  return kpage;
}
예제 #27
0
파일: syscall.c 프로젝트: chutchUCD/OS
int sys_open(const char* file) {
  // memory validation
  check_user((const uint8_t*) file);

  struct file* file_opened;
  struct file_desc* fd = palloc_get_page(0);
  if (!fd) {
    return -1;
  }

  lock_acquire (&filesys_lock);
  file_opened = filesys_open(file);
  if (!file_opened) {
    palloc_free_page (fd);
    lock_release (&filesys_lock);
    return -1;
  }

  fd->file = file_opened; //file save

  // directory handling
  struct inode *inode = file_get_inode(fd->file);
  if(inode != NULL && inode_is_directory(inode)) {
    fd->dir = dir_open( inode_reopen(inode) );
  }
  else fd->dir = NULL;

  struct list* fd_list = &thread_current()->file_descriptors;
  if (list_empty(fd_list)) {
    // 0, 1, 2 are reserved for stdin, stdout, stderr
    fd->id = 3;
  }
  else {
    fd->id = (list_entry(list_back(fd_list), struct file_desc, elem)->id) + 1;
  }
  list_push_back(fd_list, &(fd->elem));

  lock_release (&filesys_lock);
  return fd->id;
}
예제 #28
0
/* Creates a copy of user string US in kernel memory
   and returns it as a page that must be freed with
   palloc_free_page().
   Truncates the string at PGSIZE bytes in size.
   Call thread_exit() if any of the user accesses are invalid. */
static char *
copy_in_string (const char *us) 
{
  char *ks;
  char *upage;
  size_t length;
 
  ks = palloc_get_page (0);
  if (ks == NULL) 
    thread_exit ();

  length = 0;
  for (;;) 
    {
      upage = pg_round_down (us);
      if (!page_lock (upage, false))
        goto lock_error;

      for (; us < upage + PGSIZE; us++) 
        {
          ks[length++] = *us;
          if (*us == '\0') 
            {
              page_unlock (upage);
              return ks; 
            }
          else if (length >= PGSIZE) 
            goto too_long_error;
        }

      page_unlock (upage);
    }

 too_long_error:
  page_unlock (upage);
 lock_error:
  palloc_free_page (ks);
  thread_exit ();
}
예제 #29
0
파일: frame.c 프로젝트: raunk/cs140
void*
frame_get_page(enum palloc_flags flags, void *uaddr)
{
  /* Ensure we are always getting from the user pool */
  flags = PAL_USER | flags;
  
  /* Attempt to allocate a page, if this comes back null then
     we need to evict */
  void *page = palloc_get_page(flags);
  /* TODO: not sure if this is right way to check that we ran out of pages
      Maybe we should check if pages within some count?? */
  if(page != NULL) {
    struct frame *frm = (struct frame*) malloc(sizeof(struct frame));
    frm->physical_address = page;
    frm->user_address = uaddr;
    frm->owner = thread_current ();
    
    list_push_front(&frame_list, &frm->elem);
  } else {
    printf("WE RAN OUT OF SPACE. SHIT!\n");
  }
}
예제 #30
0
/* initializes the cashing system */
void
cache_init ()
{
	/* loop variables */
	int i,j;

	/* allocate kernel pages for cache */
	for (i = 0; i < (CACHE_SIZE / blocks_per_page); i++)
	{
		/* get a page from kernel memory */
		void *kpage = palloc_get_page (PAL_ZERO);
		for (j = 0; j < blocks_per_page; j++)
		{
			/* init the block */                        
			struct cache_block *c = (struct cache_block*) malloc(sizeof(struct cache_block));

			c->reader = 0;
			c->writer = 0;
			c->bid = -1;
			c->kpage = kpage + j * BLOCK_SECTOR_SIZE ;
			c->dirty = false;
			c->accessed = false;

			/* save to cache */
			cache[i * blocks_per_page + j] = c;
		}
	}

	/*create a bitmap that represents the free entries in the cache table */
	cache_table = bitmap_create (CACHE_SIZE);

	/* init list, lock and counting semaphore */
	lock_init(&cache_globallock);
	list_init(&readahead_list);
	sema_init(&readahead_cnt, 0);
}