Diff for /src/sys/vm/vm_pageout.c between versions 1.10 and 1.11

version 1.10, 2004/03/23 22:54:32 version 1.11, 2004/05/13 17:40:19
Line 209  static void vm_pageout_page_stats(void); Line 209  static void vm_pageout_page_stats(void);
 /*  /*
  * vm_pageout_clean:   * vm_pageout_clean:
  *   *
 * Clean the page and remove it from the laundry. * Clean the page and remove it from the laundry.  The page must not be
  * busy on-call.
  *    * 
  * We set the busy bit to cause potential page faults on this page to   * We set the busy bit to cause potential page faults on this page to
  * block.  Note the careful timing, however, the busy bit isn't set till   * block.  Note the careful timing, however, the busy bit isn't set till
Line 443  vm_pageout_flush(vm_page_t *mc, int coun Line 444  vm_pageout_flush(vm_page_t *mc, int coun
  */   */
 static void  static void
 vm_pageout_object_deactivate_pages(vm_map_t map, vm_object_t object,  vm_pageout_object_deactivate_pages(vm_map_t map, vm_object_t object,
    vm_pindex_t desired, int map_remove_only)        vm_pindex_t desired, int map_remove_only)
 {  {
         vm_page_t p, next;          vm_page_t p, next;
         int rcount;          int rcount;
Line 462  vm_pageout_object_deactivate_pages(vm_ma Line 463  vm_pageout_object_deactivate_pages(vm_ma
                 remove_mode = map_remove_only;                  remove_mode = map_remove_only;
                 if (object->shadow_count > 1)                  if (object->shadow_count > 1)
                         remove_mode = 1;                          remove_mode = 1;
        /*
         * scan the objects entire memory queue                /*
         */                 * scan the objects entire memory queue.  spl protection is
                  * required to avoid an interrupt unbusy/free race against
                  * our busy check.
                  */
                 s = splvm();
                 rcount = object->resident_page_count;                  rcount = object->resident_page_count;
                 p = TAILQ_FIRST(&object->memq);                  p = TAILQ_FIRST(&object->memq);
   
                 while (p && (rcount-- > 0)) {                  while (p && (rcount-- > 0)) {
                         int actcount;                          int actcount;
                        if (pmap_resident_count(vm_map_pmap(map)) <= desired)                        if (pmap_resident_count(vm_map_pmap(map)) <= desired) {
                                 splx(s);
                                 return;                                  return;
                           }
                         next = TAILQ_NEXT(p, listq);                          next = TAILQ_NEXT(p, listq);
                         mycpu->gd_cnt.v_pdpages++;                          mycpu->gd_cnt.v_pdpages++;
                         if (p->wire_count != 0 ||                          if (p->wire_count != 0 ||
Line 501  vm_pageout_object_deactivate_pages(vm_ma Line 509  vm_pageout_object_deactivate_pages(vm_ma
                                                 vm_page_protect(p, VM_PROT_NONE);                                                  vm_page_protect(p, VM_PROT_NONE);
                                                 vm_page_deactivate(p);                                                  vm_page_deactivate(p);
                                         } else {                                          } else {
                                                 s = splvm();  
                                                 TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, p, pageq);                                                  TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, p, pageq);
                                                 TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, p, pageq);                                                  TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, p, pageq);
                                                 splx(s);  
                                         }                                          }
                                 } else {                                  } else {
                                         vm_page_activate(p);                                          vm_page_activate(p);
                                         vm_page_flag_clear(p, PG_REFERENCED);                                          vm_page_flag_clear(p, PG_REFERENCED);
                                         if (p->act_count < (ACT_MAX - ACT_ADVANCE))                                          if (p->act_count < (ACT_MAX - ACT_ADVANCE))
                                                 p->act_count += ACT_ADVANCE;                                                  p->act_count += ACT_ADVANCE;
                                         s = splvm();  
                                         TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, p, pageq);                                          TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, p, pageq);
                                         TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, p, pageq);                                          TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, p, pageq);
                                         splx(s);  
                                 }                                  }
                         } else if (p->queue == PQ_INACTIVE) {                          } else if (p->queue == PQ_INACTIVE) {
                                 vm_page_protect(p, VM_PROT_NONE);                                  vm_page_protect(p, VM_PROT_NONE);
                         }                          }
                         p = next;                          p = next;
                 }                  }
                   splx(s);
                 object = object->backing_object;                  object = object->backing_object;
         }          }
         return;  
 }  }
   
 /*  /*
Line 675  vm_pageout_scan(int pass) Line 679  vm_pageout_scan(int pass)
         if (pass)          if (pass)
                 maxlaunder = 10000;                  maxlaunder = 10000;
   
           /*
            * We will generally be at splvm() throughout the scan, but we
            * can release it temporarily when we are sitting on a non-busy
            * page without fear.  The spl protection is required because an
            * an interrupt can come along and unbusy/free a busy page prior
            * to our busy check, leaving us on the wrong queue or checking
            * the wrong page.
            */
           s = splvm();
 rescan0:  rescan0:
         addl_page_shortage = addl_page_shortage_init;          addl_page_shortage = addl_page_shortage_init;
         maxscan = vmstats.v_inactive_count;          maxscan = vmstats.v_inactive_count;
         for (m = TAILQ_FIRST(&vm_page_queues[PQ_INACTIVE].pl);          for (m = TAILQ_FIRST(&vm_page_queues[PQ_INACTIVE].pl);
              m != NULL && maxscan-- > 0 && page_shortage > 0;               m != NULL && maxscan-- > 0 && page_shortage > 0;
             m = next) {             m = next
         ) {
                 mycpu->gd_cnt.v_pdpages++;                  mycpu->gd_cnt.v_pdpages++;
   
                if (m->queue != PQ_INACTIVE) {                /*
                        goto rescan0;                 * Give interrupts a chance
                }                 */
                 splx(s);
                 s = splvm();
   
                   /*
                    * It's easier for some of the conditions below to just loop
                    * and catch queue changes here rather then check everywhere
                    * else.
                    */
                   if (m->queue != PQ_INACTIVE)
                           goto rescan0;
                 next = TAILQ_NEXT(m, pageq);                  next = TAILQ_NEXT(m, pageq);
   
                 /*                  /*
Line 700  rescan0: Line 722  rescan0:
                  * A held page may be undergoing I/O, so skip it.                   * A held page may be undergoing I/O, so skip it.
                  */                   */
                 if (m->hold_count) {                  if (m->hold_count) {
                         s = splvm();  
                         TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);                          TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);
                         TAILQ_INSERT_TAIL(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);                          TAILQ_INSERT_TAIL(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);
                         splx(s);  
                         addl_page_shortage++;                          addl_page_shortage++;
                         continue;                          continue;
                 }                  }
   
                 /*                  /*
                  * Dont mess with busy pages, keep in the front of the                   * Dont mess with busy pages, keep in the front of the
                  * queue, most likely are being paged out.                   * queue, most likely are being paged out.
Line 716  rescan0: Line 737  rescan0:
                         continue;                          continue;
                 }                  }
   
                 /*  
                  * If the object is not being used, we ignore previous   
                  * references.  
                  */  
                 if (m->object->ref_count == 0) {                  if (m->object->ref_count == 0) {
                           /*
                            * If the object is not being used, we ignore previous 
                            * references.
                            */
                         vm_page_flag_clear(m, PG_REFERENCED);                          vm_page_flag_clear(m, PG_REFERENCED);
                         pmap_clear_reference(m);                          pmap_clear_reference(m);
   
                 /*  
                  * Otherwise, if the page has been referenced while in the   
                  * inactive queue, we bump the "activation count" upwards,   
                  * making it less likely that the page will be added back to   
                  * the inactive queue prematurely again.  Here we check the   
                  * page tables (or emulated bits, if any), given the upper   
                  * level VM system not knowing anything about existing   
                  * references.  
                  */  
                 } else if (((m->flags & PG_REFERENCED) == 0) &&                  } else if (((m->flags & PG_REFERENCED) == 0) &&
                        (actcount = pmap_ts_referenced(m))) {                            (actcount = pmap_ts_referenced(m))) {
                         /*
                          * Otherwise, if the page has been referenced while 
                          * in the inactive queue, we bump the "activation
                          * count" upwards, making it less likely that the
                          * page will be added back to the inactive queue
                          * prematurely again.  Here we check the page tables
                          * (or emulated bits, if any), given the upper level
                          * VM system not knowing anything about existing 
                          * references.
                          */
                         vm_page_activate(m);                          vm_page_activate(m);
                         m->act_count += (actcount + ACT_ADVANCE);                          m->act_count += (actcount + ACT_ADVANCE);
                         continue;                          continue;
Line 806  rescan0: Line 828  rescan0:
                          * before being freed.  This significantly extends                           * before being freed.  This significantly extends
                          * the thrash point for a heavily loaded machine.                           * the thrash point for a heavily loaded machine.
                          */                           */
                         s = splvm();  
                         vm_page_flag_set(m, PG_WINATCFLS);                          vm_page_flag_set(m, PG_WINATCFLS);
                         TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);                          TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);
                         TAILQ_INSERT_TAIL(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);                          TAILQ_INSERT_TAIL(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);
                         splx(s);  
                 } else if (maxlaunder > 0) {                  } else if (maxlaunder > 0) {
                         /*                          /*
                          * We always want to try to flush some dirty pages if                           * We always want to try to flush some dirty pages if
Line 838  rescan0: Line 858  rescan0:
                          * Those objects are in a "rundown" state.                           * Those objects are in a "rundown" state.
                          */                           */
                         if (!swap_pageouts_ok || (object->flags & OBJ_DEAD)) {                          if (!swap_pageouts_ok || (object->flags & OBJ_DEAD)) {
                                 s = splvm();  
                                 TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);                                  TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);
                                 TAILQ_INSERT_TAIL(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);                                  TAILQ_INSERT_TAIL(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);
                                 splx(s);  
                                 continue;                                  continue;
                         }                          }
   
