/[hurd]/hurd/serverboot/default_pager.c
ViewVC logotype

Diff of /hurd/serverboot/default_pager.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.24 by roland, Sun Apr 1 01:41:05 2001 UTC revision 1.25 by roland, Sun Mar 24 01:12:42 2002 UTC
# Line 651  struct dpager { Line 651  struct dpager {
651  #endif  #endif
652          dp_map_t        map;            /* block map */          dp_map_t        map;            /* block map */
653          vm_size_t       size;           /* size of paging object, in pages */          vm_size_t       size;           /* size of paging object, in pages */
654            vm_size_t       limit;  /* limit (bytes) allowed to grow to */
655          p_index_t       cur_partition;          p_index_t       cur_partition;
656  #ifdef  CHECKSUM  #ifdef  CHECKSUM
657          vm_offset_t     *checksum;      /* checksum - parallel to block map */          vm_offset_t     *checksum;      /* checksum - parallel to block map */
# Line 739  pager_alloc(pager, part, size) Line 740  pager_alloc(pager, part, size)
740          }          }
741          pager->map = mapptr;          pager->map = mapptr;
742          pager->size = size;          pager->size = size;
743            pager->limit = (vm_size_t)-1;
744    
745  #ifdef  CHECKSUM  #ifdef  CHECKSUM
746          if (INDIRECT_PAGEMAP(size)) {          if (INDIRECT_PAGEMAP(size)) {
# Line 913  pager_extend(pager, new_size) Line 915  pager_extend(pager, new_size)
915              pager->writer = FALSE;              pager->writer = FALSE;
916  #endif  #endif
917              mutex_unlock(&pager->lock);              mutex_unlock(&pager->lock);
918    #if 0
919              ddprintf ("pager_extend 1 mapptr %x [3b] = %x\n", new_mapptr,              ddprintf ("pager_extend 1 mapptr %x [3b] = %x\n", new_mapptr,
920                       new_mapptr[0x3b]);                       new_mapptr[0x3b]);
921              if (new_mapptr[0x3b].indirect > 0x10000              if (new_mapptr[0x3b].indirect > 0x10000
922                  && new_mapptr[0x3b].indirect != NO_BLOCK)                  && new_mapptr[0x3b].indirect != NO_BLOCK)
923                panic ("debug panic");                panic ("debug panic");
924    #endif
925              return;              return;
926          }          }
927    
# Line 941  pager_extend(pager, new_size) Line 945  pager_extend(pager, new_size)
945              kfree((char *)old_mapptr, PAGEMAP_SIZE(old_size));              kfree((char *)old_mapptr, PAGEMAP_SIZE(old_size));
946              old_mapptr = new_mapptr;              old_mapptr = new_mapptr;
947    
948    #if 0
949              ddprintf ("pager_extend 2 mapptr %x [3b] = %x\n", new_mapptr,              ddprintf ("pager_extend 2 mapptr %x [3b] = %x\n", new_mapptr,
950                       new_mapptr[0x3b]);                       new_mapptr[0x3b]);
951              if (new_mapptr[0x3b].indirect > 0x10000              if (new_mapptr[0x3b].indirect > 0x10000
952                  && new_mapptr[0x3b].indirect != NO_BLOCK)                  && new_mapptr[0x3b].indirect != NO_BLOCK)
953                panic ("debug panic");                panic ("debug panic");
954    #endif
955    
956              /*              /*
957               * Now allocate indirect map.               * Now allocate indirect map.
# Line 1015  pager_extend(pager, new_size) Line 1021  pager_extend(pager, new_size)
1021          mutex_unlock(&pager->lock);          mutex_unlock(&pager->lock);
1022  }  }
1023    
1024    /* Truncate a memory object.  First, any pages between the new size
1025       and the (larger) old size are deallocated.  Then, the size of
1026       the pagemap may be reduced, an indirect map may be turned into
1027       a direct map.
1028    
1029       The pager must be locked by the caller.  */
1030    static void
1031    pager_truncate(dpager_t pager, vm_size_t new_size)      /* in pages */
1032    {
1033      dp_map_t new_mapptr;
1034      dp_map_t old_mapptr;
1035      int i;
1036      vm_size_t old_size;
1037    
1038      /* This deallocates the pages necessary to truncate a direct map
1039         previously of size NEW_SIZE to the smaller size OLD_SIZE.  */
1040      inline void dealloc_direct (dp_map_t mapptr,
1041                                  vm_size_t old_size, vm_size_t new_size)
1042        {
1043          vm_size_t i;
1044          for (i = new_size; i < old_size; ++i)
1045            {
1046              const union dp_map entry = mapptr[i];
1047              pager_dealloc_page(entry.block.p_index, entry.block.p_offset,
1048                                 TRUE);
1049              invalidate_block(mapptr[i]);
1050            }
1051        }
1052    
1053      old_size = pager->size;
1054    
1055      if (INDIRECT_PAGEMAP(old_size))
1056        {
1057          /* First handle the entire second-levels blocks that are being freed.  */
1058          for (i = INDIRECT_PAGEMAP_ENTRIES(new_size);
1059               i < INDIRECT_PAGEMAP_ENTRIES(old_size);
1060               ++i)
1061            {
1062              const dp_map_t mapptr = pager->map[i].indirect;
1063              pager->map[i].indirect = (dp_map_t)0;
1064              dealloc_direct (mapptr, PAGEMAP_ENTRIES, 0);
1065              kfree ((char *)mapptr, PAGEMAP_SIZE(PAGEMAP_ENTRIES));
1066            }
1067    
1068          /* Now truncate what's now the final nonempty direct block.  */
1069          dealloc_direct (pager->map[(new_size - 1) / PAGEMAP_ENTRIES].indirect,
1070                          old_size & (PAGEMAP_ENTRIES - 1),
1071                          new_size & (PAGEMAP_ENTRIES - 1));
1072    
1073          if (INDIRECT_PAGEMAP (new_size))
1074            {
1075              if (INDIRECT_PAGEMAP_SIZE (new_size) >= vm_page_size)
1076                /* XXX we know how kalloc.c works; avoid copying.  */
1077                kfree ((char *) round_page ((vm_address_t) pager->map
1078                                            + INDIRECT_PAGEMAP_SIZE (new_size)),
1079                       round_page (INDIRECT_PAGEMAP_SIZE (old_size))
1080                       - round_page (INDIRECT_PAGEMAP_SIZE (new_size)));
1081              else
1082                {
1083                  const dp_map_t old_mapptr = pager->map;
1084                  pager->map = (dp_map_t) kalloc (INDIRECT_PAGEMAP_SIZE(new_size));
1085                  memcpy (pager->map, old_mapptr, INDIRECT_PAGEMAP_SIZE(old_size));
1086                  kfree ((char *) old_mapptr, INDIRECT_PAGEMAP_SIZE (old_size));
1087                }
1088            }
1089          else
1090            {
1091              /* We are truncating to a size small enough that it goes to using
1092                 a one-level map.  We already have that map, as the first and only
1093                 nonempty element in our indirect map.  */
1094              const dp_map_t mapptr = pager->map[0].indirect;
1095              kfree((char *)pager->map, INDIRECT_PAGEMAP_SIZE(old_size));
1096              pager->map = mapptr;
1097              old_size = PAGEMAP_ENTRIES;
1098            }
1099        }
1100    
1101      if (new_size == 0)
1102        new_size = 1;
1103    
1104      if (! INDIRECT_PAGEMAP(old_size))
1105        {
1106          /* First deallocate pages in the truncated region.  */
1107          dealloc_direct (pager->map, old_size, new_size);
1108          /* Now reduce the size of the direct map itself.  We don't bother
1109             with kalloc/kfree if it's not shrinking enough that kalloc.c
1110             would actually use less.  */
1111          if (PAGEMAP_SIZE (new_size) <= PAGEMAP_SIZE (old_size) / 2)
1112            {
1113              const dp_map_t old_mapptr = pager->map;
1114              pager->map = (dp_map_t) kalloc (PAGEMAP_SIZE (new_size));
1115              memcpy (pager->map, old_mapptr, PAGEMAP_SIZE (old_size));
1116              kfree ((char *) old_mapptr, PAGEMAP_SIZE (old_size));
1117            }
1118        }
1119    
1120      pager->size = new_size;
1121    
1122    #ifdef  CHECKSUM
1123    #error write me
1124    #endif   /* CHECKSUM */
1125    }
1126    
1127    
1128  /*  /*
1129   * Given an offset within a paging object, find the   * Given an offset within a paging object, find the
1130   * corresponding block within the paging partition.   * corresponding block within the paging partition.
# Line 1709  default_has_page(ds, offset) Line 1819  default_has_page(ds, offset)
1819  {  {
1820          return ( ! no_block(pager_read_offset(ds, offset)) );          return ( ! no_block(pager_read_offset(ds, offset)) );
1821  }  }
   
1822  /*  /*
1823    
1824   */   */
# Line 1737  struct dstruct { Line 1846  struct dstruct {
1846          unsigned int    readers;        /* Reads in progress */          unsigned int    readers;        /* Reads in progress */
1847          unsigned int    writers;        /* Writes in progress */          unsigned int    writers;        /* Writes in progress */
1848    
1849            /* This is the reply port of an outstanding
1850               default_pager_object_set_size call.  */
1851            mach_port_t     lock_request;
1852    
1853          unsigned int    errors;         /* Pageout error count */          unsigned int    errors;         /* Pageout error count */
1854          struct dpager   dpager;         /* Actual pager */          struct dpager   dpager;         /* Actual pager */
1855  };  };
# Line 2069  mach_port_t default_pager_default_port; Line 2182  mach_port_t default_pager_default_port;
2182    
2183  /* We catch exceptions on ourself & startup using this port. */  /* We catch exceptions on ourself & startup using this port. */
2184  mach_port_t default_pager_exception_port;  mach_port_t default_pager_exception_port;
 /* We receive bootstrap requests on this port. */  
 mach_port_t default_pager_bootstrap_port;  
