Exemple #1
0
/* Create a new pager in USER_PAGER with NPAGES pages, and return a
   mapping to the memory in *USER.  */
error_t
user_pager_create (struct user_pager *user_pager, unsigned int npages,
		   struct cons_display **user)
{
  error_t err;
  struct user_pager_info *upi;

  upi = calloc (1, sizeof (struct user_pager_info)
		+ sizeof (vm_address_t) * npages);
  if (!upi)
    return errno;

  upi->memobj_npages = npages;

  /* XXX Are the values 1 and MEMORY_OBJECT_COPY_DELAY correct? */
  user_pager->pager = pager_create (upi, pager_bucket,
				    1, MEMORY_OBJECT_COPY_DELAY, 0);
  if (!user_pager->pager)
    {
      free (upi);
      return errno;
    }
  user_pager->memobj = pager_get_port (user_pager->pager);
  ports_port_deref (user_pager->pager);

  mach_port_insert_right (mach_task_self (), user_pager->memobj,
			  user_pager->memobj, MACH_MSG_TYPE_MAKE_SEND);

  *user = 0;
  err = vm_map (mach_task_self (),
		(vm_address_t *) user,
		(vm_size_t) npages * vm_page_size,
		(vm_address_t) 0,
		1 /* ! (flags & MAP_FIXED) */,
		user_pager->memobj, 0 /* (vm_offset_t) offset */,
		0 /* ! (flags & MAP_SHARED) */,
                VM_PROT_READ | VM_PROT_WRITE,
                VM_PROT_READ | VM_PROT_WRITE,
                VM_INHERIT_NONE);
  if (err)
    {
      /* UPI will be cleaned up by libpager.  */
      mach_port_deallocate (mach_task_self (), user_pager->memobj);
      return err;
    }

  return 0;
}
void
diskfs_start_disk_pager (struct user_pager_info *upi,
			 struct port_bucket *pager_bucket, int may_cache,
			 size_t size, void **image)
{
  error_t err;
  mach_port_t disk_pager_port;

  /* Make a thread to service paging requests.  */
  cthread_detach (cthread_fork ((cthread_fn_t) service_paging_requests,
				(any_t)pager_bucket));

  /* Create the pager.  */
  diskfs_disk_pager = pager_create (upi, pager_bucket,
				    may_cache, MEMORY_OBJECT_COPY_NONE);
  assert (diskfs_disk_pager);

  /* Get a port to the disk pager.  */
  disk_pager_port = pager_get_port (diskfs_disk_pager);
  mach_port_insert_right (mach_task_self (), disk_pager_port, disk_pager_port,
			  MACH_MSG_TYPE_MAKE_SEND);

  /* Now map the disk image.  */
  err = vm_map (mach_task_self (), (vm_address_t *)image, size,
		0, 1, disk_pager_port, 0, 0,
		VM_PROT_READ | (diskfs_readonly ? 0 : VM_PROT_WRITE),
		VM_PROT_READ | VM_PROT_WRITE,
		VM_INHERIT_NONE);
  if (err)
    error (2, err, "cannot vm_map whole disk");

  /* Set up the signal preemptor to catch faults on the disk image.  */
  preemptor.first = (vm_address_t) *image;
  preemptor.last = ((vm_address_t) *image + size);
  hurd_preempt_signals (&preemptor);

  /* We have the mapping; we no longer need the send right.  */
  mach_port_deallocate (mach_task_self (), disk_pager_port);
}