Annotation of Gnu-Mach/vm/vm_pageout.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University.
                      4:  * Copyright (c) 1993,1994 The University of Utah and
                      5:  * the Computer Systems Laboratory (CSL).
                      6:  * All rights reserved.
                      7:  *
                      8:  * Permission to use, copy, modify and distribute this software and its
                      9:  * documentation is hereby granted, provided that both the copyright
                     10:  * notice and this permission notice appear in all copies of the
                     11:  * software, derivative works or modified versions, and any portions
                     12:  * thereof, and that both notices appear in supporting documentation.
                     13:  *
                     14:  * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
                     15:  * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
                     16:  * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
                     17:  * THIS SOFTWARE.
                     18:  *
                     19:  * Carnegie Mellon requests users of this software to return to
                     20:  *
                     21:  *  Software Distribution Coordinator  or  [email protected]
                     22:  *  School of Computer Science
                     23:  *  Carnegie Mellon University
                     24:  *  Pittsburgh PA 15213-3890
                     25:  *
                     26:  * any improvements or extensions that they make and grant Carnegie Mellon
                     27:  * the rights to redistribute these changes.
                     28:  */
                     29: /*
                     30:  *     File:   vm/vm_pageout.c
                     31:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     32:  *     Date:   1985
                     33:  *
                     34:  *     The proverbial page-out daemon.
                     35:  */
                     36: 
1.1.1.3 ! root       37: #include <device/net_io.h>
1.1       root       38: #include <mach/mach_types.h>
                     39: #include <mach/memory_object.h>
1.1.1.3 ! root       40: #include <vm/memory_object_default.user.h>
        !            41: #include <vm/memory_object_user.user.h>
1.1       root       42: #include <mach/vm_param.h>
                     43: #include <mach/vm_statistics.h>
                     44: #include <kern/counters.h>
1.1.1.3 ! root       45: #include <kern/debug.h>
        !            46: #include <kern/slab.h>
        !            47: #include <kern/task.h>
1.1       root       48: #include <kern/thread.h>
                     49: #include <vm/pmap.h>
                     50: #include <vm/vm_map.h>
                     51: #include <vm/vm_object.h>
                     52: #include <vm/vm_page.h>
                     53: #include <vm/vm_pageout.h>
1.1.1.3 ! root       54: #include <machine/locore.h>
1.1       root       55: #include <machine/vm_tuning.h>
                     56: 
                     57: 
                     58: 
                     59: #ifndef        VM_PAGEOUT_BURST_MAX
                     60: #define        VM_PAGEOUT_BURST_MAX    10              /* number of pages */
1.1.1.2   root       61: #endif /* VM_PAGEOUT_BURST_MAX */
1.1       root       62: 
                     63: #ifndef        VM_PAGEOUT_BURST_MIN
                     64: #define        VM_PAGEOUT_BURST_MIN    5               /* number of pages */
1.1.1.2   root       65: #endif /* VM_PAGEOUT_BURST_MIN */
1.1       root       66: 
                     67: #ifndef        VM_PAGEOUT_BURST_WAIT
1.1.1.2   root       68: #define        VM_PAGEOUT_BURST_WAIT   10              /* milliseconds per page */
                     69: #endif /* VM_PAGEOUT_BURST_WAIT */
1.1       root       70: 
                     71: #ifndef        VM_PAGEOUT_EMPTY_WAIT
1.1.1.2   root       72: #define VM_PAGEOUT_EMPTY_WAIT  75              /* milliseconds */
                     73: #endif /* VM_PAGEOUT_EMPTY_WAIT */
1.1       root       74: 
                     75: #ifndef        VM_PAGEOUT_PAUSE_MAX
                     76: #define        VM_PAGEOUT_PAUSE_MAX    10              /* number of pauses */
1.1.1.2   root       77: #endif /* VM_PAGEOUT_PAUSE_MAX */
1.1       root       78: 
                     79: /*
                     80:  *     To obtain a reasonable LRU approximation, the inactive queue
                     81:  *     needs to be large enough to give pages on it a chance to be
                     82:  *     referenced a second time.  This macro defines the fraction
                     83:  *     of active+inactive pages that should be inactive.
                     84:  *     The pageout daemon uses it to update vm_page_inactive_target.
                     85:  *
                     86:  *     If vm_page_free_count falls below vm_page_free_target and
                     87:  *     vm_page_inactive_count is below vm_page_inactive_target,
                     88:  *     then the pageout daemon starts running.
                     89:  */
                     90: 
                     91: #ifndef        VM_PAGE_INACTIVE_TARGET
                     92: #define        VM_PAGE_INACTIVE_TARGET(avail)  ((avail) * 2 / 3)
1.1.1.2   root       93: #endif /* VM_PAGE_INACTIVE_TARGET */
1.1       root       94: 
                     95: /*
                     96:  *     Once the pageout daemon starts running, it keeps going
                     97:  *     until vm_page_free_count meets or exceeds vm_page_free_target.
                     98:  */
                     99: 
                    100: #ifndef        VM_PAGE_FREE_TARGET
                    101: #define        VM_PAGE_FREE_TARGET(free)       (15 + (free) / 80)
1.1.1.2   root      102: #endif /* VM_PAGE_FREE_TARGET */
1.1       root      103: 
                    104: /*
                    105:  *     The pageout daemon always starts running once vm_page_free_count
                    106:  *     falls below vm_page_free_min.
                    107:  */
                    108: 
                    109: #ifndef        VM_PAGE_FREE_MIN
                    110: #define        VM_PAGE_FREE_MIN(free)  (10 + (free) / 100)