2185    
2186  mach_port_t default_pager_internal_set; /* Port set for internal objects. */  mach_port_t default_pager_internal_set; /* Port set for internal objects. */
2187  mach_port_t default_pager_external_set; /* Port set for external objects. */  mach_port_t default_pager_external_set; /* Port set for external objects. */
# Line 2537  ddprintf ("seqnos_memory_object_data_req Line 2648  ddprintf ("seqnos_memory_object_data_req
2648              goto done;              goto done;
2649          }          }
2650    
2651          rc = default_read(&ds->dpager, dpt->dpt_buffer,          if (offset >= ds->dpager.limit)
2652                            vm_page_size, offset,            rc = PAGER_ERROR;
2653                            &addr, protection_required & VM_PROT_WRITE);          else
2654              rc = default_read(&ds->dpager, dpt->dpt_buffer,
2655                                vm_page_size, offset,
2656                                &addr, protection_required & VM_PROT_WRITE);
2657    
2658          switch (rc) {          switch (rc) {
2659              case PAGER_SUCCESS:              case PAGER_SUCCESS:
# Line 2762  seqnos_memory_object_copy(old_memory_obj Line 2876  seqnos_memory_object_copy(old_memory_obj
2876          return KERN_FAILURE;          return KERN_FAILURE;
2877  }  }
2878    
2879    /* We get this when our memory_object_lock_request has completed
2880       after we truncated an object.  */
2881  kern_return_t  kern_return_t
2882  seqnos_memory_object_lock_completed(pager, seqno, pager_request,  seqnos_memory_object_lock_completed (memory_object_t pager,
2883                                      offset, length)                                       mach_port_seqno_t seqno,
2884          memory_object_t pager;                                       mach_port_t pager_request,
2885          mach_port_seqno_t seqno;                                       vm_offset_t offset,
2886          mach_port_t     pager_request;                                       vm_size_t length)
         vm_offset_t     offset;  
         vm_size_t       length;  
