processes[i].pool_item.prev == NULL &&
processes[i].pool_item.next == NULL
);
- assert(
- processes[i].size ==
- victim_core_item.limit -
- victim_core_item.base +
- victim_swap_item.limit -
- victim_swap_item.base
- );
+ int core_size = victim_core_item.limit - victim_core_item.base;
+ assert(core_size);
+ int swap_size = victim_swap_item.limit - victim_swap_item.base;
+ assert(swap_size);
+ assert(processes[i].size == core_size + swap_size);
}
else {
if (processes[i].lru_item.prev) {
}
static void do_swap_out(int swap_out) {
- int size;
-
- // while can still swap out, choose victim and swap some
- for (; swap_out > 0; swap_out -= size) {
- // choose victim and calculate how much can swap out,
- // getting rid of victims that are completely swapped
- if (victim == NULL)
- goto no_victim;
- while ((size = victim_core_item.limit - victim_core_item.base) == 0) {
- printf("victimized %d\n", (int)(victim - processes));
- // remove from core pool, using dedicated core item
- pool_free(&core_head, &victim_core_item);
-
- // move dedicated to per-process swap item
- pool_move_item(&victim_swap_item, &victim->pool_item);
+ printf("swap_out %d\n", swap_out);
+ int victim_size, size;
+
+ // loop entry code for the case of an existing victim
+ if (swap_out > 0) {
+ if (victim) {
+ // calculate amount to swap
+ victim_size = victim_core_item.limit - victim_core_item.base;
+ size = swap_out < victim_size ? swap_out : victim_size;
+ printf("existing victim %d, swap out %d of %d\n", (int)(victim - processes), size, victim_size);
+
+ // increase swap allocation
+ rassert(
+ pool_realloc_moveable(
+ &swap_head,
+ &victim_swap_item,
+ size + victim_swap_item.limit - victim_swap_item.base
+ )
+ );
+ goto loop_entry;
+ }
- no_victim:
+ // loop for the case of no existing victim
+ do {
// take next least recently used process as victim
assert(lru_head.prev != &lru_head);
victim = (struct process *)lru_head.prev;
- printf("new victim %d\n", (int)(victim - processes));
// remove from LRU list
victim->lru_item.prev->next = victim->lru_item.next;
// move per-process to dedicated core item
pool_move_item(&victim->pool_item, &victim_core_item);
+ // calculate amount to swap
+ victim_size = victim_core_item.limit - victim_core_item.base;
+ size = swap_out < victim_size ? swap_out : victim_size;
+ printf("new victim %d, swap out %d of %d\n", (int)(victim - processes), size, victim_size);
+
// add to swap pool, using dedicated swap item
- rassert(pool_alloc_moveable(&swap_head, &victim_swap_item, 0));
- }
+ rassert(pool_alloc_moveable(&swap_head, &victim_swap_item, size));
+
+ loop_entry:
+ // transfer data to swap
+ swap_write(
+ ~victim_swap_item.limit,
+ victim_core_item.limit - size,
+ size
+ );
+
+ // see if victim fully swapped out
+ victim_size -= size;
+ if (victim_size) {
+ // no, reduce core allocation, using dedicated core item
+ rassert(
+ pool_realloc_moveable(&core_head, &victim_core_item, victim_size)
+ );
+
+ // as an optimization, skip the calculation of swap_out -= size
+ return;
+ }
+
+ printf("victimized %d\n", (int)(victim - processes));
+ // remove from core pool, using dedicated core item
+ pool_free(&core_head, &victim_core_item);
+
+ // move dedicated to per-process swap item
+ pool_move_item(&victim_swap_item, &victim->pool_item);
- // calculate amount to swap
- if (size > swap_out)
- size = swap_out;
- printf("victim %d size %d\n", (int)(victim - processes), size);
-
- // increase swap allocation
- rassert(
- pool_realloc_moveable(
- &swap_head,
- &victim_swap_item,
- size + victim_swap_item.limit - victim_swap_item.base
- )
- );
-
- // transfer data to swap
- swap_write(
- ~victim_swap_item.limit,
- victim_core_item.limit - size,
- size
- );
-
- // reduce core allocation
- rassert(
- pool_realloc_moveable(
- &core_head,
- &victim_core_item,
- victim_core_item.limit - victim_core_item.base - size
- )
- );
+ swap_out -= size;
+ } while (swap_out);
+ victim = NULL;
}
}
}
void process_run(struct process *process) {
- int swap_in, swap_out;
+ int swap_in, size, swap_out;
struct pool_item process_core_item, process_swap_item;
// must be already allocated
memset(&process_core_item, 0, sizeof(process_core_item));
memset(&process_swap_item, 0, sizeof(process_swap_item));
#endif
-
- // see whether victim or fully in swap
- if (process == victim) {
- // victim, take over the dedicated pool items
- victim = NULL;
- pool_move_item(&victim_core_item, &process_core_item);
- pool_move_item(&victim_swap_item, &process_swap_item);
- }
- else {
+
+ // loop entry code for case of fully in swap
+ if (process != victim) {
// fully in swap, take over only the per-process swap item
pool_move_item(&process->pool_item, &process_swap_item);
- rassert(pool_alloc_moveable(&core_head, &process_core_item, 0));
+ swap_in = process_swap_item.limit - process_swap_item.base;
+
+ // calculate amount to swap
+ size = swap_in;
+ swap_out = size - core_head.avail;
+ if (swap_out > swap_head.avail) {
+ size += swap_head.avail - swap_out;
+ swap_out = swap_head.avail;
+ }
+
+ // free up as much core as we can
+ do_swap_out(swap_out);
+
+ // add to core pool, using dedicated core item
+ rassert(pool_alloc_moveable(&core_head, &process_core_item, size));
+ goto loop_entry_full;
}
- // 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;
+ // victim, take over the dedicated pool items
+ victim = NULL;
+ pool_move_item(&victim_core_item, &process_core_item);
+ pool_move_item(&victim_swap_item, &process_swap_item);
+ swap_in = process_swap_item.limit - process_swap_item.base;
+ goto loop_entry_partial;
+
+ // loop for case of partially in core, partially in swap
+ do {
+ // reduce swap allocation
+ rassert(
+ pool_realloc_moveable(
+ &swap_head,
+ &process_swap_item,
+ swap_in
+ )
+ );
+
+ loop_entry_partial:
+ // calculate how much to swap
+ size = swap_in;
+ swap_out = size - core_head.avail;
if (swap_out > swap_head.avail) {
- swap_in += swap_head.avail - swap_out;
+ size += swap_head.avail - swap_out;
swap_out = swap_head.avail;
}
+
+ // free up as much core as we can
do_swap_out(swap_out);
// increase core allocation
pool_realloc_moveable(
&core_head,
&process_core_item,
- swap_in + process_core_item.limit - process_core_item.base
+ process_core_item.limit - process_core_item.base + size
)
);
+ loop_entry_full:
// transfer data to core
swap_read(
~process_swap_item.limit,
- process_core_item.limit - swap_in,
- swap_in
+ process_core_item.limit - size,
+ size
);
- // reduce swap allocation
- rassert(
- pool_realloc_moveable(
- &swap_head,
- &process_swap_item,
- process_swap_item.limit - process_swap_item.base - swap_in
- )
- );
- }
+ swap_in -= size;
+ } while (swap_in);
// move dedicated to per-process core item
pool_move_item(&process_core_item, &process->pool_item);