コード例 #1
0
ファイル: syscall.c プロジェクト: xuruiyang/CS5600
/*
 * System Call: mapid_t mmap (int fd, void *addr)
 * Maps the file open as fd into the process's virtual address space.
 * The entire file is mapped into consecutive virtual pages starting
 * at addr.
 */
mapid_t mmap_handler (int fd, void *addr){
	if(addr==NULL) return -1;
	if(pg_ofs(addr) != 0) return -1;
	if(fd<2) return -1;

	struct file *f_,*f;
	lock_acquire (&fic_m);
	f_ = findfd(fd);
	if(f_== NULL) {
		lock_release (&fic_m);
		return -1;
	}
	f = file_reopen(f_);
	lock_release (&fic_m);

	lock_acquire (&fic_m);
	int32_t size_f = file_length(f);
	lock_release (&fic_m);
	if (size_f == 0) return -1;
	if (addr+size_f>=thread_current()->saved_esp) return -1;
	if(validate_mapping(addr, size_f)){
		size_t page_num = size_f/PGSIZE + 1;
		int ret = addfmap (f, addr, page_num, size_f);
		return ret;
	}
	return -1;
}
コード例 #2
0
ファイル: syscall.c プロジェクト: c22dunbar/sven-pintos-code
void mmap (struct intr_frame *f) {

	int fd = *value_stack_int(f->esp,4);
	//void * addr = *(void **)value_stack(f->esp,8);
	void * addr = *(void **)(f->esp + 8);

	if (!is_user_vaddr(addr) ) exit_mythread(-1); 

	//fd 0 and 1 are not allowed ... MISSING PAGE ALIGN
	if(fd == 1 || fd == 0 || addr == 0 || (unsigned int)addr % PGSIZE != 0 ) { 
		f->eax = -1;
		return ;
	}

	struct filed * file = find_file(fd);
	if ( file == NULL ) {
		exit_mythread(-1);
	}

	struct file * mfile = file_reopen(file->file);

	//get the file from the threads file table
	if ( mfile == NULL ) {
		exit_mythread(-1);
	}

	int size = file_length(mfile);
	//get the number of pages we need for the file
	int numberpages = size/PGSIZE;

	if (file_length(mfile) % PGSIZE != 0) numberpages += 1;

	//check if the virtual memory pages are free
	int i;
	for (i = 0; i < numberpages;i++) {
		if (page_lookup(addr + i*PGSIZE, thread_current()) != NULL) {
			file_close(mfile);
			f->eax=-1;
			return ;
		}
	}

	//add to filetable
	fd = add_filemmap(mfile,addr);

	off_t length = 0;
	//add the pages to the supplemental page table
	for (i = 0; i < numberpages; i++) {
		if (size >= PGSIZE) length = PGSIZE;
		else length = size;
		page_add_mmap (addr + i*PGSIZE, (off_t *) (i*PGSIZE),true,fd,length,i*PGSIZE);
		size -= length;
	}

	f->eax = fd;

}
コード例 #3
0
ファイル: syscall.c プロジェクト: chutchUCD/OS
mmapid_t sys_mmap(int fd, void *upage) {
  // check arguments
  if (upage == NULL || pg_ofs(upage) != 0) return -1;
  if (fd <= 1) return -1; // 0 and 1 are unmappable
  struct thread *curr = thread_current();

  lock_acquire (&filesys_lock);

  /* 1. Open file */
  struct file *f = NULL;
  struct file_desc* file_d = find_file_desc(thread_current(), fd, FD_FILE);
  if(file_d && file_d->file) {
    // reopen file so that it doesn't interfere with process itself
    // it will be store in the mmap_desc struct (later closed on munmap)
    f = file_reopen (file_d->file);
  }
  if(f == NULL) goto MMAP_FAIL;

  size_t file_size = file_length(f);
  if(file_size == 0) goto MMAP_FAIL;

  /* 2. Mapping memory pages */
  // First, ensure that all the page address is NON-EXIESENT.
  size_t offset;
  for (offset = 0; offset < file_size; offset += PGSIZE) {
    void *addr = upage + offset;
    if (vm_supt_has_entry(curr->supt, addr)) goto MMAP_FAIL;
  }

  // Now, map each page to filesystem
  for (offset = 0; offset < file_size; offset += PGSIZE) {
    void *addr = upage + offset;

    size_t read_bytes = (offset + PGSIZE < file_size ? PGSIZE : file_size - offset);
    size_t zero_bytes = PGSIZE - read_bytes;

    vm_supt_install_filesys(curr->supt, addr,
        f, offset, read_bytes, zero_bytes, /*writable*/true);
  }

  /* 3. Assign mmapid */
  mmapid_t mid;
  if (! list_empty(&curr->mmap_list)) {
    mid = list_entry(list_back(&curr->mmap_list), struct mmap_desc, elem)->id + 1;
  }
コード例 #4
0
ファイル: syscall.c プロジェクト: samath/oosterhoot
static mapid_t syscall_mmap (int fd, void *addr) 
{
  if(fd == 0 || fd == 1 || addr == NULL || (int) addr % PGSIZE != 0) {
    return MAP_FAILED;
  }

  struct mmap_entry *mme = mmap_entry_from_fd (fd);
  if (mme == NULL) return MAP_FAILED;

  mme->uaddr = addr;
  struct supp_page_table *spt = thread_current ()->spt;
  unsigned i = 0;
  for(; i < mme->num_pages; i++) {
    if (!is_user_vaddr ((char *)addr + i * PGSIZE)||
        supp_page_lookup (spt, (char *)addr + i * PGSIZE) != NULL) {
      free (mme);
      return MAP_FAILED;
    }
  }

  lock_acquire (&filesys_lock);
  file_reopen (mme->fp);
  lock_release (&filesys_lock);
 
  mme->map_id = (mapid_t) get_new_fd (fm, mme->fp, FM_MODE_MMAP);

  i = 0;
  for(; i < mme->num_pages; i++) {
    supp_page_insert (spt, (char *)addr + i * PGSIZE,
                      FRAME_MMAP, mme, false);
  }


  mmap_table_insert (thread_current ()->mmt, mme);
  return mme->map_id;
}
コード例 #5
0
ファイル: syscall.c プロジェクト: chikinmukjja/Past_Projects
int mmap(int fd, void *addr)
{

	struct thread *t = thread_current();
	struct mmap_file* mmap_f= malloc(sizeof(struct mmap_file)); // mmap_file allocate

	struct file *fp1 = process_get_file(fd);                    // get file for fd
	if(fp1 == NULL)
		return -1;


	if( !is_user_vaddr(addr)|| addr < (void *)0x08048000 ||
		   	   ((uint32_t)addr % PGSIZE)!= 0)return -1;
    // only on user address space, set address to aligned pagesize

	struct file *fp2 = file_reopen(fp1);       // fail for reopening
	if(fp2 == NULL || file_length(fp1) == 0)
	return -1;


	if(mmap_f != NULL){                        // fail for allocate space for mmap_file

			t->mapid++;
			mmap_f->file = fp2;
			mmap_f->mapid = t->mapid;
			list_init(&mmap_f->vme_list);

	}else return -1;

	int32_t offset = 0;
	uint32_t read_bytes = file_length(fp2);   //  to read the number of bytes
	
	uint32_t page_read_bytes;
	uint32_t page_zero_bytes;

	while(read_bytes > 0)
	{

		page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;  // over PGSIZE 4096
		page_zero_bytes = PGSIZE - page_read_bytes;

		// add_mmap_to_page
		struct vm_entry *entry = malloc(sizeof(struct vm_entry));
		if(entry == NULL)return -1;
		
		entry->file = fp2;                             // vme_entry initialize
		entry->offset = offset;
		entry->vaddr = addr;
		entry->read_bytes = page_read_bytes;
		entry->zero_bytes = page_zero_bytes;
		entry->is_loaded = false;
		entry->type = VM_FILE;
		entry->writable = true;
		
		list_push_back(&mmap_f->vme_list,&entry->mmap_elem);       // to push element to (mmap_file`s member) vme_list
		if(!insert_vme(&t->vm,entry))return -1;

		read_bytes -= page_read_bytes;                              // if read_bytes > PGSIZE -> decrease PGSIZE
		offset += page_read_bytes;
		addr += PGSIZE;

	}
	
	list_push_back(&t->mmap_list,&mmap_f->elem);                    //to push element to( struct thread`s member )mmap_list


	return t->mapid;
	
}
コード例 #6
0
ファイル: syscall.c プロジェクト: jchen2caltech/pintos-cz
/*! Memory map from file to user address. */
mapid_t mmap(uint32_t fd, void* addr){
    
    int f_size;
    void* addr_e;
    mapid_t mapid;
    uint32_t read_bytes, zero_bytes;
    uint8_t *upage;
    off_t ofs;
    struct file* file;
    struct f_info* f;
    struct mmap_elem* me;
    struct supp_table* st;
    struct thread* t = thread_current();
    
    if (!checkva(addr))
        return MAP_FAIL;

    /* Check for the invalid conditions:
     * fd is standard io; file size of the given fd is 0; give user address
     * is not valie; given address is not page aligned; given address is 0.
     * If invalid, then return MAP_FAIL. */
    if (fd == STDIN_FILENO ||
        fd == STDOUT_FILENO ||
        filesize(fd) == 0 ||
        pg_ofs(addr) != 0 ||
        addr == 0) {
            return MAP_FAIL;
    }
    
    /* Get the file size of the file. And check the entire range of the
     * to-be-mapped user address does not overlap with any already allocated
     * pages. */
    f_size = filesize(fd);
    for (addr_e = addr; addr_e < addr + f_size; addr_e += PGSIZE){
            if (find_supp_table(addr_e) != NULL){
                /* If found a supplemental page entry of this page address,
                 * Then this is already alocated. Return MAP_FAIL. */
                return MAP_FAIL;
            }   
    }
    
    /* Increment the thread's max mmapid to give this mmapping a unque ID. */
    ++ t->mmapid_max;
    mapid = t->mmapid_max;
    
    /* Allocated the new mmap struct */
    me = (struct mmap_elem*) malloc(sizeof(struct mmap_elem));
    if (me == NULL)
        return MAP_FAIL;
    
    /* Reopen the file according to the file descriptor. */
    f = findfile(fd);
    if (f->isdir)
        return MAP_FAIL;
    lock_acquire(&filesys_lock);
    file = file_reopen(f->f);
    lock_release(&filesys_lock);
    
    /* If the file is NULL, then free the struct and return MAP_FAIL. */
    if (file == NULL){
        free(me);
        return MAP_FAIL;
    }
    
    /* Setup the fields of the mmap struct.*/
    me->file = file;
    me->mapid = mapid;
    /* Push the mmap struct to the list of mmap of this process. */
    list_push_back(&(t->mmap_lst), &(me->elem));
    list_init(&(me->s_table));
    
    /* Allocate pages for the read-in file data.*/
    upage = addr;
    ofs = 0;
    read_bytes = f_size;
    
    if (read_bytes >= PGSIZE)
        zero_bytes = 0;
    else
        zero_bytes = PGSIZE - read_bytes;
    
    while (read_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;
        
        /* Create a new supplemental page entry for this page*/
        st = create_mmap_supp_table(file, ofs, upage, page_read_bytes, 
                                    page_zero_bytes, true);
        /* Push the page entry to the mmap struct's list */
        list_push_back(&(me->s_table), &(st->map_elem));
        
        /* Update the remaining read_bytes, zero_bytes;
         * Update upage, and ofs. This is for the next page to load the file.*/
        read_bytes -= page_read_bytes;
        zero_bytes -= page_zero_bytes;
        upage += PGSIZE;
        ofs += page_read_bytes;
        
    }
    return mapid;
}
コード例 #7
0
ファイル: syscall.c プロジェクト: nachonavarro/pintosOS
/* Maps the file open as FD into the process' virtual address space - entire
   file mapped into consecutive virtual pages starting at ADDR. (Lazy load
   pages in mmap regions). (Evicting a page mapped by mmap writes it back to
   the actual file it was mapped from). (Set spare bytes on final page to zero
   when that page is faulted in the file system, and ignore these bytes when
   page is written back to disk). Returns mapid_t for the mapping, or -1 on
   failure. Failure occurs when file has length 0, if addr is not page aligned,
   if range of pages mapped overlaps any existing mapped pages (including the
   stack or pages mapped at executable load time), if addr is 0, or if fd
   is 0 or 1. */
static mapid_t
sys_mmap(int fd, void *addr)
{
  /* Check that fd is a valid file descriptor. */
  check_fd(fd);

  /* Cannot map stdin or stdout. */
  if (fd == STDIN_FILENO || fd == STDOUT_FILENO) {
    return ERROR;
  }

  /* Address to map to cannot be 0, because some Pintos code assumes virtual
     page 0 is not mapped. */
  if (addr == 0) {
    return ERROR;
  }

  int size = sys_filesize(fd);

  /* Cannot map a file of size 0 bytes. */
  if (size == 0) {
    return ERROR;
  }

  /* ADDR must be page-aligned. */
  if (pg_ofs(addr) != 0) {
    return ERROR;
  }

  /* If ADDR is not in user/process address space, we cannot map
     the file there. */
  if (!is_user_vaddr(addr)) {
    sys_exit(ERROR);
  }

  /* Pages is number of pages needed to map file.
     (size % PGSIZE) gives the number of spare bytes on the final page.
     This is necessary because the division is integer division, and so
     will round down, but we want it to round up. */
  int pages = size / PGSIZE;
  if ((size % PGSIZE) != 0) {
    pages++;
  }

  struct thread *cur = thread_current();
  struct hash *mmap_table = &cur->mmap_table;
  struct hash *spt = &cur->supp_pt;

  lock_acquire(&secure_file);
  struct file *old_file = get_file(fd);
  if (!old_file) {
    lock_release(&secure_file);
    sys_exit(ERROR);
  }
  /* Must use file_reopen() to get independent 'struct file *' for same file
     (with same inode) because the file could be being read at different points
     (file->pos could be different) and they could have different
     file->deny_write (file_deny_write() could be called on one struct file but
     not another of same file (inode) but different struct file). */
  struct file *file = file_reopen(old_file);
  lock_release(&secure_file);

  int i;
  int bytes_to_write;
  void *cur_page;
  /* Check that the contiguous range of pages to be mapped doesn't overlap
     any existing set of mapped pages (Not including stack). Can then add
     these pages to the supplementary page table. */
  for (i = 0; i < pages; i++) {
    cur_page = (void *) ((uint8_t *) addr) + (i * PGSIZE);
    /* Check to see if there is an existing mapped page at what would be the
       i'th page of this mapped file. */
    if (get_spt_entry(spt, cur_page) != NULL) {
      return ERROR;
    }
    /* Only on the last page do we potentially not fill up whole page with
       part of file. */
    bytes_to_write = (i == (pages - 1)) ? (size % PGSIZE) : PGSIZE;
    /* Add current page to the supplementary page table. */
    spt_insert_file(cur_page, file, bytes_to_write,
                       PGSIZE - bytes_to_write, i * PGSIZE, true, true, false);
  }

  mapid_t mapid = cur->next_mapid;

  /* Lock must be acquired to call hash_insert() in mmap_table_insert(), and
     since we have thread_current() here already it makes sense to lock here
     rather than in mmap_table_insert() in mmap.c. */
  lock_acquire(&cur->mmap_table_lock);
  bool success = mmap_table_insert(mmap_table, addr, addr + size, pages,
                                     mapid, file);
  lock_release(&cur->mmap_table_lock);

  /* Return -1 if mmap_table_insert wasn't successful (meaning there isn't
     enough space to malloc for a struct mmap_mapping *). */
  if (!success) {
    return ERROR;
  }

  /* Increment next_mapid for this thread, so that the next mmap will have a
     different mapid, ensuring unique mapids for all mappings for a process.
     Increment after checking for mmap_table_insert() success status, because
     in the case of failure, we can reuse the mapid that the failed mapping
     would have had. */
  cur->next_mapid++;

  /* If successful, function returns the mapid that uniquely identifies
     the mapping within the process. */
  return mapid;
}
コード例 #8
0
ファイル: umem.c プロジェクト: iocoder/graduation
uint32_t mmap(uint32_t base, uint32_t size, uint32_t type,
              uint32_t flags, uint32_t fd, uint64_t off) {

    int32_t pages;
    uint32_t addr;
    umem_t *umem = &(curproc->umem); /* current process umem image. */

    /*printk("mmap called: %x, size: %x\n", base, size);*/

    /* make sure fd is valid if a file is to be used */
    if (type & MMAP_TYPE_FILE) {
        if (fd < 0 || fd >= FD_MAX || curproc->file[fd] == NULL)
            return 0;
    }

    if (!base) {
        /* allocate space */
        base = umem->heap_end - size;
    }

    size += base & (~PAGE_BASE_MASK);     /* rectify "size". */
    base = base & PAGE_BASE_MASK;
    pages = (size+PAGE_SIZE-1)/PAGE_SIZE; /* pages to be allocated. */
    size = pages*PAGE_SIZE;               /* actual size. */

    /*printk("           - %x, size: %x\n", base, size); */

    /* make sure the system is initialized. */
    if (curproc == NULL)
        return 0; /* system is not initialized. */

    /* check whether the given range is valid or not. */
    for (addr = base; addr < base + size; addr+=PAGE_SIZE) {
        if (addr<USER_MEMORY_BASE || addr>=KERNEL_MEMORY_BASE) {
            return 0; /* invalid */
        }
    }

    /* update heap end: */
    if (base < umem->heap_end)
        umem->heap_end = base;

    /* now allocate. */
    for (addr = base; addr < base + size; addr+=PAGE_SIZE) {
        arch_vmpage_map(umem, (int32_t) addr, 1 /* user mode */);
        /* mapping a file? */
        if (type & MMAP_TYPE_FILE) {
            /* read file information */
            file_t *file = curproc->file[fd];
            inode_t *inode = file->inode;
            file_mem_t *region = inode->sma.first;

            /* shared? */
            if (flags & MMAP_FLAGS_SHARED) {
                /* search for the wanted region */
                while (region != NULL) {
                    if (region->pos == off) {
                        /* found */
                        region->ref++;
                        break;
                    }
                    region = region->next;
                }

                /* region found or not? */
                if (!region) {
                    /* region not found, create it */
                    region = kmalloc(sizeof(file_mem_t));
                    if (!region)
                        return 0;
                    if (file_reopen(file, &(region->file)))
                        return 0;
                    region->pos = off;
                    region->paddr = 0;
                    region->ref = 1;

                    /* add to the inode */
                    linkedlist_add(&(inode->sma), region);
                }
            } else {
                /* not shared, allocate a new one */
                region = kmalloc(sizeof(file_mem_t));
                if (!region)
                    return 0;
                if (file_reopen(file, &(region->file)))
                    return 0;
                region->pos = off;
                region->paddr = 0;
                region->ref = 1;
            }
            /* attach the virtual page to the mapping */
            arch_vmpage_attach_file(umem, (int32_t) addr, region);
            /* update offset */
            off += PAGE_SIZE;
        }
    }

    /* return the base address. */
    return base;
}