2887  {  {
2888  #ifdef  lint    default_pager_t ds;
         pager++; seqno++; pager_request++; offset++; length++;  
 #endif   /* lint */  
2889    
2890          panic("%slock_completed",my_name);    ds = pager_port_lookup(pager);
2891          return(KERN_FAILURE);    assert(ds != DEFAULT_PAGER_NULL);
2892    
2893      pager_port_lock(ds, seqno);
2894      pager_port_wait_for_readers(ds);
2895      pager_port_wait_for_writers(ds);
2896    
2897      /* Now that any in-core pages have been flushed, we can apply
2898         the limit to prevent any new page-ins.  */
2899      assert (page_aligned (offset));
2900      ds->dpager.limit = offset;
2901    
2902      default_pager_object_set_size_reply (ds->lock_request, KERN_SUCCESS);
2903      ds->lock_request = MACH_PORT_NULL;
2904    
2905      if (ds->dpager.size > ds->dpager.limit / vm_page_size)
2906        /* Deallocate the old backing store pages and shrink the page map.  */
2907        pager_truncate (&ds->dpager, ds->dpager.limit / vm_page_size);
2908    
2909      pager_port_unlock(ds, seqno);
2910    
2911      return KERN_SUCCESS;
2912  }  }
2913    
2914  kern_return_t  kern_return_t
# Line 2897  ddprintf ("DPAGER DEMUX OBJECT <%p>: %d\ Line 3029  ddprintf ("DPAGER DEMUX OBJECT <%p>: %d\
3029  rval =  rval =
3030   (seqnos_memory_object_server(in, out) ||   (seqnos_memory_object_server(in, out) ||
3031                  seqnos_memory_object_default_server(in, out) ||                  seqnos_memory_object_default_server(in, out) ||
3032                  default_pager_notify_server(in, out));                  default_pager_notify_server(in, out) ||
3033                    default_pager_server(in, out));
3034  ddprintf ("DPAGER DEMUX OBJECT DONE <%p>: %d\n", in, in->msgh_id);  ddprintf ("DPAGER DEMUX OBJECT DONE <%p>: %d\n", in, in->msgh_id);
3035  return rval;  return rval;
3036  }  }
# Line 2929  return rval; Line 3062  return rval;
3062                   */                   */
3063    
3064                  return exc_server(in, out);                  return exc_server(in, out);
         } else if (in->msgh_local_port == default_pager_bootstrap_port) {  
                 /*  
                  *      We receive bootstrap requests  
                  *      from the startup task.  
                  */  
   
                 if (in->msgh_id == 999999) {  
                         /* compatibility for old bootstrap interface */  
   
                         bootstrap_compat(in, out);  
                         return TRUE;  
                 }  
   
                 return bootstrap_server(in, out);  
3065          } else {          } else {
3066                  panic(my_name);                  panic(my_name);
3067                  return FALSE;                  return FALSE;
# Line 3087  default_pager_initialize(host_port) Line 3206  default_pager_initialize(host_port)
3206                  panic(my_name);                  panic(my_name);
3207    
3208          /*          /*
          *      Initialize the bootstrap port.  
          */  
         kr = mach_port_allocate(default_pager_self, MACH_PORT_RIGHT_RECEIVE,  
                                 &default_pager_bootstrap_port);  
         if (kr != KERN_SUCCESS)  
                 panic(my_name);  
   
         /*  
3209           * Arrange for wiring privileges.           * Arrange for wiring privileges.
3210           */           */
3211          wire_setup(host_port);          wire_setup(host_port);
# Line 3169  default_pager() Line 3280  default_pager()
3280          if (kr != KERN_SUCCESS)          if (kr != KERN_SUCCESS)
3281                  panic(my_name);                  panic(my_name);
3282    
         kr = mach_port_move_member(default_pager_self,  
                                    default_pager_bootstrap_port,  
                                    default_pager_default_set);  
         if (kr != KERN_SUCCESS)  
                 panic(my_name);  
   
3283          /*          /*
3284           *      Now we create the threads that will actually           *      Now we create the threads that will actually
3285           *      manage objects.           *      manage objects.
# Line 3600  default_pager_object_pages(pager, object Line 3705  default_pager_object_pages(pager, object
3705          return KERN_SUCCESS;          return KERN_SUCCESS;
3706  }  }
3707    
3708    
3709    kern_return_t
3710    default_pager_object_set_size(mach_port_t pager,
3711                                  mach_port_seqno_t seqno,
3712                                  mach_port_t reply_to,
3713                                  vm_size_t limit)
3714    {
3715      kern_return_t kr;
3716      default_pager_t ds;
3717    
3718      ds = pager_port_lookup(pager);
3719      if (ds == DEFAULT_PAGER_NULL)
3720        return KERN_INVALID_ARGUMENT;
3721    
3722      pager_port_lock(ds, seqno);
3723      pager_port_check_request(ds, reply_to);
3724      pager_port_wait_for_readers(ds);
3725      pager_port_wait_for_writers(ds);
3726    
3727      limit = round_page (limit);
3728      if (ds->dpager.size <= limit / vm_page_size)
3729        {
3730          /* The limit has not been exceeded heretofore.  Just change it.  */
3731          ds->dpager.limit = limit;
3732          kr = KERN_SUCCESS;
3733        }
3734      else if (ds->lock_request == MACH_PORT_NULL)
3735        {
3736          /* Tell the kernel to flush from core all the pages being removed.
3737             We will get the memory_object_lock_completed callback when they
3738             have been flushed.  We handle that by completing the limit update
3739             and posting the reply to the pending truncation.  */
3740          kr = memory_object_lock_request (ds->pager_request,
3741                                           limit,
3742                                           ds->dpager.size * vm_page_size - limit,
3743                                           MEMORY_OBJECT_RETURN_NONE, TRUE,
3744                                           VM_PROT_ALL, ds->pager);
3745          if (kr != KERN_SUCCESS)
3746            panic ("memory_object_lock_request: %d", kr);
3747          ds->lock_request = reply_to;
3748          kr = MIG_NO_REPLY;
3749        }
3750      else
3751        /* There is already another call in progress.  Tough titties.  */
3752        kr = KERN_FAILURE;
3753    
3754      pager_port_unlock(ds, seqno);
3755    
3756      return kr;
3757    }
3758    
3759  /*  /*
3760   * Add/remove extra paging space   * Add/remove extra paging space
3761   */   */
# Line 3747  catch_exception_raise(exception_port, th Line 3903  catch_exception_raise(exception_port, th
3903    
3904          return KERN_FAILURE;          return KERN_FAILURE;
3905  }  }
   
 /*  
  *      Handle bootstrap requests.  
  */  
   
 kern_return_t  
 do_bootstrap_privileged_ports(bootstrap, hostp, devicep)  
         mach_port_t bootstrap;  
         mach_port_t *hostp, *devicep;  
 {  
         *hostp = bootstrap_master_host_port;  
         *devicep = bootstrap_master_device_port;  
         return KERN_SUCCESS;  
 }  
   
 void  
 bootstrap_compat(in, out)  
         mach_msg_header_t *in, *out;  
 {  
         mig_reply_header_t *reply = (mig_reply_header_t *) out;  
         mach_msg_return_t mr;  
   
         struct imsg {  
                 mach_msg_header_t       hdr;  
                 mach_msg_type_t         port_desc_1;  
                 mach_port_t             port_1;  
                 mach_msg_type_t         port_desc_2;  
                 mach_port_t             port_2;  
         } imsg;  
   
         /*  
          * Send back the host and device ports.  
          */  
   
         imsg.hdr.msgh_bits = MACH_MSGH_BITS_COMPLEX |  
                 MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(in->msgh_bits), 0);  
         /* msgh_size doesn't need to be initialized */  
         imsg.hdr.msgh_remote_port = in->msgh_remote_port;  
         imsg.hdr.msgh_local_port = MACH_PORT_NULL;  
         /* msgh_seqno doesn't need to be initialized */  
         imsg.hdr.msgh_id = in->msgh_id + 100;   /* this is a reply msg */  
   
         imsg.port_desc_1.msgt_name = MACH_MSG_TYPE_COPY_SEND;  
         imsg.port_desc_1.msgt_size = (sizeof(mach_port_t) * 8);  
         imsg.port_desc_1.msgt_number = 1;  
         imsg.port_desc_1.msgt_inline = TRUE;  
         imsg.port_desc_1.msgt_longform = FALSE;  
         imsg.port_desc_1.msgt_deallocate = FALSE;  
         imsg.port_desc_1.msgt_unused = 0;  
   
         imsg.port_1 = bootstrap_master_host_port;  
   
         imsg.port_desc_2 = imsg.port_desc_1;  
   
         imsg.port_2 = bootstrap_master_device_port;  
   
         /*  
          * Send the reply message.  
          * (mach_msg_server can not do this, because the reply  
          * is not in standard format.)  
          */  
   
         mr = mach_msg(&imsg.hdr, MACH_SEND_MSG,  
                       sizeof imsg, 0, MACH_PORT_NULL,  
                       MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);  
         if (mr != MACH_MSG_SUCCESS)  
                 (void) mach_port_deallocate(default_pager_self,  
                                             imsg.hdr.msgh_remote_port);  
   
         /*  
          * Tell mach_msg_server to do nothing.  
          */  
   
         reply->RetCode = MIG_NO_REPLY;  
 }  
   
 #ifdef  mips  
 /*  
  * set_ras_address for default pager  
  * Default pager does not have emulator support  
  * so it needs a local version of set_ras_address.  
  */  
 int  
 set_ras_address(basepc, boundspc)  
         vm_offset_t basepc;  
         vm_offset_t boundspc;  
 {  
         kern_return_t status;  
   
         status = task_ras_control(mach_task_self(), basepc, boundspc,  
                                   TASK_RAS_CONTROL_INSTALL_ONE);  
         if (status != KERN_SUCCESS)  
           return -1;  
         return 0;  
 }  
 #endif  

Legend:
Removed from v.1.24  
changed lines
  Added in v.1.25

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26