1.1.1.2   root      111: #endif /* VM_PAGE_FREE_MIN */
                    112: 
                    113: /*      When vm_page_external_count exceeds vm_page_external_limit, 
                    114:  *     allocations of externally paged pages stops.
                    115:  */
                    116: 
                    117: #ifndef VM_PAGE_EXTERNAL_LIMIT
                    118: #define VM_PAGE_EXTERNAL_LIMIT(free)           ((free) / 2)
                    119: #endif  /* VM_PAGE_EXTERNAL_LIMIT */
                    120: 
                    121: /*     Attempt to keep the number of externally paged pages less
                    122:  *     than vm_pages_external_target.
                    123:  */
                    124: #ifndef VM_PAGE_EXTERNAL_TARGET
                    125: #define VM_PAGE_EXTERNAL_TARGET(free)          ((free) / 4)
                    126: #endif  /* VM_PAGE_EXTERNAL_TARGET */
1.1       root      127: 
                    128: /*
                    129:  *     When vm_page_free_count falls below vm_page_free_reserved,
                    130:  *     only vm-privileged threads can allocate pages.  vm-privilege
                    131:  *     allows the pageout daemon and default pager (and any other
                    132:  *     associated threads needed for default pageout) to continue
1.1.1.2   root      133:  *     operation by dipping into the reserved pool of pages.  */
1.1       root      134: 
                    135: #ifndef        VM_PAGE_FREE_RESERVED
1.1.1.2   root      136: #define        VM_PAGE_FREE_RESERVED                   50
                    137: #endif /* VM_PAGE_FREE_RESERVED */
1.1       root      138: 
                    139: /*
                    140:  *     When vm_page_free_count falls below vm_pageout_reserved_internal,
                    141:  *     the pageout daemon no longer trusts external pagers to clean pages.
                    142:  *     External pagers are probably all wedged waiting for a free page.
                    143:  *     It forcibly double-pages dirty pages belonging to external objects,
                    144:  *     getting the pages to the default pager to clean.
                    145:  */
                    146: 
                    147: #ifndef        VM_PAGEOUT_RESERVED_INTERNAL
1.1.1.2   root      148: #define        VM_PAGEOUT_RESERVED_INTERNAL(reserve)   ((reserve) - 25)
                    149: #endif /* VM_PAGEOUT_RESERVED_INTERNAL */
1.1       root      150: 
                    151: /*
                    152:  *     When vm_page_free_count falls below vm_pageout_reserved_really,
                    153:  *     the pageout daemon stops work entirely to let the default pager
                    154:  *     catch up (assuming the default pager has pages to clean).
                    155:  *     Beyond this point, it is too dangerous to consume memory
                    156:  *     even for memory_object_data_write messages to the default pager.
                    157:  */
                    158: 
                    159: #ifndef        VM_PAGEOUT_RESERVED_REALLY
1.1.1.2   root      160: #define        VM_PAGEOUT_RESERVED_REALLY(reserve)     ((reserve) - 40)
                    161: #endif /* VM_PAGEOUT_RESERVED_REALLY */
1.1       root      162: 
                    163: extern void vm_pageout_continue();
                    164: extern void vm_pageout_scan_continue();
                    165: 
                    166: unsigned int vm_pageout_reserved_internal = 0;
                    167: unsigned int vm_pageout_reserved_really = 0;
                    168: 
1.1.1.2   root      169: unsigned int vm_page_external_target = 0;
                    170: 
1.1       root      171: unsigned int vm_pageout_burst_max = 0;
                    172: unsigned int vm_pageout_burst_min = 0;
                    173: unsigned int vm_pageout_burst_wait = 0;                /* milliseconds per page */
                    174: unsigned int vm_pageout_empty_wait = 0;                /* milliseconds */
                    175: unsigned int vm_pageout_pause_count = 0;
                    176: unsigned int vm_pageout_pause_max = 0;
                    177: 
                    178: /*
                    179:  *     These variables record the pageout daemon's actions:
                    180:  *     how many pages it looks at and what happens to those pages.
                    181:  *     No locking needed because only one thread modifies the variables.
                    182:  */
                    183: 
                    184: unsigned int vm_pageout_active = 0;            /* debugging */
                    185: unsigned int vm_pageout_inactive = 0;          /* debugging */
                    186: unsigned int vm_pageout_inactive_nolock = 0;   /* debugging */
                    187: unsigned int vm_pageout_inactive_busy = 0;     /* debugging */
                    188: unsigned int vm_pageout_inactive_absent = 0;   /* debugging */
                    189: unsigned int vm_pageout_inactive_used = 0;     /* debugging */
                    190: unsigned int vm_pageout_inactive_clean = 0;    /* debugging */
                    191: unsigned int vm_pageout_inactive_dirty = 0;    /* debugging */
                    192: unsigned int vm_pageout_inactive_double = 0;   /* debugging */
