assert(avail == process_avail);
// in-core LRU list processes:
- // must have core, can't have swap except the last
- for (
- struct lru_item *p0 = lru_head_core.next;
- p0 != &lru_head_core;
- p0 = p0->next
- ) {
+ // must have core, can't have swap
+ struct lru_item *p0;
#define p ((struct process *)p0)
+ for (p0 = lru_head_core.next; p0 != &lru_head_core; p0 = p0->next) {
assert(p0->prev->next == p0);
assert(p0->next->prev == p0);
assert(p->core_item.prev);
- assert(p->swap_item.prev == NULL || p0->next == &lru_head_core);
-#undef p
+ assert(p->swap_item.prev == NULL);
}
// in-swap LRU list processes:
- // may have swap, can't have core
- for (
- struct lru_item *p0 = lru_head_swap.next;
- p0 != &lru_head_swap;
- p0 = p0->next
- ) {
-#define p ((struct process *)p0)
+ // must have swap, can't have core except the first
+ p0 = lru_head_swap.next;
+ if (p0 != &lru_head_swap) {
assert(p0->prev->next == p0);
assert(p0->next->prev == p0);
- assert(p->core_item.prev == NULL);
-#undef p
+ assert(p->core_item.prev);
+ assert(p->swap_item.prev);
+ for (p0 = p0->next; p0 != &lru_head_swap; p0 = p0->next) {
+ assert(p0->prev->next == p0);
+ assert(p0->next->prev == p0);
+ assert(p->core_item.prev == NULL);
+ assert(p->swap_item.prev);
+ }
}
+#undef p
}
#endif
for (; swap_out > 0; swap_out -= size) {
// choose victim and calculate how much can swap out,
// getting rid of victims that are completely swapped
- goto loop_entry;
- do {
+ victim0 = lru_head_swap.next;
+ if (victim0 == &lru_head_swap)
+ goto no_victim;
+ while ((size = victim->core_item.limit - victim->core_item.base) == 0) {
printf("victimized %d\n", (int)(victim - processes));
- // remove from tail of in-core LRU list
+ // remove from core pool
+ pool_free(&core_head, &victim->core_item);
+ victim->core_item.prev = NULL;
+
+ no_victim:
+ // take new victim from tail of in-core LRU list
+ victim0 = lru_head_core.prev;
+ assert(victim0 != &lru_head_core);
victim0->prev->next = victim0->next;
victim0->next->prev = victim0->prev;
victim0->prev->next = victim0;
victim0->next->prev = victim0;
- // remove from core pool for efficiency
- // note: if zero length it's neither in core nor swap pool
- pool_free(&core_head, &victim->core_item);
- victim->core_item.prev = NULL;
-
- loop_entry:
- // there must be a victim, based on calculations above
- victim0 = lru_head_core.prev;
- assert(victim0 != &lru_head_core);
- size = victim->core_item.limit - victim->core_item.base;
- } while (size == 0);
-
- // if removed from swap pool for efficiency, put back in
- if (victim->swap_item.prev == NULL)
+ // put in swap pool
rassert(pool_alloc_moveable(&swap_head, &victim->swap_item, 0));
+ }
// calculate amount to swap
if (size > swap_out)
void process_run(struct process *process) {
int swap_in, swap_out;
+ struct lru_item *victim0;
+#define victim ((struct process *)victim0)
// must be already allocated
assert(process->lru_item.prev && process->lru_item.next);
+ // note current victim before messing with LRU lists
+ victim0 = lru_head_swap.next;
+
// remove from whichever LRU list it's in
process->lru_item.prev->next = process->lru_item.next;
process->lru_item.next->prev = process->lru_item.prev;
- // insert at head of in-core LRU list
- process->lru_item.prev = &lru_head_core;
- process->lru_item.next = lru_head_core.next;
- process->lru_item.prev->next = &process->lru_item;
- process->lru_item.next->prev = &process->lru_item;
-
- // if removed from core pool for efficiency, put back in
- // note: this can only happen if it came from in-swap LRU list
- if (process->core_item.prev == NULL)
- rassert(pool_alloc_moveable(&core_head, &process->core_item, 0));
-
- // if not in swap pool, then it must be fully in core
- if (process->swap_item.prev == NULL)
- return;
-
- // while not fully in core, make space and bring some in
- while (
- (
- swap_in =
- process->size +
- process->core_item.base -
- process->core_item.limit
- ) != 0
- ) {
- // free up as much core as we can, for this iteration
- swap_out = swap_in - core_head.avail;
- if (swap_out > swap_head.avail) {
- swap_in += swap_head.avail - swap_out;
- swap_out = swap_head.avail;
+ // if in swap pool, may need to swap in
+ if (process->swap_item.prev) {
+ // see if we are the current victim
+ if (victim == process) {
+ // we are already in core pool
+ // if there is a new victim, put it in core pool
+ victim0 = victim0->next;
+ if (victim0 != &lru_head_swap)
+ rassert(pool_alloc_moveable(&core_head, &victim->core_item, 0));
}
- do_swap_out(swap_out);
+ else
+ // put us in core pool
+ rassert(pool_alloc_moveable(&core_head, &process->core_item, 0));
+
+ // while not fully in core, make space and bring some in
+ while (
+ (
+ swap_in =
+ process->size +
+ process->core_item.base -
+ process->core_item.limit
+ ) != 0
+ ) {
+ // free up as much core as we can, for this iteration
+ swap_out = swap_in - core_head.avail;
+ if (swap_out > swap_head.avail) {
+ swap_in += swap_head.avail - swap_out;
+ swap_out = swap_head.avail;
+ }
+ do_swap_out(swap_out);
+
+ // increase core allocation
+ rassert(
+ pool_realloc_moveable(
+ &core_head,
+ &process->core_item,
+ swap_in + process->core_item.limit - process->core_item.base
+ )
+ );
- // increase core allocation
- rassert(
- pool_realloc_moveable(
- &core_head,
- &process->core_item,
- swap_in + process->core_item.limit - process->core_item.base
- )
- );
+ // transfer data to core
+ swap_pop(
+ process->swap_item.limit,
+ process->core_item.limit - swap_in,
+ swap_in
+ );
- // transfer data to core
- swap_pop(
- process->swap_item.limit,
- process->core_item.limit - swap_in,
- swap_in
- );
+ // reduce swap allocation
+ rassert(
+ pool_realloc_moveable(
+ &swap_head,
+ &process->swap_item,
+ process->swap_item.limit - process->swap_item.base - swap_in
+ )
+ );
+ }
- // reduce swap allocation
- rassert(
- pool_realloc_moveable(
- &swap_head,
- &process->swap_item,
- process->swap_item.limit - process->swap_item.base - swap_in
- )
- );
+ // remove from swap pool
+ pool_free(&swap_head, &process->swap_item);
+ process->swap_item.prev = NULL;
}
- // remove from swap pool for efficiency
- pool_free(&swap_head, &process->swap_item);
- process->swap_item.prev = NULL;
+ // insert at head of in-core LRU list
+ process->lru_item.prev = &lru_head_core;
+ process->lru_item.next = lru_head_core.next;
+ process->lru_item.prev->next = &process->lru_item;
+ process->lru_item.next->prev = &process->lru_item;
check_invariants();
+#undef victim
}
void process_free(struct process *process) {
+ struct lru_item *victim0;
+#define victim ((struct process *)victim0)
+
+ check_invariants();
// must be already allocated
assert(process->lru_item.prev && process->lru_item.next);
+ // note current victim before messing with LRU lists
+ victim0 = lru_head_swap.next;
// remove from whichever LRU list it's in
process->lru_item.prev->next = process->lru_item.next;
process->lru_item.next->prev = process->lru_item.prev;
process->lru_item.next = NULL;
#endif
+ // see if we are the current victim
+ if (victim == process) {
+ // if there is a new victim, put it in core pool
+ victim0 = lru_head_swap.next;
+ printf("victim0 %p\n", victim0);
+ if (victim0 != &lru_head_swap)
+ rassert(pool_alloc_moveable(&core_head, &victim->core_item, 0));
+ }
+
// free from core and/or swap pools if there
if (process->core_item.prev)
pool_free(&core_head, &process->core_item);
// track total allocation
process_avail += process->size;
check_invariants();
+#undef victim
}