Line 907  rescan0: Line 925  rescan0:
                                  * be undergoing I/O, so skip it                                   * be undergoing I/O, so skip it
                                  */                                   */
                                 if (m->hold_count) {                                  if (m->hold_count) {
                                         s = splvm();  
                                         TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);                                          TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);
                                         TAILQ_INSERT_TAIL(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);                                          TAILQ_INSERT_TAIL(&vm_page_queues[PQ_INACTIVE].pl, m, pageq);
                                         splx(s);  
                                         if (object->flags & OBJ_MIGHTBEDIRTY)                                          if (object->flags & OBJ_MIGHTBEDIRTY)
                                                 vnodes_skipped++;                                                  vnodes_skipped++;
                                         vput(vp);                                          vput(vp);
Line 932  rescan0: Line 948  rescan0:
                          * the (future) cleaned page.  Otherwise we could wind                           * the (future) cleaned page.  Otherwise we could wind
                          * up laundering or cleaning too many pages.                           * up laundering or cleaning too many pages.
                          */                           */
                         s = splvm();  
                         TAILQ_INSERT_AFTER(&vm_page_queues[PQ_INACTIVE].pl, m, &marker, pageq);                          TAILQ_INSERT_AFTER(&vm_page_queues[PQ_INACTIVE].pl, m, &marker, pageq);
                         splx(s);  
                         if (vm_pageout_clean(m) != 0) {                          if (vm_pageout_clean(m) != 0) {
                                 --page_shortage;                                  --page_shortage;
                                 --maxlaunder;                                  --maxlaunder;
                         }                           } 
                         s = splvm();  
                         next = TAILQ_NEXT(&marker, pageq);                          next = TAILQ_NEXT(&marker, pageq);
                         TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, &marker, pageq);                          TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, &marker, pageq);
                         splx(s);  
                         if (vp != NULL)                          if (vp != NULL)
                                 vput(vp);                                  vput(vp);
                 }                  }
