[BACK]Return to uvm_mmap.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / uvm

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/uvm/uvm_mmap.c between version 1.35 and 1.35.2.5

version 1.35, 1999/07/17 21:35:50 version 1.35.2.5, 2001/03/27 15:32:50
Line 64 
Line 64 
   
 #include <miscfs/specfs/specdev.h>  #include <miscfs/specfs/specdev.h>
   
 #include <vm/vm.h>  
 #include <vm/vm_page.h>  
 #include <vm/vm_kern.h>  
   
 #include <sys/syscallargs.h>  #include <sys/syscallargs.h>
   
 #include <uvm/uvm.h>  #include <uvm/uvm.h>
Line 168  sys_mincore(p, v, retval)
Line 164  sys_mincore(p, v, retval)
          * Lock down vec, so our returned status isn't outdated by           * Lock down vec, so our returned status isn't outdated by
          * storing the status byte for a page.           * storing the status byte for a page.
          */           */
         uvm_vslock(p, vec, npgs, VM_PROT_WRITE);  
   
           uvm_vslock(p, vec, npgs, VM_PROT_WRITE);
         vm_map_lock_read(map);          vm_map_lock_read(map);
   
         if (uvm_map_lookup_entry(map, start, &entry) == FALSE) {          if (uvm_map_lookup_entry(map, start, &entry) == FALSE) {
Line 180  sys_mincore(p, v, retval)
Line 176  sys_mincore(p, v, retval)
         for (/* nothing */;          for (/* nothing */;
              entry != &map->header && entry->start < end;               entry != &map->header && entry->start < end;
              entry = entry->next) {               entry = entry->next) {
 #ifdef DIAGNOSTIC                  KASSERT(!UVM_ET_ISSUBMAP(entry));
                 if (UVM_ET_ISSUBMAP(entry))                  KASSERT(start >= entry->start);
                         panic("mincore: user map has submap");  
                 if (start < entry->start)  
                         panic("mincore: hole");  
 #endif  
                 /* Make sure there are no holes. */                  /* Make sure there are no holes. */
                 if (entry->end < end &&                  if (entry->end < end &&
                      (entry->next == &map->header ||                       (entry->next == &map->header ||
Line 200  sys_mincore(p, v, retval)
Line 193  sys_mincore(p, v, retval)
                  * Special case for objects with no "real" pages.  Those                   * Special case for objects with no "real" pages.  Those
                  * are always considered resident (mapped devices).                   * are always considered resident (mapped devices).
                  */                   */
   
                 if (UVM_ET_ISOBJ(entry)) {                  if (UVM_ET_ISOBJ(entry)) {
 #ifdef DIAGNOSTIC                          KASSERT(!UVM_OBJ_IS_KERN_OBJECT(entry->object.uvm_obj));
                         if (UVM_OBJ_IS_KERN_OBJECT(entry->object.uvm_obj))  
                                 panic("mincore: user map has kernel object");  
 #endif  
                         if (entry->object.uvm_obj->pgops->pgo_releasepg                          if (entry->object.uvm_obj->pgops->pgo_releasepg
                             == NULL) {                              == NULL) {
                                 for (/* nothing */; start < lim;                                  for (/* nothing */; start < lim;
Line 230  sys_mincore(p, v, retval)
Line 221  sys_mincore(p, v, retval)
                                     start - entry->start);                                      start - entry->start);
                                 /* Don't need to lock anon here. */                                  /* Don't need to lock anon here. */
                                 if (anon != NULL && anon->u.an_page != NULL) {                                  if (anon != NULL && anon->u.an_page != NULL) {
   
                                         /*                                          /*
                                          * Anon has the page for this entry                                           * Anon has the page for this entry
                                          * offset.                                           * offset.
                                          */                                           */
   
                                         pgi = 1;                                          pgi = 1;
                                 }                                  }
                         }                          }
   
                         if (uobj != NULL && pgi == 0) {                          if (uobj != NULL && pgi == 0) {
                                 /* Check the bottom layer. */                                  /* Check the bottom layer. */
                                 m = uvm_pagelookup(uobj,                                  m = uvm_pagelookup(uobj,
                                     entry->offset + (start - entry->start));                                      entry->offset + (start - entry->start));
                                 if (m != NULL) {                                  if (m != NULL) {
   
                                         /*                                          /*
                                          * Object has the page for this entry                                           * Object has the page for this entry
                                          * offset.                                           * offset.
                                          */                                           */
   
                                         pgi = 1;                                          pgi = 1;
                                 }                                  }
                         }                          }
   
                         (void) subyte(vec, pgi);                          (void) subyte(vec, pgi);
                 }                  }
   
                 if (uobj != NULL)                  if (uobj != NULL)
                         simple_unlock(&uobj->vmobjlock);                          simple_unlock(&uobj->vmobjlock);
                 if (amap != NULL)                  if (amap != NULL)
Line 266  sys_mincore(p, v, retval)
Line 258  sys_mincore(p, v, retval)
         return (error);          return (error);
 }  }
   
 #if 0  
 /*  
  * munmapfd: unmap file descriptor  
  *  
  * XXX: is this acutally a useful function?   could it be useful?  
  */  
   
 void  
 munmapfd(p, fd)  
         struct proc *p;  
         int fd;  
 {  
   
         /*  
          * XXX should vm_deallocate any regions mapped to this file  
          */  
         p->p_fd->fd_ofileflags[fd] &= ~UF_MAPPED;  
 }  
 #endif  
   
 /*  /*
  * sys_mmap: mmap system call.   * sys_mmap: mmap system call.
  *   *
Line 301  sys_mmap(p, v, retval)
Line 273  sys_mmap(p, v, retval)
         void *v;          void *v;
         register_t *retval;          register_t *retval;
 {  {
         register struct sys_mmap_args /* {          struct sys_mmap_args /* {
                 syscallarg(caddr_t) addr;                  syscallarg(caddr_t) addr;
                 syscallarg(size_t) len;                  syscallarg(size_t) len;
                 syscallarg(int) prot;                  syscallarg(int) prot;
Line 317  sys_mmap(p, v, retval)
Line 289  sys_mmap(p, v, retval)
         vm_prot_t prot, maxprot;          vm_prot_t prot, maxprot;
         int flags, fd;          int flags, fd;
         vaddr_t vm_min_address = VM_MIN_ADDRESS;          vaddr_t vm_min_address = VM_MIN_ADDRESS;
         register struct filedesc *fdp = p->p_fd;          struct filedesc *fdp = p->p_fd;
         register struct file *fp;          struct file *fp;
         struct vnode *vp;          struct vnode *vp;
         caddr_t handle;          void *handle;
         int error;          int error;
   
         /*          /*
          * first, extract syscall args from the uap.           * first, extract syscall args from the uap.
          */           */
   
         addr = (vaddr_t) SCARG(uap, addr);          addr = (vaddr_t)SCARG(uap, addr);
         size = (vsize_t) SCARG(uap, len);          size = (vsize_t)SCARG(uap, len);
         prot = SCARG(uap, prot) & VM_PROT_ALL;          prot = SCARG(uap, prot) & VM_PROT_ALL;
         flags = SCARG(uap, flags);          flags = SCARG(uap, flags);
         fd = SCARG(uap, fd);          fd = SCARG(uap, fd);
Line 344  sys_mmap(p, v, retval)
Line 316  sys_mmap(p, v, retval)
                 return (EINVAL);                  return (EINVAL);
   
         /*          /*
          * make sure that the newsize fits within a vaddr_t  
          * XXX: need to revise addressing data types  
          */  
         if (pos + size > (vaddr_t)-PAGE_SIZE) {  
 #ifdef DEBUG  
                 printf("mmap: pos=%qx, size=%lx too big\n", (long long)pos,  
                        (long)size);  
 #endif  
                 return (EINVAL);  
         }  
   
         /*  
          * align file position and save offset.  adjust size.           * align file position and save offset.  adjust size.
          */           */
   
         pageoff = (pos & PAGE_MASK);          pageoff = (pos & PAGE_MASK);
         pos  -= pageoff;          pos  -= pageoff;
         size += pageoff;                        /* add offset */          size += pageoff;                        /* add offset */
         size = (vsize_t) round_page(size);      /* round up */          size = (vsize_t)round_page(size);       /* round up */
         if ((ssize_t) size < 0)          if ((ssize_t) size < 0)
                 return (EINVAL);                        /* don't allow wrap */                  return (EINVAL);                        /* don't allow wrap */
   
Line 391  sys_mmap(p, v, retval)
Line 351  sys_mmap(p, v, retval)
                  * not fixed: make sure we skip over the largest possible heap.                   * not fixed: make sure we skip over the largest possible heap.
                  * we will refine our guess later (e.g. to account for VAC, etc)                   * we will refine our guess later (e.g. to account for VAC, etc)
                  */                   */
                 if (addr < round_page(p->p_vmspace->vm_daddr + MAXDSIZ))  
                         addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ);                  addr = MAX(addr, round_page((vaddr_t)p->p_vmspace->vm_daddr +
                                               MAXDSIZ));
         }          }
   
         /*          /*
Line 415  sys_mmap(p, v, retval)
Line 376  sys_mmap(p, v, retval)
                     vp->v_type != VBLK)                      vp->v_type != VBLK)
                         return (ENODEV);  /* only REG/CHR/BLK support mmap */                          return (ENODEV);  /* only REG/CHR/BLK support mmap */
   
                   if (vp->v_type == VREG && (pos + size) < pos)
                           return (EOVERFLOW);             /* no offset wrapping */
   
                 /* special case: catch SunOS style /dev/zero */                  /* special case: catch SunOS style /dev/zero */
                 if (vp->v_type == VCHR && iszerodev(vp->v_rdev)) {                  if (vp->v_type == VCHR && iszerodev(vp->v_rdev)) {
                         flags |= MAP_ANON;                          flags |= MAP_ANON;
Line 446  sys_mmap(p, v, retval)
Line 410  sys_mmap(p, v, retval)
                  * so just change it to MAP_SHARED.                   * so just change it to MAP_SHARED.
                  */                   */
                 if (vp->v_type == VCHR && (flags & MAP_PRIVATE) != 0) {                  if (vp->v_type == VCHR && (flags & MAP_PRIVATE) != 0) {
 #if defined(DIAGNOSTIC)  
                         printf("WARNING: converted MAP_PRIVATE device mapping "  
                             "to MAP_SHARED (pid %d comm %s)\n", p->p_pid,  
                             p->p_comm);  
 #endif  
                         flags = (flags & ~MAP_PRIVATE) | MAP_SHARED;                          flags = (flags & ~MAP_PRIVATE) | MAP_SHARED;
                 }                  }
   
Line 489  sys_mmap(p, v, retval)
Line 448  sys_mmap(p, v, retval)
                         /* MAP_PRIVATE mappings can always write to */                          /* MAP_PRIVATE mappings can always write to */
                         maxprot |= VM_PROT_WRITE;                          maxprot |= VM_PROT_WRITE;
                 }                  }
                   handle = vp;
                 /*  
                  * set handle to vnode  
                  */  
   
                 handle = (caddr_t)vp;  
   
         } else {                /* MAP_ANON case */          } else {                /* MAP_ANON case */
                 /*                  /*
Line 519  sys_mmap(p, v, retval)
Line 473  sys_mmap(p, v, retval)
         if ((flags & MAP_ANON) != 0 ||          if ((flags & MAP_ANON) != 0 ||
             ((flags & MAP_PRIVATE) != 0 && (prot & PROT_WRITE) != 0)) {              ((flags & MAP_PRIVATE) != 0 && (prot & PROT_WRITE) != 0)) {
                 if (size >                  if (size >
                     (p->p_rlimit[RLIMIT_DATA].rlim_cur - ctob(p->p_vmspace->vm_dsize))) {                      (p->p_rlimit[RLIMIT_DATA].rlim_cur -
                        ctob(p->p_vmspace->vm_dsize))) {
                         return (ENOMEM);                          return (ENOMEM);
                 }                  }
         }          }
Line 556  sys___msync13(p, v, retval)
Line 511  sys___msync13(p, v, retval)
         vaddr_t addr;          vaddr_t addr;
         vsize_t size, pageoff;          vsize_t size, pageoff;
         vm_map_t map;          vm_map_t map;
         int rv, flags, uvmflags;          int error, rv, flags, uvmflags;
   
         /*          /*
          * extract syscall args from the uap           * extract syscall args from the uap
Line 575  sys___msync13(p, v, retval)
Line 530  sys___msync13(p, v, retval)
           flags |= MS_SYNC;            flags |= MS_SYNC;
   
         /*          /*
          * align the address to a page boundary, and adjust the size accordingly           * align the address to a page boundary and adjust the size accordingly.
          */           */
   
         pageoff = (addr & PAGE_MASK);          pageoff = (addr & PAGE_MASK);
         addr -= pageoff;          addr -= pageoff;
         size += pageoff;          size += pageoff;
         size = (vsize_t) round_page(size);          size = (vsize_t)round_page(size);
   
         /* disallow wrap-around. */          /* disallow wrap-around. */
         if (addr + size < addr)          if (addr + size < addr)
Line 603  sys___msync13(p, v, retval)
Line 558  sys___msync13(p, v, retval)
          * This can be incorrect if the region splits or is coalesced           * This can be incorrect if the region splits or is coalesced
          * with a neighbor.           * with a neighbor.
          */           */
   
         if (size == 0) {          if (size == 0) {
                 vm_map_entry_t entry;                  vm_map_entry_t entry;
   
Line 620  sys___msync13(p, v, retval)
Line 576  sys___msync13(p, v, retval)
         /*          /*
          * translate MS_ flags into PGO_ flags           * translate MS_ flags into PGO_ flags
          */           */
   
         uvmflags = PGO_CLEANIT;          uvmflags = PGO_CLEANIT;
         if (flags & MS_INVALIDATE)          if (flags & MS_INVALIDATE)
                 uvmflags |= PGO_FREE;                  uvmflags |= PGO_FREE;
Line 628  sys___msync13(p, v, retval)
Line 585  sys___msync13(p, v, retval)
         else          else
                 uvmflags |= PGO_SYNCIO;  /* XXXCDC: force sync for now! */                  uvmflags |= PGO_SYNCIO;  /* XXXCDC: force sync for now! */
   
         /*          error = uvm_map_clean(map, addr, addr+size, uvmflags);
          * doit!          return error;
          */  
         rv = uvm_map_clean(map, addr, addr+size, uvmflags);  
   
         /*  
          * and return...  
          */  
         switch (rv) {  
         case KERN_SUCCESS:  
                 return(0);  
         case KERN_INVALID_ADDRESS:  
                 return (ENOMEM);  
         case KERN_FAILURE:  
                 return (EIO);  
         case KERN_PAGES_LOCKED: /* XXXCDC: uvm doesn't return this */  
                 return (EBUSY);  
         default:  
                 return (EINVAL);  
         }  
         /*NOTREACHED*/  
 }  }
   
 /*  /*
Line 657  sys___msync13(p, v, retval)
Line 595  sys___msync13(p, v, retval)
   
 int  int
 sys_munmap(p, v, retval)  sys_munmap(p, v, retval)
         register struct proc *p;          struct proc *p;
         void *v;          void *v;
         register_t *retval;          register_t *retval;
 {  {
         register struct sys_munmap_args /* {          struct sys_munmap_args /* {
                 syscallarg(caddr_t) addr;                  syscallarg(caddr_t) addr;
                 syscallarg(size_t) len;                  syscallarg(size_t) len;
         } */ *uap = v;          } */ *uap = v;
Line 672  sys_munmap(p, v, retval)
Line 610  sys_munmap(p, v, retval)
         struct vm_map_entry *dead_entries;          struct vm_map_entry *dead_entries;
   
         /*          /*
          * get syscall args...           * get syscall args.
          */           */
   
         addr = (vaddr_t) SCARG(uap, addr);          addr = (vaddr_t)SCARG(uap, addr);
         size = (vsize_t) SCARG(uap, len);          size = (vsize_t)SCARG(uap, len);
   
         /*          /*
          * align the address to a page boundary, and adjust the size accordingly           * align the address to a page boundary and adjust the size accordingly.
          */           */
   
         pageoff = (addr & PAGE_MASK);          pageoff = (addr & PAGE_MASK);
         addr -= pageoff;          addr -= pageoff;
         size += pageoff;          size += pageoff;
         size = (vsize_t) round_page(size);          size = (vsize_t)round_page(size);
   
         if ((int)size < 0)          if ((int)size < 0)
                 return (EINVAL);                  return (EINVAL);
Line 704  sys_munmap(p, v, retval)
Line 642  sys_munmap(p, v, retval)
                 return (EINVAL);                  return (EINVAL);
         map = &p->p_vmspace->vm_map;          map = &p->p_vmspace->vm_map;
   
   
         vm_map_lock(map);       /* lock map so we can checkprot */  
   
         /*          /*
          * interesting system call semantic: make sure entire range is           * interesting system call semantic: make sure entire range is
          * allocated before allowing an unmap.           * allocated before allowing an unmap.
          */           */
   
           vm_map_lock(map);
         if (!uvm_map_checkprot(map, addr, addr + size, VM_PROT_NONE)) {          if (!uvm_map_checkprot(map, addr, addr + size, VM_PROT_NONE)) {
                 vm_map_unlock(map);                  vm_map_unlock(map);
                 return (EINVAL);                  return (EINVAL);
         }          }
           uvm_unmap_remove(map, addr, addr + size, &dead_entries);
         /*          vm_map_unlock(map);
          * doit!  
          */  
         (void) uvm_unmap_remove(map, addr, addr + size, &dead_entries);  
   
         vm_map_unlock(map);     /* and unlock */  
   
         if (dead_entries != NULL)          if (dead_entries != NULL)
                 uvm_unmap_detach(dead_entries, 0);                  uvm_unmap_detach(dead_entries, 0);
   
         return (0);          return (0);
 }  }
   
