These changes fix a couple of lingering VM problems:
1. The pageout daemon used to block under certain circumstances, and we needed to add new functionality that would cause the pageout daemon to block more often. Now, the pageout daemon mostly just gets rid of pages and kills processes when the system is out of swap. The swapping, rss limiting and object cache trimming have been folded into a new daemon called "vmdaemon". This new daemon does things that need to be done for the VM system, but can block. For example, if the vmdaemon blocks for memory, the pageout daemon can take care of it. If the pageout daemon had blocked for memory, it was difficult to handle the situation correctly (and in some cases, was impossible). 2. The collapse problem has now been entirely fixed. It now appears to be impossible to accumulate unnecessary vm objects. The object collapsing now occurs when ref counts drop to one (where it is more likely to be more simple anyway because less pages would be out on disk.) The original fixes were incomplete in that pathological circumstances could still be contrived to cause uncontrolled growth of swap. Also, the old code still, under steady state conditions, used more swap space than necessary. When using the new code, users will generally notice a significant decrease in swap space usage, and theoretically, the system should be leaving fewer unused pages around competing for memory. Submitted by: John Dyson
This commit is contained in:
parent
40598ff428
commit
eadf9e27cd
@ -36,7 +36,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)init_main.c 8.9 (Berkeley) 1/21/94
|
||||
* $Id: init_main.c,v 1.15 1994/10/26 03:34:20 phk Exp $
|
||||
* $Id: init_main.c,v 1.16 1994/11/06 05:01:58 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -319,7 +319,6 @@ main(framep)
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#ifdef REL2_1
|
||||
/*
|
||||
* Start high level vm daemon (process 3).
|
||||
*/
|
||||
@ -333,7 +332,6 @@ main(framep)
|
||||
vm_daemon();
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Start update daemon (process 4).
|
||||
|
@ -61,7 +61,7 @@
|
||||
* any improvements or extensions that they make and grant Carnegie the
|
||||
* rights to redistribute these changes.
|
||||
*
|
||||
* $Id: vm_object.c,v 1.9 1994/10/15 10:28:46 davidg Exp $
|
||||
* $Id: vm_object.c,v 1.10 1994/11/06 05:07:50 davidg Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -127,9 +127,7 @@ _vm_object_allocate(size, object)
|
||||
{
|
||||
bzero(object, sizeof *object);
|
||||
TAILQ_INIT(&object->memq);
|
||||
#ifdef REL2_1a
|
||||
TAILQ_INIT(&object->reverse_shadow_head);
|
||||
#endif
|
||||
vm_object_lock_init(object);
|
||||
object->ref_count = 1;
|
||||
object->resident_page_count = 0;
|
||||
@ -253,10 +251,8 @@ vm_object_deallocate(object)
|
||||
*/
|
||||
vm_object_lock(object);
|
||||
if (--(object->ref_count) != 0) {
|
||||
#ifdef REL2_1a
|
||||
if( object->ref_count == 1)
|
||||
vm_object_rcollapse(object->reverse_shadow_head.tqh_first, object);
|
||||
#endif
|
||||
|
||||
vm_object_unlock(object);
|
||||
/*
|
||||
@ -299,10 +295,8 @@ vm_object_deallocate(object)
|
||||
vm_object_cache_unlock();
|
||||
|
||||
temp = object->shadow;
|
||||
#ifdef REL2_1a
|
||||
if( temp)
|
||||
TAILQ_REMOVE(&temp->reverse_shadow_head, object, reverse_shadow_list);
|
||||
#endif
|
||||
vm_object_terminate(object);
|
||||
/* unlocks and deallocates object */
|
||||
object = temp;
|
||||
@ -917,14 +911,10 @@ void vm_object_copy(src_object, src_offset, size,
|
||||
*/
|
||||
|
||||
src_object->ref_count--; /* remove ref. from old_copy */
|
||||
#ifdef REL2_1a
|
||||
if( old_copy->shadow)
|
||||
TAILQ_REMOVE(&old_copy->shadow->reverse_shadow_head, old_copy, reverse_shadow_list);
|
||||
#endif
|
||||
old_copy->shadow = new_copy;
|
||||
#ifdef REL2_1a
|
||||
TAILQ_INSERT_TAIL(&old_copy->shadow->reverse_shadow_head, old_copy, reverse_shadow_list);
|
||||
#endif
|
||||
new_copy->ref_count++; /* locking not needed - we
|
||||
have the only pointer */
|
||||
vm_object_unlock(old_copy); /* done with old_copy */
|
||||
@ -938,9 +928,7 @@ void vm_object_copy(src_object, src_offset, size,
|
||||
*/
|
||||
|
||||
new_copy->shadow = src_object;
|
||||
#ifdef REL2_1a
|
||||
TAILQ_INSERT_TAIL(&new_copy->shadow->reverse_shadow_head, new_copy, reverse_shadow_list);
|
||||
#endif
|
||||
new_copy->shadow_offset = new_start;
|
||||
src_object->ref_count++;
|
||||
src_object->copy = new_copy;
|
||||
@ -997,9 +985,7 @@ vm_object_shadow(object, offset, length)
|
||||
* count.
|
||||
*/
|
||||
result->shadow = source;
|
||||
#ifdef REL2_1a
|
||||
TAILQ_INSERT_TAIL(&result->shadow->reverse_shadow_head, result, reverse_shadow_list);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Store the offset into the source object,
|
||||
@ -1148,7 +1134,6 @@ vm_object_remove(pager)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REL2_1a
|
||||
static void
|
||||
vm_object_rcollapse(object, sobject)
|
||||
register vm_object_t object, sobject;
|
||||
@ -1212,7 +1197,6 @@ vm_object_rcollapse(object, sobject)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* this version of collapse allows the operation to occur earlier and
|
||||
@ -1483,17 +1467,13 @@ vm_object_collapse(object)
|
||||
* moves from within backing_object to within object.
|
||||
*/
|
||||
|
||||
#ifdef REL2_1a
|
||||
TAILQ_REMOVE(&object->shadow->reverse_shadow_head, object, reverse_shadow_list);
|
||||
if( backing_object->shadow)
|
||||
TAILQ_REMOVE(&backing_object->shadow->reverse_shadow_head, backing_object, reverse_shadow_list);
|
||||
#endif
|
||||
object->shadow = backing_object->shadow;
|
||||
#ifdef REL2_1a
|
||||
if( object->shadow)
|
||||
TAILQ_INSERT_TAIL(&object->shadow->reverse_shadow_head, object, reverse_shadow_list);
|
||||
#endif
|
||||
|
||||
|
||||
object->shadow_offset += backing_object->shadow_offset;
|
||||
if (object->shadow != NULL &&
|
||||
object->shadow->copy != NULL) {
|
||||
@ -1574,14 +1554,10 @@ vm_object_collapse(object)
|
||||
* count is at least 2.
|
||||
*/
|
||||
|
||||
#ifdef REL2_1a
|
||||
TAILQ_REMOVE(&object->shadow->reverse_shadow_head, object, reverse_shadow_list);
|
||||
#endif
|
||||
vm_object_reference(object->shadow = backing_object->shadow);
|
||||
#ifdef REL2_1a
|
||||
if( object->shadow)
|
||||
TAILQ_INSERT_TAIL(&object->shadow->reverse_shadow_head, object, reverse_shadow_list);
|
||||
#endif
|
||||
object->shadow_offset += backing_object->shadow_offset;
|
||||
|
||||
/*
|
||||
|
@ -65,7 +65,7 @@
|
||||
* any improvements or extensions that they make and grant Carnegie the
|
||||
* rights to redistribute these changes.
|
||||
*
|
||||
* $Id: vm_pageout.c,v 1.25 1994/11/14 02:57:40 davidg Exp $
|
||||
* $Id: vm_pageout.c,v 1.26 1994/11/17 06:24:25 davidg Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -343,20 +343,10 @@ vm_pageout_object_deactivate_pages(map, object, count)
|
||||
if (count == 0)
|
||||
count = 1;
|
||||
|
||||
#ifndef REL2_1
|
||||
if (object->shadow) {
|
||||
int scount = count;
|
||||
if( object->shadow->ref_count > 1)
|
||||
scount /= object->shadow->ref_count;
|
||||
if( scount)
|
||||
dcount += vm_pageout_object_deactivate_pages(map, object->shadow, scount);
|
||||
}
|
||||
#else
|
||||
if (object->shadow) {
|
||||
if( object->shadow->ref_count == 1)
|
||||
dcount += vm_pageout_object_deactivate_pages(map, object->shadow, count/2);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (object->paging_in_progress)
|
||||
return dcount;
|
||||
@ -479,7 +469,6 @@ vm_pageout_map_deactivate_pages(map, entry, count, freeer)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef REL2_1
|
||||
void
|
||||
vm_req_vmdaemon() {
|
||||
extern int ticks;
|
||||
@ -489,7 +478,6 @@ vm_req_vmdaemon() {
|
||||
lastrun = ticks;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* vm_pageout_scan does the dirty work for the pageout daemon.
|
||||
@ -508,69 +496,6 @@ vm_pageout_scan()
|
||||
int force_wakeup = 0;
|
||||
int cache_size, orig_cache_size;
|
||||
|
||||
#ifndef REL2_1
|
||||
morefree:
|
||||
/*
|
||||
* now swap processes out if we are in low memory conditions
|
||||
*/
|
||||
if ((cnt.v_free_count <= cnt.v_free_min) && !swap_pager_full && vm_swap_size) {
|
||||
/*
|
||||
* swap out inactive processes
|
||||
*/
|
||||
swapout_threads();
|
||||
}
|
||||
|
||||
/*
|
||||
* scan the processes for exceeding their rlimits or if process
|
||||
* is swapped out -- deactivate pages
|
||||
*/
|
||||
|
||||
for (p = (struct proc *)allproc; p != NULL; p = p->p_next) {
|
||||
int overage;
|
||||
quad_t limit;
|
||||
|
||||
/*
|
||||
* if this is a system process or if we have already
|
||||
* looked at this process, skip it.
|
||||
*/
|
||||
if (p->p_flag & (P_SYSTEM|P_WEXIT)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* if the process is in a non-running type state,
|
||||
* don't touch it.
|
||||
*/
|
||||
if (p->p_stat != SRUN && p->p_stat != SSLEEP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* get a limit
|
||||
*/
|
||||
limit = qmin(p->p_rlimit[RLIMIT_RSS].rlim_cur,
|
||||
p->p_rlimit[RLIMIT_RSS].rlim_max);
|
||||
|
||||
/*
|
||||
* let processes that are swapped out really be swapped out
|
||||
* set the limit to nothing (will force a swap-out.)
|
||||
*/
|
||||
if ((p->p_flag & P_INMEM) == 0)
|
||||
limit = 0;
|
||||
|
||||
size = p->p_vmspace->vm_pmap.pm_stats.resident_count * NBPG;
|
||||
if (limit >= 0 && size >= limit) {
|
||||
overage = (size - limit) / NBPG;
|
||||
vm_pageout_map_deactivate_pages(&p->p_vmspace->vm_map,
|
||||
(vm_map_entry_t) 0, &overage, vm_pageout_object_deactivate_pages);
|
||||
}
|
||||
}
|
||||
|
||||
if (((cnt.v_free_count + cnt.v_inactive_count) >=
|
||||
(cnt.v_inactive_target + cnt.v_free_target)) &&
|
||||
(cnt.v_free_count >= cnt.v_free_target))
|
||||
return force_wakeup;
|
||||
#else
|
||||
/* calculate the total cached size */
|
||||
|
||||
if( cnt.v_inactive_count < cnt.v_inactive_target) {
|
||||
@ -586,8 +511,6 @@ vm_pageout_scan()
|
||||
vm_req_vmdaemon();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
pages_freed = 0;
|
||||
desired_free = cnt.v_free_target;
|
||||
|
||||
@ -598,7 +521,7 @@ vm_pageout_scan()
|
||||
* encounter dirty pages, we start cleaning them.
|
||||
*/
|
||||
|
||||
maxlaunder = (cnt.v_free_target - cnt.v_free_count);
|
||||
maxlaunder = 128;
|
||||
maxscan = cnt.v_inactive_count;
|
||||
rescan1:
|
||||
m = vm_page_queue_inactive.tqh_first;
|
||||
@ -891,7 +814,6 @@ vm_pageout()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef REL2_1
|
||||
void
|
||||
vm_daemon() {
|
||||
int cache_size;
|
||||
@ -994,4 +916,3 @@ vm_daemon() {
|
||||
vm_object_cache_unlock();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user