1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  28 /*        All Rights Reserved   */
  29 
  30 #include <sys/param.h>
  31 #include <sys/types.h>
  32 #include <sys/sysmacros.h>
  33 #include <sys/systm.h>
  34 #include <sys/proc.h>
  35 #include <sys/cpuvar.h>
  36 #include <sys/var.h>
  37 #include <sys/tuneable.h>
  38 #include <sys/cmn_err.h>
  39 #include <sys/buf.h>
  40 #include <sys/disp.h>
  41 #include <sys/vmsystm.h>
  42 #include <sys/vmparam.h>
  43 #include <sys/class.h>
  44 #include <sys/vtrace.h>
  45 #include <sys/modctl.h>
  46 #include <sys/debug.h>
  47 #include <sys/tnf_probe.h>
  48 #include <sys/procfs.h>
  49 
  50 #include <vm/seg.h>
  51 #include <vm/seg_kp.h>
  52 #include <vm/as.h>
  53 #include <vm/rm.h>
  54 #include <vm/seg_kmem.h>
  55 #include <sys/callb.h>
  56 
  57 pgcnt_t avefree;        /* 5 sec moving average of free memory */
  58 pgcnt_t avefree30;      /* 30 sec moving average of free memory */
  59 
  60 /*
  61  * Memory scheduler.
  62  */
  63 void
  64 sched()
  65 {
  66         kthread_id_t    t;
  67         callb_cpr_t     cprinfo;
  68         kmutex_t        swap_cpr_lock;
  69 
  70         mutex_init(&swap_cpr_lock, NULL, MUTEX_DEFAULT, NULL);
  71         CALLB_CPR_INIT(&cprinfo, &swap_cpr_lock, callb_generic_cpr, "sched");
  72 
  73         for (;;) {
  74                 if (avenrun[0] >= 2 * FSCALE &&
  75                     (MAX(avefree, avefree30) < desfree) &&
  76                     (pginrate + pgoutrate > maxpgio || avefree < minfree)) {
  77                         /*
  78                          * Unload all unloadable modules, free all other memory
  79                          * resources we can find, then look for a thread to
  80                          * hardswap.
  81                          */
  82                         modreap();
  83                         segkp_cache_free();
  84                 }
  85 
  86                 t = curthread;
  87                 thread_lock(t);
  88                 t->t_schedflag |= (TS_ALLSTART & ~TS_CSTART);
  89                 t->t_whystop = PR_SUSPENDED;
  90                 t->t_whatstop = SUSPEND_NORMAL;
  91                 (void) new_mstate(t, LMS_SLEEP);
  92                 mutex_enter(&swap_cpr_lock);
  93                 CALLB_CPR_SAFE_BEGIN(&cprinfo);
  94                 mutex_exit(&swap_cpr_lock);
  95                 thread_stop(t);         /* change to stop state and drop lock */
  96                 swtch();
  97                 mutex_enter(&swap_cpr_lock);
  98                 CALLB_CPR_SAFE_END(&cprinfo, &swap_cpr_lock);
  99                 mutex_exit(&swap_cpr_lock);
 100         }
 101 }