Line 748  sys_mprotect(p, v, retval)
Line 677  sys_mprotect(p, v, retval)
         vaddr_t addr;          vaddr_t addr;
         vsize_t size, pageoff;          vsize_t size, pageoff;
         vm_prot_t prot;          vm_prot_t prot;
         int rv;          int error;
   
         /*          /*
          * extract syscall args from uap           * extract syscall args from uap
Line 759  sys_mprotect(p, v, retval)
Line 688  sys_mprotect(p, v, retval)
         prot = SCARG(uap, prot) & VM_PROT_ALL;          prot = SCARG(uap, prot) & VM_PROT_ALL;
   
         /*          /*
          * align the address to a page boundary, and adjust the size accordingly           * align the address to a page boundary and adjust the size accordingly.
          */           */
   
         pageoff = (addr & PAGE_MASK);          pageoff = (addr & PAGE_MASK);
         addr -= pageoff;          addr -= pageoff;
         size += pageoff;          size += pageoff;
         size = (vsize_t) round_page(size);          size = (vsize_t)round_page(size);
   
         if ((int)size < 0)          if ((int)size < 0)
                 return (EINVAL);                  return (EINVAL);
           error = uvm_map_protect(&p->p_vmspace->vm_map, addr, addr + size, prot,
         /*                                  FALSE);
          * doit          return error;
          */  
   
         rv = uvm_map_protect(&p->p_vmspace->vm_map,  
                            addr, addr+size, prot, FALSE);  
   
         if (rv == KERN_SUCCESS)  
                 return (0);  
         if (rv == KERN_PROTECTION_FAILURE)  
                 return (EACCES);  
         return (EINVAL);  
 }  }
   
 /*  /*
Line 799  sys_minherit(p, v, retval)
Line 720  sys_minherit(p, v, retval)
         } */ *uap = v;          } */ *uap = v;
         vaddr_t addr;          vaddr_t addr;
         vsize_t size, pageoff;          vsize_t size, pageoff;
         register vm_inherit_t inherit;          vm_inherit_t inherit;
           int error;
   
         addr = (vaddr_t)SCARG(uap, addr);          addr = (vaddr_t)SCARG(uap, addr);
         size = (vsize_t)SCARG(uap, len);          size = (vsize_t)SCARG(uap, len);
         inherit = SCARG(uap, inherit);          inherit = SCARG(uap, inherit);
   
         /*          /*
          * align the address to a page boundary, and adjust the size accordingly           * align the address to a page boundary and adjust the size accordingly.
          */           */
   
         pageoff = (addr & PAGE_MASK);          pageoff = (addr & PAGE_MASK);
         addr -= pageoff;          addr -= pageoff;
         size += pageoff;          size += pageoff;
         size = (vsize_t) round_page(size);          size = (vsize_t)round_page(size);
   
         if ((int)size < 0)          if ((int)size < 0)
                 return (EINVAL);                  return (EINVAL);
           error = uvm_map_inherit(&p->p_vmspace->vm_map, addr, addr + size,
         switch (uvm_map_inherit(&p->p_vmspace->vm_map, addr, addr+size,                                  inherit);
                          inherit)) {          return error;
         case KERN_SUCCESS:  
                 return (0);  
         case KERN_PROTECTION_FAILURE:  
                 return (EACCES);  
         }  
         return (EINVAL);  
 }  }
   
 /*  /*
Line 844  sys_madvise(p, v, retval)
Line 761  sys_madvise(p, v, retval)
         } */ *uap = v;          } */ *uap = v;
         vaddr_t addr;          vaddr_t addr;
         vsize_t size, pageoff;          vsize_t size, pageoff;
         int advice, rv;;          int advice, error;
   
         addr = (vaddr_t)SCARG(uap, addr);          addr = (vaddr_t)SCARG(uap, addr);
         size = (vsize_t)SCARG(uap, len);          size = (vsize_t)SCARG(uap, len);