Line 960  rescan0: Line 972  rescan0:
          * Scan the active queue for things we can deactivate. We nominally           * Scan the active queue for things we can deactivate. We nominally
          * track the per-page activity counter and use it to locate            * track the per-page activity counter and use it to locate 
          * deactivation candidates.           * deactivation candidates.
            *
            * NOTE: we are still at splvm().
          */           */
   
         pcount = vmstats.v_active_count;          pcount = vmstats.v_active_count;
         m = TAILQ_FIRST(&vm_page_queues[PQ_ACTIVE].pl);          m = TAILQ_FIRST(&vm_page_queues[PQ_ACTIVE].pl);
   
         while ((m != NULL) && (pcount-- > 0) && (page_shortage > 0)) {          while ((m != NULL) && (pcount-- > 0) && (page_shortage > 0)) {
                   /*
                    * Give interrupts a chance.
                    */
                   splx(s);
                   s = splvm();
   
                 /*                  /*
                 * This is a consistency check, and should likely be a panic                 * If the page was ripped out from under us, just stop.
                 * or warning. 
                  */                   */
                if (m->queue != PQ_ACTIVE) {                if (m->queue != PQ_ACTIVE)
                         break;                          break;
                 }  
   
                 next = TAILQ_NEXT(m, pageq);                  next = TAILQ_NEXT(m, pageq);
   
                 /*                  /*
                  * Don't deactivate pages that are busy.                   * Don't deactivate pages that are busy.
                  */                   */
                 if ((m->busy != 0) ||                  if ((m->busy != 0) ||
                     (m->flags & PG_BUSY) ||                      (m->flags & PG_BUSY) ||
                     (m->hold_count != 0)) {                      (m->hold_count != 0)) {
                         s = splvm();  
                         TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, m, pageq);                          TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, m, pageq);
                         TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, m, pageq);                          TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, m, pageq);
                         splx(s);  
                         m = next;                          m = next;
                         continue;                          continue;
                 }                  }