1.1.1.2   root      193: unsigned int vm_pageout_inactive_cleaned_external = 0;
1.1       root      194: 
                    195: /*
                    196:  *     Routine:        vm_pageout_setup
                    197:  *     Purpose:
                    198:  *             Set up a page for pageout.
                    199:  *
                    200:  *             Move or copy the page to a new object, as part
                    201:  *             of which it will be sent to its memory manager
                    202:  *             in a memory_object_data_write or memory_object_initialize
                    203:  *             message.
                    204:  *
                    205:  *             The "paging_offset" argument specifies the offset
                    206:  *             of the page within its external memory object.
                    207:  *
                    208:  *             The "new_object" and "new_offset" arguments
                    209:  *             indicate where the page should be moved.
                    210:  *
                    211:  *             The "flush" argument specifies whether the page
                    212:  *             should be flushed from its object.  If not, a
                    213:  *             copy of the page is moved to the new object.
                    214:  *
                    215:  *     In/Out conditions:
                    216:  *             The page in question must not be on any pageout queues,
                    217:  *             and must be busy.  The object to which it belongs
                    218:  *             must be unlocked, and the caller must hold a paging
                    219:  *             reference to it.  The new_object must not be locked.
                    220:  *
                    221:  *             If the page is flushed from its original object,
                    222:  *             this routine returns a pointer to a place-holder page,
                    223:  *             inserted at the same offset, to block out-of-order
                    224:  *             requests for the page.  The place-holder page must
                    225:  *             be freed after the data_write or initialize message
                    226:  *             has been sent.  If the page is copied,
                    227:  *             the holding page is VM_PAGE_NULL.
                    228:  *
                    229:  *             The original page is put on a paging queue and marked
                    230:  *             not busy on exit.
                    231:  */
                    232: vm_page_t
                    233: vm_pageout_setup(m, paging_offset, new_object, new_offset, flush)
                    234:        register vm_page_t      m;
                    235:        vm_offset_t             paging_offset;
                    236:        register vm_object_t    new_object;
                    237:        vm_offset_t             new_offset;
                    238:        boolean_t               flush;
                    239: {
                    240:        register vm_object_t    old_object = m->object;
                    241:        register vm_page_t      holding_page = 0; /*'=0'to quiet gcc warnings*/
                    242:        register vm_page_t      new_m;
                    243: 
                    244:        assert(m->busy && !m->absent && !m->fictitious);
                    245: 
                    246:        /*
                    247:         *      If we are not flushing the page, allocate a
                    248:         *      page in the object.  If we cannot get the
                    249:         *      page, flush instead.
                    250:         */
                    251:        if (!flush) {
                    252:                vm_object_lock(new_object);
                    253:                new_m = vm_page_alloc(new_object, new_offset);
                    254:                if (new_m == VM_PAGE_NULL)
                    255:                        flush = TRUE;
                    256:                vm_object_unlock(new_object);
                    257:        }
                    258: 
                    259:        if (flush) {
                    260:                /*
                    261:                 *      Create a place-holder page where the old one was,
                    262:                 *      to prevent anyone from attempting to page in this
                    263:                 *      page while we`re unlocked.
                    264:                 */
                    265:                while ((holding_page = vm_page_grab_fictitious())
                    266:                                                        == VM_PAGE_NULL)
                    267:                        vm_page_more_fictitious();
                    268: 
                    269:                vm_object_lock(old_object);
                    270:                vm_page_lock_queues();
                    271:                vm_page_remove(m);
                    272:                vm_page_unlock_queues();
                    273:                PAGE_WAKEUP_DONE(m);
                    274: 
                    275:                vm_page_lock_queues();
                    276:                vm_page_insert(holding_page, old_object, m->offset);
                    277:                vm_page_unlock_queues();
                    278: 
                    279:                /*
                    280:                 *      Record that this page has been written out
                    281:                 */
                    282: #if    MACH_PAGEMAP
                    283:                vm_external_state_set(old_object->existence_info,
                    284:                                        paging_offset,
                    285:                                        VM_EXTERNAL_STATE_EXISTS);
1.1.1.2   root      286: #endif /* MACH_PAGEMAP */
1.1       root      287: 
                    288:                vm_object_unlock(old_object);
                    289: 
                    290:                vm_object_lock(new_object);
                    291: 
                    292:                /*
                    293:                 *      Move this page into the new object
                    294:                 */
                    295: 
                    296:                vm_page_lock_queues();
                    297:                vm_page_insert(m, new_object, new_offset);
                    298:                vm_page_unlock_queues();
                    299: 
                    300:                m->dirty = TRUE;
                    301:                m->precious = FALSE;
                    302:                m->page_lock = VM_PROT_NONE;
                    303:                m->unlock_request = VM_PROT_NONE;
                    304:        }
                    305:        else {
                    306:                /*
                    307:                 *      Copy the data into the new page,
                    308:                 *      and mark the new page as clean.
                    309:                 */
                    310:                vm_page_copy(m, new_m);
                    311: 
                    312:                vm_object_lock(old_object);
                    313:                m->dirty = FALSE;
                    314:                pmap_clear_modify(m->phys_addr);
                    315: 
                    316:                /*
                    317:                 *      Deactivate old page.
                    318:                 */
                    319:                vm_page_lock_queues();
                    320:                vm_page_deactivate(m);
                    321:                vm_page_unlock_queues();
                    322: 
                    323:                PAGE_WAKEUP_DONE(m);
                    324: 
                    325:                /*
                    326:                 *      Record that this page has been written out
                    327:                 */
                    328: 
                    329: #if    MACH_PAGEMAP
                    330:                vm_external_state_set(old_object->existence_info,
                    331:                                        paging_offset,
                    332:                                        VM_EXTERNAL_STATE_EXISTS);
1.1.1.2   root      333: #endif /* MACH_PAGEMAP */
1.1       root      334: 
                    335:                vm_object_unlock(old_object);
                    336: 
                    337:                vm_object_lock(new_object);
                    338: 
                    339:                /*
                    340:                 *      Use the new page below.
                    341:                 */
                    342:                m = new_m;
                    343:                m->dirty = TRUE;
                    344:                assert(!m->precious);
                    345:                PAGE_WAKEUP_DONE(m);
                    346:        }
                    347: 
                    348:        /*
                    349:         *      Make the old page eligible for replacement again; if a
                    350:         *      user-supplied memory manager fails to release the page,
                    351:         *      it will be paged out again to the default memory manager.
                    352:         *
                    353:         *      Note that pages written to the default memory manager
                    354:         *      must be wired down -- in return, it guarantees to free
                    355:         *      this page, rather than reusing it.
                    356:         */
                    357: 
                    358:        vm_page_lock_queues();
                    359:        vm_stat.pageouts++;
                    360:        if (m->laundry) {
                    361:                /*
                    362:                 *      vm_pageout_scan is telling us to put this page
                    363:                 *      at the front of the inactive queue, so it will
                    364:                 *      be immediately paged out to the default pager.
                    365:                 */
                    366: 
                    367:                assert(!old_object->internal);
                    368:                m->laundry = FALSE;
                    369: 
                    370:                queue_enter_first(&vm_page_queue_inactive, m,
                    371:                                  vm_page_t, pageq);
                    372:                m->inactive = TRUE;
                    373:                vm_page_inactive_count++;
                    374:        } else if (old_object->internal) {
                    375:                m->laundry = TRUE;
                    376:                vm_page_laundry_count++;
                    377: 
                    378:                vm_page_wire(m);
                    379:        } else
                    380:                vm_page_activate(m);
                    381:        vm_page_unlock_queues();
                    382: 
                    383:        /*
                    384:         *      Since IPC operations may block, we drop locks now.
                    385:         *      [The placeholder page is busy, and we still have
                    386:         *      paging_in_progress incremented.]
                    387:         */
                    388: 
                    389:        vm_object_unlock(new_object);
                    390: 
                    391:        /*
                    392:         *      Return the placeholder page to simplify cleanup.
                    393:         */
                    394:        return (flush ? holding_page : VM_PAGE_NULL);
                    395: }
                    396: 
                    397: /*
                    398:  *     Routine:        vm_pageout_page
                    399:  *     Purpose:
                    400:  *             Causes the specified page to be written back to
                    401:  *             the appropriate memory object.
                    402:  *
                    403:  *             The "initial" argument specifies whether this
                    404:  *             data is an initialization only, and should use
                    405:  *             memory_object_data_initialize instead of
                    406:  *             memory_object_data_write.
                    407:  *
                    408:  *             The "flush" argument specifies whether the page
                    409:  *             should be flushed from the object.  If not, a
                    410:  *             copy of the data is sent to the memory object.
                    411:  *
                    412:  *     In/out conditions:
                    413:  *             The page in question must not be on any pageout queues.
                    414:  *             The object to which it belongs must be locked.
                    415:  *     Implementation:
                    416:  *             Move this page to a completely new object, if flushing;
                    417:  *             copy to a new page in a new object, if not.
                    418:  */
                    419: void
                    420: vm_pageout_page(m, initial, flush)
                    421:        register vm_page_t      m;
                    422:        boolean_t               initial;
                    423:        boolean_t               flush;
                    424: {
                    425:        vm_map_copy_t           copy;
                    426:        register vm_object_t    old_object;
                    427:        register vm_object_t    new_object;
                    428:        register vm_page_t      holding_page;
                    429:        vm_offset_t             paging_offset;
                    430:        kern_return_t           rc;
                    431:        boolean_t               precious_clean;
                    432: 
                    433:        assert(m->busy);
                    434: 
                    435:        /*
                    436:         *      Cleaning but not flushing a clean precious page is a
                    437:         *      no-op.  Remember whether page is clean and precious now
                    438:         *      because vm_pageout_setup will mark it dirty and not precious.
                    439:         *
                    440:         * XXX Check if precious_clean && !flush can really happen.
                    441:         */
                    442:        precious_clean = (!m->dirty) && m->precious;
                    443:        if (precious_clean && !flush) {
                    444:                PAGE_WAKEUP_DONE(m);
                    445:                return;
                    446:        }
                    447: 
                    448:        /*
                    449:         *      Verify that we really want to clean this page.
                    450:         */
                    451:        if (m->absent || m->error || (!m->dirty && !m->precious)) {
                    452:                VM_PAGE_FREE(m);
                    453:                return;
                    454:        }
                    455: 
                    456:        /*
                    457:         *      Create a paging reference to let us play with the object.
                    458:         */
                    459:        old_object = m->object;
                    460:        paging_offset = m->offset + old_object->paging_offset;
                    461:        vm_object_paging_begin(old_object);
                    462:        vm_object_unlock(old_object);
                    463: 
                    464:        /*
                    465:         *      Allocate a new object into which we can put the page.
                    466:         */
                    467:        new_object = vm_object_allocate(PAGE_SIZE);
                    468: 
                    469:        /*
                    470:         *      Move the page into the new object.
                    471:         */
                    472:        holding_page = vm_pageout_setup(m,
                    473:                                paging_offset,
                    474:                                new_object,
                    475:                                0,              /* new offset */
                    476:                                flush);         /* flush */
                    477: 
                    478:        rc = vm_map_copyin_object(new_object, 0, PAGE_SIZE, &copy);
                    479:        assert(rc == KERN_SUCCESS);
                    480: 
                    481:        if (initial || old_object->use_old_pageout) {
                    482:                rc = (*(initial ? memory_object_data_initialize
                    483:                             : memory_object_data_write))
                    484:                        (old_object->pager,
                    485:                         old_object->pager_request,
                    486:                         paging_offset, (pointer_t) copy, PAGE_SIZE);
                    487:        }
                    488:        else {
                    489:                rc = memory_object_data_return(
                    490:                         old_object->pager,
                    491:                         old_object->pager_request,
                    492:                         paging_offset, (pointer_t) copy, PAGE_SIZE,
                    493:                         !precious_clean, !flush);
                    494:        }
                    495: 
                    496:        if (rc != KERN_SUCCESS)
                    497:                vm_map_copy_discard(copy);
                    498: 
                    499:        /*
                    500:         *      Clean up.
                    501:         */
                    502:        vm_object_lock(old_object);
                    503:        if (holding_page != VM_PAGE_NULL)
                    504:            VM_PAGE_FREE(holding_page);
                    505:        vm_object_paging_end(old_object);
                    506: }
                    507: 
                    508: /*
                    509:  *     vm_pageout_scan does the dirty work for the pageout daemon.
                    510:  *     It returns with vm_page_queue_free_lock held and
                    511:  *     vm_page_free_wanted == 0.
                    512:  */
                    513: 
                    514: void vm_pageout_scan()
                    515: {
                    516:        unsigned int burst_count;
1.1.1.2   root      517:        unsigned int want_pages;
1.1       root      518: 
                    519:        /*
                    520:         *      We want to gradually dribble pages from the active queue
                    521:         *      to the inactive queue.  If we let the inactive queue get
                    522:         *      very small, and then suddenly dump many pages into it,
                    523:         *      those pages won't get a sufficient chance to be referenced
                    524:         *      before we start taking them from the inactive queue.
                    525:         *
                    526:         *      We must limit the rate at which we send pages to the pagers.
                    527:         *      data_write messages consume memory, for message buffers and
                    528:         *      for map-copy objects.  If we get too far ahead of the pagers,
                    529:         *      we can potentially run out of memory.
                    530:         *
                    531:         *      We can use the laundry count to limit directly the number
                    532:         *      of pages outstanding to the default pager.  A similar
                    533:         *      strategy for external pagers doesn't work, because
                    534:         *      external pagers don't have to deallocate the pages sent them,
                    535:         *      and because we might have to send pages to external pagers
                    536:         *      even if they aren't processing writes.  So we also
                    537:         *      use a burst count to limit writes to external pagers.
                    538:         *
                    539:         *      When memory is very tight, we can't rely on external pagers to
                    540:         *      clean pages.  They probably aren't running, because they
                    541:         *      aren't vm-privileged.  If we kept sending dirty pages to them,
                    542:         *      we could exhaust the free list.  However, we can't just ignore
                    543:         *      pages belonging to external objects, because there might be no
                    544:         *      pages belonging to internal objects.  Hence, we get the page
                    545:         *      into an internal object and then immediately double-page it,
                    546:         *      sending it to the default pager.
                    547:         *
1.1.1.3 ! root      548:         *      slab_collect should be last, because the other operations
        !           549:         *      might return memory to caches.  When we pause we use
1.1       root      550:         *      vm_pageout_scan_continue as our continuation, so we will
                    551:         *      reenter vm_pageout_scan periodically and attempt to reclaim
                    552:         *      internal memory even if we never reach vm_page_free_target.
                    553:         */
                    554: 
                    555:        stack_collect();
                    556:        net_kmsg_collect();
                    557:        consider_task_collect();
                    558:        consider_thread_collect();
1.1.1.3 ! root      559:        slab_collect();
1.1       root      560: 
                    561:        for (burst_count = 0;;) {
                    562:                register vm_page_t m;
                    563:                register vm_object_t object;
                    564:                unsigned int free_count;
                    565: 
                    566:                /*
                    567:                 *      Recalculate vm_page_inactivate_target.
                    568:                 */
                    569: 
                    570:                vm_page_lock_queues();
                    571:                vm_page_inactive_target =
                    572:                        VM_PAGE_INACTIVE_TARGET(vm_page_active_count +
                    573:                                                vm_page_inactive_count);
                    574: 
                    575:                /*
                    576:                 *      Move pages from active to inactive.
                    577:                 */
                    578: 
                    579:                while ((vm_page_inactive_count < vm_page_inactive_target) &&
                    580:                       !queue_empty(&vm_page_queue_active)) {
                    581:                        register vm_object_t obj;
                    582: 
                    583:                        vm_pageout_active++;
                    584:                        m = (vm_page_t) queue_first(&vm_page_queue_active);
                    585:                        assert(m->active && !m->inactive);
                    586: 
                    587:                        obj = m->object;
                    588:                        if (!vm_object_lock_try(obj)) {
                    589:                                /*
                    590:                                 *      Move page to end and continue.
                    591:                                 */
                    592: 
                    593:                                queue_remove(&vm_page_queue_active, m,
                    594:                                             vm_page_t, pageq);
                    595:                                queue_enter(&vm_page_queue_active, m,
                    596:                                            vm_page_t, pageq);
                    597:                                vm_page_unlock_queues();
                    598:                                vm_page_lock_queues();
                    599:                                continue;
                    600:                        }
                    601: 
                    602:                        /*
                    603:                         *      If the page is busy, then we pull it
                    604:                         *      off the active queue and leave it alone.
                    605:                         */
                    606: 
                    607:                        if (m->busy) {
                    608:                                vm_object_unlock(obj);
                    609:                                queue_remove(&vm_page_queue_active, m,
                    610:                                             vm_page_t, pageq);
                    611:                                m->active = FALSE;
                    612:                                vm_page_active_count--;
                    613:                                continue;
                    614:                        }
                    615: 
                    616:                        /*
                    617:                         *      Deactivate the page while holding the object
                    618:                         *      locked, so we know the page is still not busy.
                    619:                         *      This should prevent races between pmap_enter
                    620:                         *      and pmap_clear_reference.  The page might be
                    621:                         *      absent or fictitious, but vm_page_deactivate
                    622:                         *      can handle that.
                    623:                         */
                    624: 
                    625:                        vm_page_deactivate(m);
                    626:                        vm_object_unlock(obj);
                    627:                }
                    628: 
                    629:                /*
1.1.1.2   root      630:                 *      We are done if we have met our targets *and*
1.1       root      631:                 *      nobody is still waiting for a page.
                    632:                 */
                    633: 
                    634:                simple_lock(&vm_page_queue_free_lock);
                    635:                free_count = vm_page_free_count;
1.1.1.2   root      636:                if ((free_count >= vm_page_free_target) &&
                    637:                    (vm_page_external_count <= vm_page_external_target) &&
1.1       root      638:                    (vm_page_free_wanted == 0)) {
                    639:                        vm_page_unlock_queues();
                    640:                        break;
                    641:                }
1.1.1.2   root      642:                want_pages = ((free_count < vm_page_free_target) ||
                    643:                              vm_page_free_wanted);
1.1       root      644:                simple_unlock(&vm_page_queue_free_lock);
                    645: 
                    646:                /*
                    647:                 * Sometimes we have to pause:
                    648:                 *      1) No inactive pages - nothing to do.
                    649:                 *      2) Flow control - wait for pagers to catch up.
                    650:                 *      3) Extremely low memory - sending out dirty pages
                    651:                 *      consumes memory.  We don't take the risk of doing
                    652:                 *      this if the default pager already has work to do.
                    653:                 */
1.1.1.2   root      654:        pause:
1.1       root      655:                if (queue_empty(&vm_page_queue_inactive) ||
                    656:                    (burst_count >= vm_pageout_burst_max) ||
                    657:                    (vm_page_laundry_count >= vm_pageout_burst_max) ||
                    658:                    ((free_count < vm_pageout_reserved_really) &&
                    659:                     (vm_page_laundry_count > 0))) {
                    660:                        unsigned int pages, msecs;
                    661: 
                    662:                        /*
                    663:                         *      vm_pageout_burst_wait is msecs/page.
                    664:                         *      If there is nothing for us to do, we wait
                    665:                         *      at least vm_pageout_empty_wait msecs.
                    666:                         */
                    667: 
                    668:                        if (vm_page_laundry_count > burst_count)
                    669:                                pages = vm_page_laundry_count;
                    670:                        else
                    671:                                pages = burst_count;
                    672:                        msecs = pages * vm_pageout_burst_wait;
                    673: 
                    674:                        if (queue_empty(&vm_page_queue_inactive) &&
                    675:                            (msecs < vm_pageout_empty_wait))
                    676:                                msecs = vm_pageout_empty_wait;
                    677:                        vm_page_unlock_queues();
                    678: 
                    679:                        thread_will_wait_with_timeout(current_thread(), msecs);
                    680:                        counter(c_vm_pageout_scan_block++);
                    681:                        thread_block(vm_pageout_scan_continue);
                    682:                        call_continuation(vm_pageout_scan_continue);
                    683:                        /*NOTREACHED*/
                    684:                }
                    685: 
                    686:                vm_pageout_inactive++;
1.1.1.2   root      687: 
                    688:                /* Find a page we are interested in paging out.  If we
                    689:                   need pages, then we'll page anything out; otherwise
                    690:                   we only page out external pages. */
                    691:                m = (vm_page_t) queue_first (&vm_page_queue_inactive);
                    692:                while (1)
                    693:                  {
                    694:                    assert (!m->active && m->inactive);
                    695:                    if (want_pages || m->external)
                    696:                      break;
                    697:                    
                    698:                    m = (vm_page_t) queue_next (m);
                    699:                    if (!m)
                    700:                      goto pause;
                    701:                  }
                    702:                
1.1       root      703:                object = m->object;
                    704: 
                    705:                /*
                    706:                 *      Try to lock object; since we've got the
                    707:                 *      page queues lock, we can only try for this one.
                    708:                 */
                    709: 
                    710:                if (!vm_object_lock_try(object)) {
                    711:                        /*
                    712:                         *      Move page to end and continue.
                    713:                         */
                    714: 
                    715:                        queue_remove(&vm_page_queue_inactive, m,
                    716:                                     vm_page_t, pageq);
                    717:                        queue_enter(&vm_page_queue_inactive, m,
                    718:                                    vm_page_t, pageq);
                    719:                        vm_page_unlock_queues();
                    720:                        vm_pageout_inactive_nolock++;
                    721:                        continue;
                    722:                }
                    723: 
                    724:                /*
                    725:                 *      Remove the page from the inactive list.
                    726:                 */
                    727: 
                    728:                queue_remove(&vm_page_queue_inactive, m, vm_page_t, pageq);
                    729:                vm_page_inactive_count--;
                    730:                m->inactive = FALSE;
                    731: 
                    732:                if (m->busy || !object->alive) {
                    733:                        /*
                    734:                         *      Somebody is already playing with this page.
                    735:                         *      Leave it off the pageout queues.
                    736:                         */
                    737: 
                    738:                        vm_page_unlock_queues();
                    739:                        vm_object_unlock(object);
                    740:                        vm_pageout_inactive_busy++;
                    741:                        continue;
                    742:                }
                    743: 
                    744:                /*
                    745:                 *      If it's absent, we can reclaim the page.
                    746:                 */
                    747: 
1.1.1.2   root      748:                if (want_pages && m->absent) {
1.1       root      749:                        vm_pageout_inactive_absent++;
                    750:                    reclaim_page:
                    751:                        vm_page_free(m);
                    752:                        vm_page_unlock_queues();
                    753:                        vm_object_unlock(object);
                    754:                        continue;
                    755:                }
                    756: 
                    757:                /*
                    758:                 *      If it's being used, reactivate.
                    759:                 *      (Fictitious pages are either busy or absent.)
                    760:                 */
                    761: 
                    762:                assert(!m->fictitious);
                    763:                if (m->reference || pmap_is_referenced(m->phys_addr)) {
                    764:                        vm_object_unlock(object);
                    765:                        vm_page_activate(m);
                    766:                        vm_stat.reactivations++;
1.1.1.3 ! root      767:                        current_task()->reactivations++;
1.1       root      768:                        vm_page_unlock_queues();
                    769:                        vm_pageout_inactive_used++;
                    770:                        continue;
                    771:                }
                    772: 
                    773:                /*
                    774:                 *      Eliminate all mappings.
                    775:                 */
                    776: 
                    777:                m->busy = TRUE;
                    778:                pmap_page_protect(m->phys_addr, VM_PROT_NONE);
                    779:                if (!m->dirty)
                    780:                        m->dirty = pmap_is_modified(m->phys_addr);
                    781: 
1.1.1.2   root      782:                if (m->external) {
                    783:                        /* Figure out if we still care about this
                    784:                        page in the limit of externally managed pages.
                    785:                        Clean pages don't actually cause system hosage,
                    786:                        so it's ok to stop considering them as
                    787:                        "consumers" of memory. */
                    788:                        if (m->dirty && !m->extcounted) {
                    789:                                m->extcounted = TRUE;
                    790:                                vm_page_external_count++;
                    791:                        } else if (!m->dirty && m->extcounted) {
                    792:                                m->extcounted = FALSE;
                    793:                                vm_page_external_count--;
                    794:                        }
                    795:                }
                    796:                
                    797:                /* If we don't actually need more memory, and the page
                    798:                   is not dirty, put it on the tail of the inactive queue
                    799:                   and move on to the next page. */
                    800:                if (!want_pages && !m->dirty) {
                    801:                        queue_remove (&vm_page_queue_inactive, m, 
                    802:                                      vm_page_t, pageq);
                    803:                        queue_enter (&vm_page_queue_inactive, m,
                    804:                                     vm_page_t, pageq);
                    805:                        vm_page_unlock_queues();
                    806:                        vm_pageout_inactive_cleaned_external++;
                    807:                        continue;
                    808:                }                       
                    809: 
1.1       root      810:                /*
                    811:                 *      If it's clean and not precious, we can free the page.
                    812:                 */
                    813: 
                    814:                if (!m->dirty && !m->precious) {
                    815:                        vm_pageout_inactive_clean++;
                    816:                        goto reclaim_page;
                    817:                }
                    818: 
                    819:                /*
                    820:                 *      If we are very low on memory, then we can't
                    821:                 *      rely on an external pager to clean a dirty page,
                    822:                 *      because external pagers are not vm-privileged.
                    823:                 *
                    824:                 *      The laundry bit tells vm_pageout_setup to
                    825:                 *      put the page back at the front of the inactive
                    826:                 *      queue instead of activating the page.  Hence,
                    827:                 *      we will pick the page up again immediately and
                    828:                 *      resend it to the default pager.
                    829:                 */
                    830: 
                    831:                assert(!m->laundry);
                    832:                if ((free_count < vm_pageout_reserved_internal) &&
                    833:                    !object->internal) {
                    834:                        m->laundry = TRUE;
                    835:                        vm_pageout_inactive_double++;
                    836:                }
                    837:                vm_page_unlock_queues();
                    838: 
                    839:                /*
                    840:                 *      If there is no memory object for the page, create
                    841:                 *      one and hand it to the default pager.
                    842:                 *      [First try to collapse, so we don't create
                    843:                 *      one unnecessarily.]
                    844:                 */
                    845: 
                    846:                if (!object->pager_initialized)
                    847:                        vm_object_collapse(object);
                    848:                if (!object->pager_initialized)
                    849:                        vm_object_pager_create(object);
                    850:                if (!object->pager_initialized)
                    851:                        panic("vm_pageout_scan");
                    852: 
                    853:                vm_pageout_inactive_dirty++;
                    854:                vm_pageout_page(m, FALSE, TRUE);        /* flush it */
                    855:                vm_object_unlock(object);
                    856:                burst_count++;
                    857:        }
                    858: }
                    859: 
                    860: void vm_pageout_scan_continue()
                    861: {
                    862:        /*
                    863:         *      We just paused to let the pagers catch up.
                    864:         *      If vm_page_laundry_count is still high,
                    865:         *      then we aren't waiting long enough.
                    866:         *      If we have paused some vm_pageout_pause_max times without
                    867:         *      adjusting vm_pageout_burst_wait, it might be too big,
                    868:         *      so we decrease it.
                    869:         */
                    870: 
                    871:        vm_page_lock_queues();
                    872:        if (vm_page_laundry_count > vm_pageout_burst_min) {
                    873:                vm_pageout_burst_wait++;
                    874:                vm_pageout_pause_count = 0;
                    875:        } else if (++vm_pageout_pause_count > vm_pageout_pause_max) {
                    876:                vm_pageout_burst_wait = (vm_pageout_burst_wait * 3) / 4;
                    877:                if (vm_pageout_burst_wait < 1)
                    878:                        vm_pageout_burst_wait = 1;
                    879:                vm_pageout_pause_count = 0;
                    880:        }
                    881:        vm_page_unlock_queues();
                    882: 
                    883:        vm_pageout_continue();
                    884:        /*NOTREACHED*/
                    885: }
                    886: 
                    887: /*
                    888:  *     vm_pageout is the high level pageout daemon.
                    889:  */
                    890: 
                    891: void vm_pageout_continue()
                    892: {
                    893:        /*
                    894:         *      The pageout daemon is never done, so loop forever.
                    895:         *      We should call vm_pageout_scan at least once each
                    896:         *      time we are woken, even if vm_page_free_wanted is
                    897:         *      zero, to check vm_page_free_target and
                    898:         *      vm_page_inactive_target.
                    899:         */
                    900: 
                    901:        for (;;) {
                    902:                vm_pageout_scan();
                    903:                /* we hold vm_page_queue_free_lock now */
                    904:                assert(vm_page_free_wanted == 0);
                    905: 
                    906:                assert_wait(&vm_page_free_wanted, FALSE);
                    907:                simple_unlock(&vm_page_queue_free_lock);
                    908:                counter(c_vm_pageout_block++);
                    909:                thread_block(vm_pageout_continue);
                    910:        }
                    911: }
                    912: 
                    913: void vm_pageout()
                    914: {
                    915:        int             free_after_reserve;
                    916: 
                    917:        current_thread()->vm_privilege = TRUE;
                    918:        stack_privilege(current_thread());
                    919: 
                    920:        /*
                    921:         *      Initialize some paging parameters.
                    922:         */
                    923: 
                    924:        if (vm_pageout_burst_max == 0)
                    925:                vm_pageout_burst_max = VM_PAGEOUT_BURST_MAX;
                    926: 
                    927:        if (vm_pageout_burst_min == 0)
                    928:                vm_pageout_burst_min = VM_PAGEOUT_BURST_MIN;
                    929: 
                    930:        if (vm_pageout_burst_wait == 0)
                    931:                vm_pageout_burst_wait = VM_PAGEOUT_BURST_WAIT;
                    932: 
                    933:        if (vm_pageout_empty_wait == 0)
                    934:                vm_pageout_empty_wait = VM_PAGEOUT_EMPTY_WAIT;
                    935: 
                    936:        if (vm_page_free_reserved == 0)
                    937:                vm_page_free_reserved = VM_PAGE_FREE_RESERVED;
                    938: 
                    939:        if (vm_pageout_pause_max == 0)
                    940:                vm_pageout_pause_max = VM_PAGEOUT_PAUSE_MAX;
                    941: 
                    942:        if (vm_pageout_reserved_internal == 0)
                    943:                vm_pageout_reserved_internal =
                    944:                        VM_PAGEOUT_RESERVED_INTERNAL(vm_page_free_reserved);
                    945: 
                    946:        if (vm_pageout_reserved_really == 0)
                    947:                vm_pageout_reserved_really =
                    948:                        VM_PAGEOUT_RESERVED_REALLY(vm_page_free_reserved);
                    949: 
                    950:        free_after_reserve = vm_page_free_count - vm_page_free_reserved;
                    951: 
1.1.1.2   root      952:        if (vm_page_external_limit == 0)
                    953:                vm_page_external_limit = 
                    954:                        VM_PAGE_EXTERNAL_LIMIT (free_after_reserve);
                    955: 
                    956:        if (vm_page_external_target == 0)
                    957:                vm_page_external_target = 
                    958:                        VM_PAGE_EXTERNAL_TARGET (free_after_reserve);
                    959: 
1.1       root      960:        if (vm_page_free_min == 0)
                    961:                vm_page_free_min = vm_page_free_reserved +
                    962:                        VM_PAGE_FREE_MIN(free_after_reserve);
                    963: 
                    964:        if (vm_page_free_target == 0)
                    965:                vm_page_free_target = vm_page_free_reserved +
                    966:                        VM_PAGE_FREE_TARGET(free_after_reserve);
                    967: 
                    968:        if (vm_page_free_target < vm_page_free_min + 5)
                    969:                vm_page_free_target = vm_page_free_min + 5;
                    970: 
                    971:        /*
                    972:         *      vm_pageout_scan will set vm_page_inactive_target.
                    973:         */
                    974: 
                    975:        vm_pageout_continue();
                    976:        /*NOTREACHED*/
                    977: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.