Line 853  sys_madvise(p, v, retval)
Line 770  sys_madvise(p, v, retval)
         /*          /*
          * align the address to a page boundary, and adjust the size accordingly           * align the address to a page boundary, and adjust the size accordingly
          */           */
   
         pageoff = (addr & PAGE_MASK);          pageoff = (addr & PAGE_MASK);
         addr -= pageoff;          addr -= pageoff;
         size += pageoff;          size += pageoff;
         size = (vsize_t) round_page(size);          size = (vsize_t)round_page(size);
   
         if ((ssize_t)size <= 0)          if ((ssize_t)size <= 0)
                 return (EINVAL);                  return (EINVAL);
Line 865  sys_madvise(p, v, retval)
Line 783  sys_madvise(p, v, retval)
         case MADV_NORMAL:          case MADV_NORMAL:
         case MADV_RANDOM:          case MADV_RANDOM:
         case MADV_SEQUENTIAL:          case MADV_SEQUENTIAL:
                 rv = uvm_map_advice(&p->p_vmspace->vm_map, addr, addr + size,                  error = uvm_map_advice(&p->p_vmspace->vm_map, addr, addr + size,
                     advice);                      advice);
                 break;                  break;
   
         case MADV_WILLNEED:          case MADV_WILLNEED:
   
                 /*                  /*
                  * Activate all these pages, pre-faulting them in if                   * Activate all these pages, pre-faulting them in if
                  * necessary.                   * necessary.
Line 879  sys_madvise(p, v, retval)
Line 798  sys_madvise(p, v, retval)
                  * Should invent a "weak" mode for uvm_fault()                   * Should invent a "weak" mode for uvm_fault()
                  * which would only do the PGO_LOCKED pgo_get().                   * which would only do the PGO_LOCKED pgo_get().
                  */                   */
   
                 return (0);                  return (0);
   
         case MADV_DONTNEED:          case MADV_DONTNEED:
   
                 /*                  /*
                  * Deactivate all these pages.  We don't need them                   * Deactivate all these pages.  We don't need them
                  * any more.  We don't, however, toss the data in                   * any more.  We don't, however, toss the data in
                  * the pages.                   * the pages.
                  */                   */
                 rv = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size,  
                   error = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size,
                     PGO_DEACTIVATE);                      PGO_DEACTIVATE);
                 break;                  break;
   
         case MADV_FREE:          case MADV_FREE:
   
                 /*                  /*
                  * These pages contain no valid data, and may be                   * These pages contain no valid data, and may be
                  * grbage-collected.  Toss all resources, including                   * garbage-collected.  Toss all resources, including
                  * any swap space in use.                   * any swap space in use.
                  */                   */
                 rv = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size,  
                   error = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size,
                     PGO_FREE);                      PGO_FREE);
                 break;                  break;
   
         case MADV_SPACEAVAIL:          case MADV_SPACEAVAIL:
   
                 /*                  /*
                  * XXXMRG What is this?  I think it's:                   * XXXMRG What is this?  I think it's:
                  *                   *
Line 912  sys_madvise(p, v, retval)
Line 837  sys_madvise(p, v, retval)
                  * as it will free swap space allocated to pages in core.                   * as it will free swap space allocated to pages in core.
                  * There's also what to do for device/file/anonymous memory.                   * There's also what to do for device/file/anonymous memory.
                  */                   */
   
                 return (EINVAL);                  return (EINVAL);
   
         default:          default:
                 return (EINVAL);                  return (EINVAL);
         }          }
   
         switch (rv) {          return error;
         case KERN_SUCCESS:  
                 return (0);  
         case KERN_NO_SPACE:  
                 return (EAGAIN);  
         case KERN_INVALID_ADDRESS:  
                 return (ENOMEM);  
         case KERN_FAILURE:  
                 return (EIO);  
         }  
   
         return (EINVAL);  
 }  }
   
 /*  /*
Line 953  sys_mlock(p, v, retval)
Line 868  sys_mlock(p, v, retval)
         /*          /*
          * extract syscall args from uap           * extract syscall args from uap
          */           */
   
         addr = (vaddr_t)SCARG(uap, addr);          addr = (vaddr_t)SCARG(uap, addr);
         size = (vsize_t)SCARG(uap, len);          size = (vsize_t)SCARG(uap, len);
   
         /*          /*
          * align the address to a page boundary and adjust the size accordingly           * align the address to a page boundary and adjust the size accordingly
          */           */
   
         pageoff = (addr & PAGE_MASK);          pageoff = (addr & PAGE_MASK);
         addr -= pageoff;          addr -= pageoff;
         size += pageoff;          size += pageoff;
         size = (vsize_t) round_page(size);          size = (vsize_t)round_page(size);
   
         /* disallow wrap-around. */          /* disallow wrap-around. */
         if (addr + (int)size < addr)          if (addr + size < addr)
                 return (EINVAL);                  return (EINVAL);
   
         if (atop(size) + uvmexp.wired > uvmexp.wiredmax)          if (atop(size) + uvmexp.wired > uvmexp.wiredmax)
