Improve use of alloc()/realloc()/free() to remove allocs and reallocs of size 0
authorNick Downing <nick@ndcode.org>
Sat, 16 Mar 2019 22:27:26 +0000 (09:27 +1100)
committerNick Downing <nick@ndcode.org>
Sat, 16 Mar 2019 22:27:26 +0000 (09:27 +1100)
process.c

index 530445b..8dc0337 100644 (file)
--- a/process.c
+++ b/process.c
@@ -45,13 +45,11 @@ static void check_invariants() {
           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) {
@@ -94,27 +92,33 @@ void process_init(int n, int spare) {
 }
 
 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;
@@ -124,39 +128,44 @@ static void do_swap_out(int swap_out) {
       // 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;
   }
 }
 
@@ -222,7 +231,7 @@ bool process_realloc(struct process *process, int size) {
 }
 
 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
@@ -241,35 +250,57 @@ void process_run(struct process *process) {
     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
@@ -277,26 +308,20 @@ void process_run(struct process *process) {
         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);