Line 1022  rescan0: Line 1036  rescan0:
                  * page activation count stats.                   * page activation count stats.
                  */                   */
                 if (actcount && (m->object->ref_count != 0)) {                  if (actcount && (m->object->ref_count != 0)) {
                         s = splvm();  
                         TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, m, pageq);                          TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, m, pageq);
                         TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, m, pageq);                          TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, m, pageq);
                         splx(s);  
                 } else {                  } else {
                         m->act_count -= min(m->act_count, ACT_DECLINE);                          m->act_count -= min(m->act_count, ACT_DECLINE);
                         if (vm_pageout_algorithm ||                          if (vm_pageout_algorithm ||
Line 1042  rescan0: Line 1054  rescan0:
                                         vm_page_deactivate(m);                                          vm_page_deactivate(m);
                                 }                                  }
                         } else {                          } else {
                                 s = splvm();  
                                 TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, m, pageq);                                  TAILQ_REMOVE(&vm_page_queues[PQ_ACTIVE].pl, m, pageq);
                                 TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, m, pageq);                                  TAILQ_INSERT_TAIL(&vm_page_queues[PQ_ACTIVE].pl, m, pageq);
                                 splx(s);  
                         }                          }
                 }                  }
                 m = next;                  m = next;
         }          }
   
         s = splvm();  
   
         /*          /*
          * We try to maintain some *really* free pages, this allows interrupt           * We try to maintain some *really* free pages, this allows interrupt
          * code to be guaranteed space.  Since both cache and free queues            * code to be guaranteed space.  Since both cache and free queues 
          * are considered basically 'free', moving pages from cache to free           * are considered basically 'free', moving pages from cache to free
          * does not effect other calculations.           * does not effect other calculations.
            *
            * NOTE: we are still at splvm().
          */           */
   
         while (vmstats.v_free_count < vmstats.v_free_reserved) {          while (vmstats.v_free_count < vmstats.v_free_reserved) {
Line 1079  rescan0: Line 1089  rescan0:
                 vm_pageout_page_free(m);                  vm_pageout_page_free(m);
                 mycpu->gd_cnt.v_dfree++;                  mycpu->gd_cnt.v_dfree++;
         }          }
   
         splx(s);          splx(s);
   
 #if !defined(NO_SWAPPING)  #if !defined(NO_SWAPPING)

Removed from v.1.10  
changed lines
  Added in v.1.11