Line 982  sys_mlock(p, v, retval)
Line 899  sys_mlock(p, v, retval)
   
         error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, FALSE,          error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, FALSE,
             0);              0);
         return (error == KERN_SUCCESS ? 0 : ENOMEM);          return error;
 }  }
   
 /*  /*
Line 1013  sys_munlock(p, v, retval)
Line 930  sys_munlock(p, v, retval)
         /*          /*
          * align the address to a page boundary, and adjust the size accordingly           * align the address to a page boundary, and adjust the size accordingly
          */           */
   
         pageoff = (addr & PAGE_MASK);          pageoff = (addr & PAGE_MASK);
         addr -= pageoff;          addr -= pageoff;
         size += pageoff;          size += pageoff;
         size = (vsize_t) round_page(size);          size = (vsize_t)round_page(size);
   
         /* disallow wrap-around. */          /* disallow wrap-around. */
         if (addr + (int)size < addr)          if (addr + size < addr)
                 return (EINVAL);                  return (EINVAL);
   
 #ifndef pmap_wired_count  #ifndef pmap_wired_count
Line 1029  sys_munlock(p, v, retval)
Line 947  sys_munlock(p, v, retval)
   
         error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, TRUE,          error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, TRUE,
             0);              0);
         return (error == KERN_SUCCESS ? 0 : ENOMEM);          return error;
 }  }
   
 /*  /*
Line 1060  sys_mlockall(p, v, retval)
Line 978  sys_mlockall(p, v, retval)
   
         error = uvm_map_pageable_all(&p->p_vmspace->vm_map, flags,          error = uvm_map_pageable_all(&p->p_vmspace->vm_map, flags,
             p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);              p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);
         switch (error) {  
         case KERN_SUCCESS:  
                 error = 0;  
                 break;  
   
         case KERN_NO_SPACE:     /* XXX overloaded */  
                 error = ENOMEM;  
                 break;  
   
         default:  
                 /*  
                  * "Some or all of the memory could not be locked when  
                  * the call was made."  
                  */  
                 error = EAGAIN;  
         }  
   
         return (error);          return (error);
 }  }
   
