diff options
author | Neal H. Walfield <neal@gnu.org> | 2008-11-04 16:25:13 +0100 |
---|---|---|
committer | Neal H. Walfield <neal@gnu.org> | 2008-11-04 16:25:13 +0100 |
commit | 908dbd86b3c431456df7a7d1f6b69f6e2830e0af (patch) | |
tree | 1aa0b65e8f9a8b6b98fdc281cd4c30a4e9ddd904 | |
parent | b3c92f167f20f1267c6b4ec83f1b6b6edd2ba85a (diff) |
In the activity structure, use a pair of lists per priority level.
2008-11-04 Neal H. Walfield <neal@gnu.org>
* activity.h (struct activity): Replace fields active, inactive,
priorities and priorities_count with fields frames_ and frames.
Update users.
* object.h (activity_lru): Rename from this...
(activity): ... to this. Update users.
* activity.c (activity_destroy): When moving frames claimed by a
child to its parent's lowest priority level, update each frame's
respective priority.
(activity_prepare) [! NDEBUG]: Initialize priority levels.
-rw-r--r-- | viengoos/ChangeLog | 12 | ||||
-rw-r--r-- | viengoos/activity.c | 157 | ||||
-rw-r--r-- | viengoos/activity.h | 40 | ||||
-rw-r--r-- | viengoos/ager.c | 32 | ||||
-rw-r--r-- | viengoos/object.c | 209 | ||||
-rw-r--r-- | viengoos/object.h | 6 | ||||
-rw-r--r-- | viengoos/pager.c | 196 |
7 files changed, 305 insertions, 347 deletions
diff --git a/viengoos/ChangeLog b/viengoos/ChangeLog index 47185bc..5604614 100644 --- a/viengoos/ChangeLog +++ b/viengoos/ChangeLog @@ -1,3 +1,15 @@ +2008-11-04 Neal H. Walfield <neal@gnu.org> + + * activity.h (struct activity): Replace fields active, inactive, + priorities and priorities_count with fields frames_ and frames. + Update users. + * object.h (activity_lru): Rename from this... + (activity): ... to this. Update users. + * activity.c (activity_destroy): When moving frames claimed by a + child to its parent's lowest priority level, update each frame's + respective priority. + (activity_prepare) [! NDEBUG]: Initialize priority levels. + 2008-11-03 Neal H. Walfield <neal@gnu.org> * viengoos.c (main): Use s_printf, not debug, to print the diff --git a/viengoos/activity.c b/viengoos/activity.c index 2f1fe18..12a4320 100644 --- a/viengoos/activity.c +++ b/viengoos/activity.c @@ -140,68 +140,50 @@ activity_destroy (struct activity *activity, struct activity *victim) int count = 0; /* Make ACTIVE objects inactive. */ - for (desc = activity_lru_list_head (&victim->active); - desc; desc = activity_lru_list_next (desc)) + int i; + for (i = OBJECT_PRIORITY_MIN; i <= OBJECT_PRIORITY_MAX; i ++) { - assert (! desc->eviction_candidate); - assert (desc->activity == victim); - assert (! list_node_attached (&desc->laundry_node)); - assert (desc->age); - - desc->age = 0; - desc->activity = victim->parent; - count ++; + for (desc = activity_list_head (&victim->frames[i].active); + desc; desc = activity_list_next (desc)) + { + assert (! desc->eviction_candidate); + assert (desc->activity == victim); + assert (! list_node_attached (&desc->laundry_node)); + assert (desc->age); + assert (desc->policy.priority == i); + + desc->age = 0; + desc->policy.priority = OBJECT_PRIORITY_MIN; + desc->activity = victim->parent; + count ++; + } + activity_list_join + (&victim->parent->frames[OBJECT_PRIORITY_MIN].inactive, + &victim->frames[i].active); } - activity_lru_list_join (&victim->parent->inactive, - &victim->active); - - struct object_desc *next - = hurd_btree_priorities_first (&victim->priorities); - while ((desc = next)) - { - assert (! desc->eviction_candidate); - assert (desc->activity == victim); - assert (desc->policy.priority != OBJECT_PRIORITY_LRU); - - next = hurd_btree_priorities_next (desc); - - desc->age = 0; - desc->activity = victim->parent; - -#ifndef NDEBUG - /* We don't detach it from the tree as we destroy the tree in - its entirety. But, the insert code expects the fields to - be zero'd. */ - memset (&desc->priority_node, 0, sizeof (desc->priority_node)); -#endif - - void *ret = hurd_btree_priorities_insert (&victim->parent->priorities, - desc); - assert (! ret); - victim->parent->priorities_count ++; - - count ++; - } -#ifndef NDEBUG - hurd_btree_priorities_tree_init (&victim->priorities); -#endif /* Move inactive objects to the head of VICTIM->PARENT's appropriate inactive list (thereby making them the first eviction candidates). */ - for (desc = activity_lru_list_head (&victim->inactive); - desc; desc = activity_lru_list_next (desc)) + for (i = OBJECT_PRIORITY_MIN; i <= OBJECT_PRIORITY_MAX; i ++) { - assert (! desc->eviction_candidate); - assert (desc->activity == victim); - assert (! list_node_attached (&desc->laundry_node)); - assert (! desc->age); - - desc->activity = victim->parent; - count ++; + for (desc = activity_list_head (&victim->frames[i].inactive); + desc; desc = activity_list_next (desc)) + { + assert (! desc->eviction_candidate); + assert (desc->activity == victim); + assert (! list_node_attached (&desc->laundry_node)); + assert (! desc->age); + assert (desc->policy.priority == i); + + desc->activity = victim->parent; + desc->policy.priority = OBJECT_PRIORITY_MIN; + count ++; + } + activity_list_join + (&victim->parent->frames[OBJECT_PRIORITY_MIN].inactive, + &victim->frames[i].inactive); } - activity_lru_list_join (&victim->parent->inactive, - &victim->inactive); /* And move all of VICTIM's eviction candidates to VICTIM->PARENT's @@ -323,12 +305,54 @@ activity_prepare (struct activity *principal, struct activity *activity) activity, last); } +#ifndef NDEBUG activity_children_list_init (&activity->children, "activity->children"); - activity_lru_list_init (&activity->active, "active"); - activity_lru_list_init (&activity->inactive, "inactive"); + static const char *names[OBJECT_PRIORITY_LEVELS] + = { "inactive-64", "inactive-63", "inactive-62", "inactive-61", + "inactive-60", "inactive-59", "inactive-58", "inactive-57", + "inactive-56", "inactive-55", "inactive-54", "inactive-53", + "inactive-52", "inactive-51", "inactive-50", "inactive-49", + "inactive-48", "inactive-47", "inactive-46", "inactive-45", + "inactive-44", "inactive-43", "inactive-42", "inactive-41", + "inactive-40", "inactive-39", "inactive-38", "inactive-37", + "inactive-36", "inactive-35", "inactive-34", "inactive-33", + "inactive-32", "inactive-31", "inactive-30", "inactive-29", + "inactive-28", "inactive-27", "inactive-26", "inactive-25", + "inactive-24", "inactive-23", "inactive-22", "inactive-21", + "inactive-20", "inactive-19", "inactive-18", "inactive-17", + "inactive-16", "inactive-15", "inactive-14", "inactive-13", + "inactive-12", "inactive-11", "inactive-10", "inactive-9", + "inactive-8", "inactive-7", "inactive-6", "inactive-5", + "inactive-4", "inactive-3", "inactive-2", "inactive-1", + "inactive0", "inactive1", "inactive2", "inactive3", + "inactive4", "inactive5", "inactive6", "inactive7", + "inactive8", "inactive9", "inactive10", "inactive11", + "inactive12", "inactive13", "inactive14", "inactive15", + "inactive16", "inactive17", "inactive18", "inactive19", + "inactive20", "inactive21", "inactive22", "inactive23", + "inactive24", "inactive25", "inactive26", "inactive27", + "inactive28", "inactive29", "inactive30", "inactive31", + "inactive32", "inactive33", "inactive34", "inactive35", + "inactive36", "inactive37", "inactive38", "inactive39", + "inactive40", "inactive41", "inactive42", "inactive43", + "inactive44", "inactive45", "inactive46", "inactive47", + "inactive48", "inactive49", "inactive50", "inactive51", + "inactive52", "inactive53", "inactive54", "inactive55", + "inactive56", "inactive57", "inactive58", "inactive59", + "inactive60", "inactive61", "inactive62", "inactive63" }; + + int i; + for (i = OBJECT_PRIORITY_MIN; i <= OBJECT_PRIORITY_MAX; i ++) + { + activity_list_init (&activity->frames[i].active, + &names[i - OBJECT_PRIORITY_MIN][2]); + activity_list_init (&activity->frames[i].inactive, + names[i - OBJECT_PRIORITY_MIN]); + } eviction_list_init (&activity->eviction_clean, "evict clean"); eviction_list_init (&activity->eviction_dirty, "evict dirty"); +#endif } void @@ -337,8 +361,12 @@ activity_deprepare (struct activity *principal, struct activity *victim) /* If we have any in-memory children or frames, then we can't be paged out. */ assert (! activity_children_list_head (&victim->children)); - assert (! activity_lru_list_count (&victim->active)); - assert (! activity_lru_list_count (&victim->inactive)); + int i; + for (i = OBJECT_PRIORITY_MIN; i <= OBJECT_PRIORITY_MAX; i ++) + { + assert (! activity_list_count (&victim->frames[i].active)); + assert (! activity_list_count (&victim->frames[i].inactive)); + } assert (! eviction_list_count (&victim->eviction_clean)); assert (! eviction_list_count (&victim->eviction_dirty)); @@ -408,8 +436,15 @@ do_activity_dump (struct activity *activity, int indent) memset (indent_string, ' ', indent); indent_string[indent] = 0; - int active = activity_lru_list_count (&activity->active); - int inactive = activity_lru_list_count (&activity->inactive); + int active = 0; + int inactive = 0; + + int i; + for (i = OBJECT_PRIORITY_MIN; i <= OBJECT_PRIORITY_MAX; i ++) + { + active += activity_list_count (&activity->frames[i].active); + inactive += activity_list_count (&activity->frames[i].inactive); + } int clean = eviction_list_count (&activity->eviction_clean); int dirty = eviction_list_count (&activity->eviction_dirty); @@ -442,7 +477,7 @@ activity_dump (struct activity *activity) zalloc_memory + available_list_count (&available), (100 * (zalloc_memory + available_list_count (&available))) / memory_total, - eviction_list_count (&laundry)); + laundry_list_count (&laundry)); do_activity_dump (activity, 0); } } diff --git a/viengoos/activity.h b/viengoos/activity.h index 8ffcc94..983395a 100644 --- a/viengoos/activity.h +++ b/viengoos/activity.h @@ -70,17 +70,19 @@ struct activity struct activity_children_list children; struct list_node sibling; - /* Objects claimed by this activity whose priority is - OBJECT_PRIORITY_LRU and for which DESC->EVICTION_CANDIDATE is - false. */ - struct activity_lru_list active; - struct activity_lru_list inactive; - - /* Objects claimed by this activity whose priority is not - OBJECT_PRIORITY_LRU and for which DESC->EVICTION_CANDIDATE is - false. Keyed by priority. */ - hurd_btree_priorities_t priorities; - int priorities_count; + /* Objects claimed by this activity for which + DESC->EVICTION_CANDIDATE is false. As priority is signed, to + avoid having to adjust the index, we play a small trick. */ + struct + { + struct activity_list active; + struct activity_list inactive; + } frames_[-OBJECT_PRIORITY_MIN]; + struct + { + struct activity_list active; + struct activity_list inactive; + } frames[OBJECT_PRIORITY_MAX + 1]; /* Objects that are owned by this activity and have been selected for eviction (DESC->EVICTION_CANDIDATE is true). These objects @@ -90,17 +92,15 @@ struct activity struct eviction_list eviction_dirty; /* Number of frames allocated to this activity not counting - children. This includes all frames allocated on the PRIORITY - tree and the ACTIVE, INACTIVE and EVICTION_DIRTY lists (but not - the EVICTION_CLEAN list, as it is elements on it are immediately - reclaimable). */ + children. This includes all frames allocated on the ACTIVE, + INACTIVE and EVICTION_DIRTY lists (but not the EVICTION_CLEAN + list, as it is elements on it are immediately reclaimable). */ uint32_t frames_local; /* Number of frames allocated to this activity (including children). - This is the sum of the number of objects on the PRIORITY tree, - and the ACTIVE, INACTIVE and EVICTION_DIRTY lists plus the number - of frames allocated to each child. This does not include the - number of frames on the eviction_clean and eviction_dirty - lists. */ + This is the sum of the number of objects on the ACTIVE, INACTIVE + and EVICTION_DIRTY lists plus the number of frames allocated to + each child. This does not include the number of frames on the + eviction_clean and eviction_dirty lists. */ uint32_t frames_total; /* Dirty frames that are pending eviction. */ diff --git a/viengoos/ager.c b/viengoos/ager.c index f413388..65cbf43 100644 --- a/viengoos/ager.c +++ b/viengoos/ager.c @@ -605,8 +605,7 @@ ager_loop (void) object_age (desc, referenced); - if (! object_active (desc) - && desc->policy.priority == OBJECT_PRIORITY_LRU) + if (! object_active (desc)) /* The object has become inactive and needs to be moved. */ { @@ -614,11 +613,13 @@ ager_loop (void) became_inactive ++; - /* Detach from active list. */ - activity_lru_list_unlink (&desc->activity->active, - desc); - - activity_lru_list_push (&desc->activity->inactive, desc); + /* Detach from active list and reattach to + inactive list. */ + int priority = desc->policy.priority; + activity_list_unlink + (&desc->activity->frames[priority].active, desc); + activity_list_push + (&desc->activity->frames[priority].inactive, desc); } else ACTIVITY_STATS (desc->activity)->active ++; @@ -635,16 +636,13 @@ ager_loop (void) became_active ++; - if (desc->policy.priority == OBJECT_PRIORITY_LRU) - { - /* Detach from inactive list. */ - activity_lru_list_unlink - (&desc->activity->inactive, desc); - - /* Attach to active list. */ - activity_lru_list_push (&desc->activity->active, - desc); - } + /* Detach from inactive list and reattach to the + active list. */ + int priority = desc->policy.priority; + activity_list_unlink + (&desc->activity->frames[priority].inactive, desc); + activity_list_push + (&desc->activity->frames[priority].active, desc); desc->dirty |= dirty; } diff --git a/viengoos/object.c b/viengoos/object.c index b1433e3..52b2283 100644 --- a/viengoos/object.c +++ b/viengoos/object.c @@ -696,46 +696,60 @@ object_desc_claim (struct activity *activity, struct object_desc *desc, struct object_policy o = desc->policy; bool ec = desc->eviction_candidate; +#ifndef NDEBUG if (desc->activity && update_accounting) - assertx (desc->activity->priorities_count - + activity_lru_list_count (&desc->activity->active) - + activity_lru_list_count (&desc->activity->inactive) - + eviction_list_count (&desc->activity->eviction_dirty) - == desc->activity->frames_local, - "%d+%d+%d+%d = %d != %d! (%p=>%p,%d,%d,%d=>%d,%d=>%d)", - desc->activity->priorities_count, - activity_lru_list_count (&desc->activity->active), - activity_lru_list_count (&desc->activity->inactive), - eviction_list_count (&desc->activity->eviction_dirty), - desc->activity->priorities_count - + activity_lru_list_count (&desc->activity->active) - + activity_lru_list_count (&desc->activity->inactive) - + eviction_list_count (&desc->activity->eviction_dirty), - desc->activity->frames_local, - desc->activity, activity, - desc->eviction_candidate, desc->dirty, - o.discardable, policy.discardable, - o.priority, policy.priority); + { + int active = 0; + int inactive = 0; + + int i; + for (i = OBJECT_PRIORITY_MIN; i <= OBJECT_PRIORITY_MAX; i ++) + { + active += activity_list_count (&desc->activity->frames[i].active); + inactive += activity_list_count (&desc->activity->frames[i].inactive); + } + + assertx (active + inactive + + eviction_list_count (&desc->activity->eviction_dirty) + == desc->activity->frames_local, + "%d+%d+%d = %d != %d! (%p=>%p,%d,%d,%d=>%d,%d=>%d)", + active, inactive, + eviction_list_count (&desc->activity->eviction_dirty), + active + inactive + + eviction_list_count (&desc->activity->eviction_dirty), + desc->activity->frames_local, + desc->activity, activity, + desc->eviction_candidate, desc->dirty, + o.discardable, policy.discardable, + o.priority, policy.priority); + } if (activity) - assertx (activity->priorities_count - + activity_lru_list_count (&activity->active) - + activity_lru_list_count (&activity->inactive) - + eviction_list_count (&activity->eviction_dirty) - == activity->frames_local, - "%d+%d+%d+%d = %d != %d! (%p=>%p,%d,%d,%d=>%d,%d=>%d)", - activity->priorities_count, - activity_lru_list_count (&activity->active), - activity_lru_list_count (&activity->inactive), - eviction_list_count (&activity->eviction_dirty), - activity->priorities_count - + activity_lru_list_count (&activity->active) - + activity_lru_list_count (&activity->inactive) - + eviction_list_count (&activity->eviction_dirty), - activity->frames_local, - desc->activity, activity, - desc->eviction_candidate, desc->dirty, - o.discardable, policy.discardable, - o.priority, policy.priority); + { + int active = 0; + int inactive = 0; + + int i; + for (i = OBJECT_PRIORITY_MIN; i <= OBJECT_PRIORITY_MAX; i ++) + { + active += activity_list_count (&activity->frames[i].active); + inactive += activity_list_count (&activity->frames[i].inactive); + } + + assertx (active + inactive + + eviction_list_count (&activity->eviction_dirty) + == activity->frames_local, + "%d+%d+%d = %d != %d! (%p=>%p,%d,%d,%d=>%d,%d=>%d)", + active, inactive, + eviction_list_count (&activity->eviction_dirty), + active + inactive + + eviction_list_count (&activity->eviction_dirty), + activity->frames_local, + desc->activity, activity, + desc->eviction_candidate, desc->dirty, + o.discardable, policy.discardable, + o.priority, policy.priority); + } +#endif if (desc->activity == activity && ! desc->eviction_candidate @@ -796,24 +810,11 @@ object_desc_claim (struct activity *activity, struct object_desc *desc, } else { - if (desc->policy.priority != OBJECT_PRIORITY_LRU) - { - hurd_btree_priorities_detach (&desc->activity->priorities, - desc); - desc->activity->priorities_count --; - } - else - { - struct activity_lru_list *list; - if (object_active (desc)) - /* DESC is active. */ - list = &desc->activity->active; - else - /* DESC is inactive. */ - list = &desc->activity->inactive; - - activity_lru_list_unlink (list, desc); - } + activity_list_unlink + (object_active (desc) + ? &desc->activity->frames[desc->policy.priority].active + : &desc->activity->frames[desc->policy.priority].inactive, + desc); if (activity != desc->activity && update_accounting) activity_charge (desc->activity, -1); @@ -855,15 +856,7 @@ object_desc_claim (struct activity *activity, struct object_desc *desc, /* We make the object active. The invariants require that DESC->AGE be non-zero. */ object_age (desc, true); - if (desc->policy.priority != OBJECT_PRIORITY_LRU) - { - void *ret = hurd_btree_priorities_insert (&activity->priorities, - desc); - assert (! ret); - activity->priorities_count ++; - } - else - activity_lru_list_push (&activity->active, desc); + activity_list_push (&activity->frames[desc->policy.priority].active, desc); if ((activity != desc->activity || (desc->eviction_candidate @@ -912,44 +905,58 @@ object_desc_claim (struct activity *activity, struct object_desc *desc, desc->policy.discardable ? "discardable" : "precious"); out: +#ifndef NDEBUG if (desc->activity && update_accounting) - assertx (desc->activity->priorities_count - + activity_lru_list_count (&desc->activity->active) - + activity_lru_list_count (&desc->activity->inactive) - + eviction_list_count (&desc->activity->eviction_dirty) - == desc->activity->frames_local, - "%d+%d+%d+%d = %d != %d (%p=>%p,%d,%d,%d=>%d,%d=>%d)", - desc->activity->priorities_count, - activity_lru_list_count (&desc->activity->active), - activity_lru_list_count (&desc->activity->inactive), - eviction_list_count (&desc->activity->eviction_dirty), - desc->activity->priorities_count - + activity_lru_list_count (&desc->activity->active) - + activity_lru_list_count (&desc->activity->inactive) - + eviction_list_count (&desc->activity->eviction_dirty), - desc->activity->frames_local, - desc->activity, activity, ec, desc->dirty, - o.discardable, policy.discardable, - o.priority, policy.priority); + { + int active = 0; + int inactive = 0; + + int i; + for (i = OBJECT_PRIORITY_MIN; i <= OBJECT_PRIORITY_MAX; i ++) + { + active += activity_list_count (&desc->activity->frames[i].active); + inactive += activity_list_count (&desc->activity->frames[i].inactive); + } + + assertx (active + inactive + + eviction_list_count (&desc->activity->eviction_dirty) + == desc->activity->frames_local, + "%d+%d+%d = %d != %d (%p=>%p,%d,%d,%d=>%d,%d=>%d)", + active, inactive, + eviction_list_count (&desc->activity->eviction_dirty), + active + inactive + + eviction_list_count (&desc->activity->eviction_dirty), + desc->activity->frames_local, + desc->activity, activity, ec, desc->dirty, + o.discardable, policy.discardable, + o.priority, policy.priority); + } if (activity && update_accounting) - assertx (activity->priorities_count - + activity_lru_list_count (&activity->active) - + activity_lru_list_count (&activity->inactive) - + eviction_list_count (&activity->eviction_dirty) - == activity->frames_local, - "%d+%d+%d+%d = %d != %d! (%p=>%p,%d,%d,%d=>%d,%d=>%d)", - activity->priorities_count, - activity_lru_list_count (&activity->active), - activity_lru_list_count (&activity->inactive), - eviction_list_count (&activity->eviction_dirty), - activity->priorities_count - + activity_lru_list_count (&activity->active) - + activity_lru_list_count (&activity->inactive) - + eviction_list_count (&activity->eviction_dirty), - activity->frames_local, - desc->activity, activity, ec, desc->dirty, - o.discardable, policy.discardable, - o.priority, policy.priority); + { + int active = 0; + int inactive = 0; + + int i; + for (i = OBJECT_PRIORITY_MIN; i <= OBJECT_PRIORITY_MAX; i ++) + { + active += activity_list_count (&activity->frames[i].active); + inactive += activity_list_count (&activity->frames[i].inactive); + } + + assertx (active + inactive + + eviction_list_count (&activity->eviction_dirty) + == activity->frames_local, + "%d+%d+%d = %d != %d! (%p=>%p,%d,%d,%d=>%d,%d=>%d)", + active, inactive, + eviction_list_count (&activity->eviction_dirty), + active + inactive + + eviction_list_count (&activity->eviction_dirty), + activity->frames_local, + desc->activity, activity, ec, desc->dirty, + o.discardable, policy.discardable, + o.priority, policy.priority); + } +#endif } /* Return the first waiter queued on object OBJECT. */ diff --git a/viengoos/object.h b/viengoos/object.h index 76540c7..0b212ea 100644 --- a/viengoos/object.h +++ b/viengoos/object.h @@ -168,13 +168,13 @@ struct object_desc union { /* ACTIVITY is valid, EVICTION_CANDIDATE is false, POLICY.PRIORITY - != OBJECT_PRIORITY_LRU. + != OBJECT_PRIORITY_DEFAULT. => attached to ACTIVITY->PRIORITIES. */ hurd_btree_node_t priority_node; /* ACTIVITY is valid, EVICTION_CANDIDATE is false, POLICY.PRIORITY - == OBJECT_PRIORITY_LRU, + == OBJECT_PRIORITY_DEFAULT, => attached to one of ACTIVITY's LRU lists. @@ -245,7 +245,7 @@ extern struct object_desc *object_descs; space; \ }), OID_PRINTF (object_to_object_desc ((__onp))->oid) \ -LIST_CLASS(activity_lru, struct object_desc, activity_node, true) +LIST_CLASS(activity, struct object_desc, activity_node, true) LIST_CLASS(eviction, struct object_desc, activity_node, true) LIST_CLASS(available, struct object_desc, available_node, true) diff --git a/viengoos/pager.c b/viengoos/pager.c index caede94..295ed4f 100644 --- a/viengoos/pager.c +++ b/viengoos/pager.c @@ -73,19 +73,23 @@ reclaim_from (struct activity *victim, int goal) /* XXX: Implement group dealloc. */ - /* First try objects with a priority lower than LRU. */ + int i; +#ifndef NDEBUG + int active = 0; + int inactive = 0; - assertx (victim->priorities_count - + activity_lru_list_count (&victim->active) - + activity_lru_list_count (&victim->inactive) - + eviction_list_count (&victim->eviction_dirty) + for (i = OBJECT_PRIORITY_MIN; i <= OBJECT_PRIORITY_MAX; i ++) + { + active += activity_list_count (&victim->frames[i].active); + inactive += activity_list_count (&victim->frames[i].inactive); + } + + assertx (active + inactive + eviction_list_count (&victim->eviction_dirty) == victim->frames_local, - "%d + %d + %d + %d != %d!", - victim->priorities_count, - activity_lru_list_count (&victim->active), - activity_lru_list_count (&victim->inactive), - eviction_list_count (&victim->eviction_dirty), + "%d + %d + %d != %d!", + active, inactive, eviction_list_count (&victim->eviction_dirty), victim->frames_local); +#endif debug (5, "Reclaiming %d from " OBJECT_NAME_FMT ", %d frames " "(global: avail: %d, laundry: %d)", @@ -93,164 +97,61 @@ reclaim_from (struct activity *victim, int goal) victim->frames_local, available_list_count (&available), laundry_list_count (&laundry)); - struct object_desc *desc; - struct object_desc *next - = hurd_btree_priorities_first (&victim->priorities); - while (((desc = next)) && count < goal) - { - assert (! desc->eviction_candidate); - - assert (desc->policy.priority != OBJECT_PRIORITY_LRU); - if (desc->policy.priority > OBJECT_PRIORITY_LRU) - /* DESC's priority is higher than OBJECT_PRIORITY_LRU, prefer - LRU ordered pages. */ - break; - - next = hurd_btree_priorities_next (desc); - - object_desc_flush (desc, false); - - hurd_btree_priorities_detach (&victim->priorities, desc); - victim->priorities_count --; - - desc->eviction_candidate = true; - - if (desc->dirty && ! desc->policy.discardable) - { - if (! list_node_attached (&desc->laundry_node)) - laundry_list_queue (&laundry, desc); - - eviction_list_queue (&victim->eviction_dirty, desc); - laundry_count ++; - } - else - { - assert (! list_node_attached (&desc->available_node)); - is_clean (desc); - - available_list_queue (&available, desc); - eviction_list_queue (&victim->eviction_clean, desc); - - if (desc->policy.discardable) - discarded ++; - } - - count ++; - } - - if (count < goal) - /* VICTIM still has to yield pages. Start stealing from the - inactive LRU lists. */ - { - struct object_desc *inactive; - - /* For every clean page we steal, we queue a dirty page for - writeout. */ - - inactive = activity_lru_list_head (&victim->inactive); - - struct object_desc *next; - - while (inactive && count < goal) - { - assert (! inactive->eviction_candidate); - assert (! list_node_attached (&inactive->available_node)); - - next = activity_lru_list_next (inactive); - - activity_lru_list_unlink (&victim->inactive, inactive); - - object_desc_flush (inactive, false); - if (inactive->dirty && ! inactive->policy.discardable) - { - eviction_list_push (&victim->eviction_dirty, inactive); - - laundry_list_queue (&laundry, inactive); - laundry_count ++; - } - else - { - is_clean (inactive); - - eviction_list_push (&victim->eviction_clean, inactive); - - available_list_queue (&available, inactive); - - if (desc->policy.discardable) - discarded ++; - } - - inactive->eviction_candidate = true; - - count ++; - - inactive = next; - } - } - - if (count < goal) - /* Still hasn't yielded enough. Steal from the active list. */ + for (i = OBJECT_PRIORITY_MIN; i <= OBJECT_PRIORITY_MAX; i ++) { struct object_desc *desc; - struct object_desc *next = activity_lru_list_head (&victim->active); - - while ((desc = next) && count < goal) + while (count < goal + && (desc = activity_list_head (&victim->frames[i].inactive))) { assert (! desc->eviction_candidate); + assert (! list_node_attached (&desc->available_node)); + assertx (i == desc->policy.priority, + "%d != %d", + i, desc->policy.priority); - next = activity_lru_list_next (desc); + activity_list_unlink (&victim->frames[i].inactive, desc); object_desc_flush (desc, false); - - desc->eviction_candidate = true; - - activity_lru_list_unlink (&victim->active, desc); - if (desc->dirty && ! desc->policy.discardable) { - if (! list_node_attached (&desc->laundry_node)) - laundry_list_queue (&laundry, desc); + eviction_list_push (&victim->eviction_dirty, desc); - eviction_list_queue (&victim->eviction_dirty, desc); + laundry_list_queue (&laundry, desc); laundry_count ++; } else { - assert (! list_node_attached (&desc->available_node)); is_clean (desc); + eviction_list_push (&victim->eviction_clean, desc); + available_list_queue (&available, desc); - eviction_list_queue (&victim->eviction_clean, desc); if (desc->policy.discardable) discarded ++; } + desc->eviction_candidate = true; + count ++; } - } - - if (count < goal) - /* We've cleared the low priority nodes, the inactive LRU lists - and the active LRU list. Steal from the high priority - lists. */ - { - /* NEXT points to the first high priority object descriptor. */ - while (count < goal && (desc = next)) + /* Currently we evict in LIFO order. We should do a semi-sort and + then evict accordingly. */ + while (count < goal + && (desc = activity_list_head (&victim->frames[i].active))) { assert (! desc->eviction_candidate); - assert (desc->policy.priority > OBJECT_PRIORITY_LRU); - - next = hurd_btree_priorities_next (desc); + assertx (i == desc->policy.priority, + "%d != %d", + i, desc->policy.priority); object_desc_flush (desc, false); - hurd_btree_priorities_detach (&victim->priorities, desc); - victim->priorities_count --; - desc->eviction_candidate = true; + activity_list_unlink (&victim->frames[i].active, desc); + if (desc->dirty && ! desc->policy.discardable) { if (! list_node_attached (&desc->laundry_node)) @@ -295,17 +196,22 @@ reclaim_from (struct activity *victim, int goal) zalloc_memory, available_list_count (&available), laundry_list_count (&laundry)); - assertx (victim->priorities_count - + activity_lru_list_count (&victim->active) - + activity_lru_list_count (&victim->inactive) - + eviction_list_count (&victim->eviction_dirty) +#ifndef NDEBUG + active = 0; + inactive = 0; + + for (i = OBJECT_PRIORITY_MIN; i <= OBJECT_PRIORITY_MAX; i ++) + { + active += activity_list_count (&victim->frames[i].active); + inactive += activity_list_count (&victim->frames[i].inactive); + } + + assertx (active + inactive + eviction_list_count (&victim->eviction_dirty) == victim->frames_local, - "%d + %d + %d + %d != %d!", - victim->priorities_count, - activity_lru_list_count (&victim->active), - activity_lru_list_count (&victim->inactive), - eviction_list_count (&victim->eviction_dirty), + "%d + %d + %d != %d!", + active, inactive, eviction_list_count (&victim->eviction_dirty), victim->frames_local); +#endif /* We should never have selected a task from which we can free nothing! */ |