Line 1111  uvm_mmap(map, addr, size, prot, maxprot,
Line 1012  uvm_mmap(map, addr, size, prot, maxprot,
         vsize_t size;          vsize_t size;
         vm_prot_t prot, maxprot;          vm_prot_t prot, maxprot;
         int flags;          int flags;
         caddr_t handle;         /* XXX: VNODE? */          void *handle;
         vaddr_t foff;          voff_t foff;
         vsize_t locklimit;          vsize_t locklimit;
 {  {
         struct uvm_object *uobj;          struct uvm_object *uobj;
         struct vnode *vp;          struct vnode *vp;
         int retval;          int error;
         int advice = UVM_ADV_NORMAL;          int advice = UVM_ADV_NORMAL;
         uvm_flag_t uvmflag = 0;          uvm_flag_t uvmflag = 0;
   
Line 1140  uvm_mmap(map, addr, size, prot, maxprot,
Line 1041  uvm_mmap(map, addr, size, prot, maxprot,
         if ((flags & MAP_FIXED) == 0) {          if ((flags & MAP_FIXED) == 0) {
                 *addr = round_page(*addr);      /* round */                  *addr = round_page(*addr);      /* round */
         } else {          } else {
   
                 if (*addr & PAGE_MASK)                  if (*addr & PAGE_MASK)
                         return(EINVAL);                          return(EINVAL);
                 uvmflag |= UVM_FLAG_FIXED;                  uvmflag |= UVM_FLAG_FIXED;
Line 1153  uvm_mmap(map, addr, size, prot, maxprot,
Line 1053  uvm_mmap(map, addr, size, prot, maxprot,
          */           */
   
         if (flags & MAP_ANON) {          if (flags & MAP_ANON) {
                   foff = UVM_UNKNOWN_OFFSET;
                 foff = UVM_UNKNOWN_OFFSET;  
                 uobj = NULL;                  uobj = NULL;
                 if ((flags & MAP_SHARED) == 0)                  if ((flags & MAP_SHARED) == 0)
                         /* XXX: defer amap create */                          /* XXX: defer amap create */
Line 1164  uvm_mmap(map, addr, size, prot, maxprot,
Line 1063  uvm_mmap(map, addr, size, prot, maxprot,
                         uvmflag |= UVM_FLAG_OVERLAY;                          uvmflag |= UVM_FLAG_OVERLAY;
   
         } else {          } else {
                   vp = (struct vnode *)handle;
                 vp = (struct vnode *) handle;   /* get vnode */  
                 if (vp->v_type != VCHR) {                  if (vp->v_type != VCHR) {
                         uobj = uvn_attach((void *) vp, (flags & MAP_SHARED) ?                          uobj = uvn_attach((void *)vp, (flags & MAP_SHARED) ?
                            maxprot : (maxprot & ~VM_PROT_WRITE));                             maxprot : (maxprot & ~VM_PROT_WRITE));
   
                           /* XXX for now, attach doesn't gain a ref */
                           VREF(vp);
                   } else {
                           uobj = udv_attach((void *) &vp->v_rdev,
                               (flags & MAP_SHARED) ? maxprot :
                               (maxprot & ~VM_PROT_WRITE), foff, size);
                         /*                          /*
                          * XXXCDC: hack from old code                           * XXX Some devices don't like to be mapped with
                          * don't allow vnodes which have been mapped                           * XXX PROT_EXEC, but we don't really have a
                          * shared-writeable to persist [forces them to be                           * XXX better way of handling this, right now
                          * flushed out when last reference goes].  
                          * XXXCDC: interesting side effect: avoids a bug.  
                          * note that in WRITE [ufs_readwrite.c] that we  
                          * allocate buffer, uncache, and then do the write.  
                          * the problem with this is that if the uncache causes  
                          * VM data to be flushed to the same area of the file  
                          * we are writing to... in that case we've got the  
                          * buffer locked and our process goes to sleep forever.  
                          *  
                          * XXXCDC: checking maxprot protects us from the  
                          * "persistbug" program but this is not a long term  
                          * solution.  
                          *  
                          * XXXCDC: we don't bother calling uncache with the vp  
                          * VOP_LOCKed since we know that we are already  
                          * holding a valid reference to the uvn (from the  
                          * uvn_attach above), and thus it is impossible for  
                          * the uncache to kill the uvn and trigger I/O.  
                          */                           */
                         if (flags & MAP_SHARED) {                          if (uobj == NULL && (prot & PROT_EXEC) == 0) {
                                 if ((prot & VM_PROT_WRITE) ||                                  maxprot &= ~VM_PROT_EXECUTE;
                                     (maxprot & VM_PROT_WRITE)) {                                  uobj = udv_attach((void *)&vp->v_rdev,
                                         uvm_vnp_uncache(vp);                                      (flags & MAP_SHARED) ? maxprot :
                                 }                                      (maxprot & ~VM_PROT_WRITE), foff, size);
                         }                          }
   
                 } else {  
                         uobj = udv_attach((void *) &vp->v_rdev,  
                             (flags & MAP_SHARED) ?  
                             maxprot : (maxprot & ~VM_PROT_WRITE), foff, size);  
                         advice = UVM_ADV_RANDOM;                          advice = UVM_ADV_RANDOM;
                 }                  }
   
                 if (uobj == NULL)                  if (uobj == NULL)
                         return((vp->v_type == VREG) ? ENOMEM : EINVAL);                          return((vp->v_type == VREG) ? ENOMEM : EINVAL);
   
                 if ((flags & MAP_SHARED) == 0)                  if ((flags & MAP_SHARED) == 0)
                         uvmflag |= UVM_FLAG_COPYONW;                          uvmflag |= UVM_FLAG_COPYONW;
         }          }
   
         /*  
          * set up mapping flags  
          */  
   
         uvmflag = UVM_MAPFLAG(prot, maxprot,          uvmflag = UVM_MAPFLAG(prot, maxprot,
                         (flags & MAP_SHARED) ? UVM_INH_SHARE : UVM_INH_COPY,                          (flags & MAP_SHARED) ? UVM_INH_SHARE : UVM_INH_COPY,
                         advice, uvmflag);                          advice, uvmflag);
           error = uvm_map(map, addr, size, uobj, foff, 0, uvmflag);
           if (error) {
                   if (uobj)
                           uobj->pgops->pgo_detach(uobj);
                   return error;
           }
   
         /*          /*
          * do it!           * POSIX 1003.1b -- if our address space was configured
            * to lock all future mappings, wire the one we just made.
          */           */
   
         retval = uvm_map(map, addr, size, uobj, foff, uvmflag);          if (prot == VM_PROT_NONE) {
   
         if (retval == KERN_SUCCESS) {  
                 /*                  /*
                  * POSIX 1003.1b -- if our address space was configured                   * No more work to do in this case.
                  * to lock all future mappings, wire the one we just made.  
                  */                   */
                 if (prot == VM_PROT_NONE) {  
                         /*  
                          * No more work to do in this case.  
                          */  
                         return (0);  
                 }  
   
                 vm_map_lock(map);  
   
                 if (map->flags & VM_MAP_WIREFUTURE) {                  return (0);
                         /*          }
                          * uvm_map_pageable() always returns the map          vm_map_lock(map);
                          * unlocked.          if (map->flags & VM_MAP_WIREFUTURE) {
                          */                  if ((atop(size) + uvmexp.wired) > uvmexp.wiredmax
                         if ((atop(size) + uvmexp.wired) > uvmexp.wiredmax  
 #ifdef pmap_wired_count  #ifdef pmap_wired_count
                             || (locklimit != 0 && (size +                      || (locklimit != 0 && (size +
                                  ptoa(pmap_wired_count(vm_map_pmap(map)))) >                      ptoa(pmap_wired_count(vm_map_pmap(map)))) >
                                 locklimit)                          locklimit)
 #endif  #endif
                         ) {                  ) {
                                 retval = KERN_RESOURCE_SHORTAGE;                          vm_map_unlock(map);
                                 /* unmap the region! */                          uvm_unmap(map, *addr, *addr + size);
                                 (void) uvm_unmap(map, *addr, *addr + size);                          return ENOMEM;
                                 goto bad;  
                         }  
                         retval = uvm_map_pageable(map, *addr, *addr + size,  
                             FALSE, UVM_LK_ENTER);  
                         if (retval != KERN_SUCCESS) {  
                                 /* unmap the region! */  
                                 (void) uvm_unmap(map, *addr, *addr + size);  
                                 goto bad;  
                         }  
                         return (0);  
                 }                  }
   
                 vm_map_unlock(map);                  /*
                    * uvm_map_pageable() always returns the map unlocked.
                    */
   
                   error = uvm_map_pageable(map, *addr, *addr + size,
                                            FALSE, UVM_LK_ENTER);
                   if (error) {
                           uvm_unmap(map, *addr, *addr + size);
                           return error;
                   }
                 return (0);                  return (0);
         }          }
           vm_map_unlock(map);
         /*          return 0;
          * errors: first detach from the uobj, if any.  
          */  
   
         if (uobj)  
                 uobj->pgops->pgo_detach(uobj);  
   
  bad:  
         switch (retval) {  
         case KERN_INVALID_ADDRESS:  
         case KERN_NO_SPACE:  
                 return(ENOMEM);  
         case KERN_RESOURCE_SHORTAGE:  
                 return (EAGAIN);  
         case KERN_PROTECTION_FAILURE:  
                 return(EACCES);  
         }  
         return(EINVAL);  
 }  }

Legend:
Removed from v.1.35  
changed lines
  Added in v.1.35.2.5

CVSweb <webmaster@jp.NetBSD.org>