From: Nick Downing Date: Sun, 5 May 2019 03:31:21 +0000 (+1000) Subject: New combined routine that does all of pool_alloc(), pool_realloc(), pool_realloc_base... X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=771c16f79a779609650706450ad3d1f830c27c17;p=moveable_pool.git New combined routine that does all of pool_alloc(), pool_realloc(), pool_realloc_base() and does the best it can with whatever move()/move_up() routines found --- diff --git a/core.c b/core.c index beb8f86..8d837e2 100644 --- a/core.c +++ b/core.c @@ -192,7 +192,9 @@ bool core_block_alloc(int *table, int size) { core_block_bitmap[j] &= ~bits[k]; core_block_next = (j << 3) | k; +#ifndef NDEBUG // makes us remove the following line in gen.sh as appropriate assert(table[i] == 0x55555555); +#endif table[i] = core_block_next++; if (core_block_next >= n_core_blocks) core_block_next = 0; @@ -214,7 +216,7 @@ void core_block_free(int *table, int size) { core_block_bitmap[j] |= bits[k]; #ifndef NDEBUG table[i] = 0x55555555; -#endif +#endif } core_block_avail += size; diff --git a/gen.sh b/gen.sh index e04fc64..b644249 100755 --- a/gen.sh +++ b/gen.sh @@ -1,5 +1,8 @@ #!/bin/sh -e +# call with -DNDEBUG to generate a release build of the expanded source +# (note that we cannot preserve #ifndef NDEBUG type constructs in output) + sed -e 's/^#define MOVEABLE_POOL 1/\/\/#define MOVEABLE_POOL 1/' -i pool.h # we will only use non-moveable swap, so it must be preallocated, @@ -13,15 +16,15 @@ sed -e 's/^#define MOVEABLE_CORE 1/\/\/#define MOVEABLE_CORE 1/' -i core.h sed -e 's/^#define INODE_SWAP 1/\/\/#define INODE_SWAP 1/' -i process.h sed -e 's/^#define INDIRECT_SWAP 1/\/\/#define INDIRECT_SWAP 1/' -i swap.h -./pp.sh indirect_core_preallocate_swap +./pp.sh indirect_core_preallocate_swap $1 cp rassert.h indirect_core_preallocate_swap sed -e 's/^\/\/#define INDIRECT_SWAP 1/#define INDIRECT_SWAP 1/' -i swap.h -./pp.sh indirect_core_indirect_swap +./pp.sh indirect_core_indirect_swap $1 cp rassert.h indirect_core_indirect_swap sed -e 's/^\/\/#define INODE_SWAP 1/#define INODE_SWAP 1/' -i process.h -./pp.sh indirect_core_inode_swap +./pp.sh indirect_core_inode_swap $1 rm indirect_core_inode_swap/swap.[ch] cp rassert.h fuzix_fs.[ch] util.[ch] indirect_core_inode_swap @@ -33,14 +36,14 @@ sed -e 's/^\/\/#define MOVEABLE_CORE 1/#define MOVEABLE_CORE 1/' -i core.h sed -e 's/^#define INODE_SWAP 1/\/\/#define INODE_SWAP 1/' -i process.h sed -e 's/^#define INDIRECT_SWAP 1/\/\/#define INDIRECT_SWAP 1/' -i swap.h -./pp.sh moveable_core_preallocate_swap +./pp.sh moveable_core_preallocate_swap $1 cp rassert.h moveable_core_preallocate_swap sed -e 's/^\/\/#define INDIRECT_SWAP 1/#define INDIRECT_SWAP 1/' -i swap.h -./pp.sh moveable_core_indirect_swap +./pp.sh moveable_core_indirect_swap $1 cp rassert.h moveable_core_indirect_swap sed -e 's/^\/\/#define INODE_SWAP 1/#define INODE_SWAP 1/' -i process.h -./pp.sh moveable_core_inode_swap +./pp.sh moveable_core_inode_swap $1 rm moveable_core_inode_swap/swap.[ch] cp rassert.h fuzix_fs.[ch] util.[ch] moveable_core_inode_swap diff --git a/n.sh b/n.sh index 18ad7bb..8609ed8 100755 --- a/n.sh +++ b/n.sh @@ -6,5 +6,11 @@ echo "generate test script" #echo "run test script, non-moveable" #./pool_test_run 64 256 -#include #include // temporary #include #include "pool.h" @@ -8,7 +7,7 @@ #define MOVEABLE_POOL 1 #define TRY_BLOCKER 1 -#if 1 +#ifndef NDEBUG void check_invariants(struct pool_head *head) { int avail; struct pool_item *p; @@ -37,551 +36,307 @@ void pool_init( head->avail = limit - base; head->move = move; head->move_up = move_up; +#ifndef NDEBUG check_invariants(head); -} - -bool pool_alloc( - struct pool_head *head, - struct pool_item *item, - int size -) { - struct pool_item *p, *q; - int avail, gap; - - // item must not be allocated yet - assert(item->prev == NULL && item->next == NULL); - - // check size, disregarding fragmentation - avail = head->avail - size; - if (avail < 0) - return false; - - // first-fit algorithm - q = &head->item; - while (true) { - p = q; - q = p->next; - - // calculate gap at current position - gap = q->base - p->limit; - //printf("p %p q %p gap %d\n", p, q, gap); - - // see if request fits in gap - if (size <= gap) - goto found; - - // see if gap can be left alone - avail -= gap; - if (avail < 0) { -#ifdef MOVEABLE_POOL - // move block after gap down into gap - if (head->move == NULL || head->move_up == NULL) - return false; - avail += gap; - - head->move(q, p->limit); - q->limit += p->limit - q->base; - q->base = p->limit; -#else - return false; #endif - } - - assert(q != &head->item); - } - -found: - item->base = p->limit; - item->limit = p->limit + size; - - // insert into list at found position - item->prev = p; - p->next = item; - item->next = q; - q->prev = item; - - // keep track of total allocation - head->avail -= size; - check_invariants(head); - return true; } - + bool pool_realloc( struct pool_head *head, struct pool_item *item, - int size + int size, + int offset, + bool dir ) { - struct pool_item *p, *q; + int old_size, new_base, new_limit; + int end_offset; int size_change, avail, gap; + bool orig_dir; + struct pool_item *p, *q; #ifdef TRY_BLOCKER - struct pool_item *blocker; - int blocker_size; + struct pool_item *r, *target_item; + int target_size; + bool prev_next; #endif -#ifdef MOVEABLE_POOL - int avail_save; -#endif - - // item must be already allocated - assert(item->prev && item->next); - - // realloc requires at least the move-down routine - // (even though some requests succeed without move) - assert(head->move); - - // try to change current block size without copying - size_change = size + item->base - item->limit; + int old_base_truncated, new_base_offset; + int old_limit_truncated, new_limit_offset; + + // see if request is for "alloc" or "realloc" + old_size = 0; + if (offset != INT_MIN) { + // realloc, item must be already allocated + assert(item->prev && item->next); + old_size = item->limit - item->base; + + // calculate new spot if block is extended not moved + new_base = item->base - offset; + new_limit = new_base + size; #ifndef TRY_BLOCKER - if (item->base + size <= item->next->base) - goto resize; + if (new_base >= item->prev->limit && new_limit <= item->next->base) + goto resize; +#endif + } +#ifndef NDEBUG + else { + // alloc, item must not be already allocated + assert(item->prev == NULL && item->next == NULL); + } #endif // check size, disregarding fragmentation + size_change = size - old_size; avail = head->avail - size_change; if (avail < 0) return false; - // first-fit algorithm, until our own list entry - q = &head->item; - -#ifdef TRY_BLOCKER -blocker_test: - // enter here when blocker has changed - blocker = item->next; - - // see if we fit, given the new blocker - if (item->base + size <= blocker->base) - goto resize; - - // otherwise, see if blocker is moveable - blocker_size = - blocker == &head->item ? INT_MAX : blocker->limit - blocker->base; -#endif - + // work in specified direction, then reverse + orig_dir = dir; while (true) { - p = q; - q = p->next; - if (q == item) - break; - - // calculate gap at current position - gap = q->base - p->limit; - - // see if request fits in gap - if (size <= gap) - goto found; + p = &head->item; + q = &head->item; #ifdef TRY_BLOCKER - // see if blocker fits in gap - if (blocker_size <= gap && head->move_up) { - // move blocker down into gap - head->move(blocker, p->limit); - blocker->limit += p->limit - blocker->base; - blocker->base = p->limit; - - // remove from list - blocker->prev->next = blocker->next; - blocker->next->prev = blocker->prev; - - // insert into list at gap position - blocker->prev = p; - p->next = blocker; - blocker->next = q; - q->prev = blocker; - - // calculate new blocker - q = blocker; - goto blocker_test; - } -#endif - - // see if gap can be left alone - avail -= gap; - if (avail < 0) { - // move block after gap down into gap - if (head->move_up == NULL) - return false; - avail += gap; - - head->move(q, p->limit); - q->limit += p->limit - q->base; - q->base = p->limit; - } - - assert(q != &head->item); - } - -#ifdef MOVEABLE_POOL - // optional step: try an ordinary realloc in rest of list - // this is because if the pool consists of a tightly packed region - // followed by a mainly free region, it's best to move us to there - avail_save = avail; -#endif - - // first-fit algorithm, including and after our own list entry, - // the first iteration (ours) is different because q != p->next, - // this causes us to ignore our own entry in the gap calculation - q = q->next; - goto loop_entry; - do { - p = q; - q = p->next; - loop_entry: - gap = q->base - p->limit; - if (size <= gap) - goto found; - if (q == &head->item) - break; - avail -= gap; - } while (avail >= 0); -#ifdef MOVEABLE_POOL - if (head->move_up == NULL) - return false; - - avail = avail_save; - p = item->prev; - - // calculate gap that would be left if we didn't move ourself - gap = item->base - p->limit; - - // see if gap can be left alone - avail -= gap; - if (avail < 0) { - // move block after gap (ourself) down into gap - avail += gap; - - head->move(item, p->limit); - item->limit += p->limit - item->base; - item->base = p->limit; - - // if didn't do ordinary realloc above, see if we now fit - //if (item->base + size <= item->next->base) - // goto resize; - } - - // at this point we will not move our own block anymore (because - // a last-fit approach is risky, given the likelihood that we will - // soon want to resize again), compact the remainder down from top - p = &head->item; - while (true) { - q = p; - p = q->prev; - if (p == item) { - assert(item->base + size <= item->next->base); - goto resize; - } - - // calculate gap at current position - gap = q->base - p->limit; - -#ifdef TRY_BLOCKER - // see if blocker fits in gap - if (blocker_size <= gap && blocker != p) { - // if moveable realloc is used, then user must provide move_up routine - assert(head->move_up); - head->move_up(blocker, q->base); - blocker->base += q->base - blocker->limit; - blocker->limit = q->base; - - // remove from list - blocker->prev->next = blocker->next; - blocker->next->prev = blocker->prev; - - // insert into list at gap position - blocker->prev = p; - p->next = blocker; - blocker->next = q; - q->prev = blocker; - - // calculate new blocker - p = blocker; - blocker = item->next; - - // see if we fit, given the new blocker - if (item->base + size <= blocker->base) +blocker_test: + // enter here when either blocker has changed + target_item = item; + target_size = size; + //printf("a target_size %d\n", target_size); + if (offset != INT_MIN) { + if (new_base >= item->prev->limit && new_limit <= item->next->base) goto resize; - // otherwise, see if blocker is moveable - blocker_size = - blocker == &head->item ? INT_MAX : blocker->limit - blocker->base; - continue; + r = item->prev; + prev_next = false; + do { + if (new_base < r->limit && r != &head->item) { + gap = r->limit - r->base; + if (gap < target_size) { + target_item = r; + target_size = gap; + //printf("b target_size %d\n", target_size); + } + } + r = item->next; + prev_next = !prev_next; + } while (prev_next); } #endif - // if gap too large, move block before gap up into gap - avail -= gap; - if (avail < 0) { - avail += gap; - - // if moveable realloc is used, user must provide move_up routine - assert(head->move_up); - head->move_up(p, q->base); - p->base += q->base - p->limit; - p->limit = q->base; - } - - assert(p != &head->item); - } + while (true) { + //printf("avail %d\n", avail); + // advance, so that p, q are before/after gap + if (!dir) { + p = q; + q = p->next; +//#ifdef TRY_BLOCKER +// if (q == item || q == target_item) { +//#else + if (q == item) { +//#endif + q = q->next; + break; + } + //printf("forw %p(%d)->%p(%d)\n", p, p->limit, q, q->base); + } + else { + q = p; + p = q->prev; +//#ifdef TRY_BLOCKER +// if (p == item || p == target_item) { +//#else + if (p == item) { +//#endif + p = p->prev; + break; + } + //printf("back %p(%d)->%p(%d)\n", p, p->limit, q, q->base); + } + + // see if target fits in current gap + gap = q->base - p->limit; +#ifdef TRY_BLOCKER + if (target_size <= gap) { + //printf("target\n"); + if (target_item == item) + goto found; + if (!dir) { + if (!head->move) + goto no_blocker; + head->move(target_item, p->limit); + target_item->limit += p->limit - target_item->base; + target_item->base = p->limit; + } + else { + if (!head->move_up) + goto no_blocker; + head->move_up(target_item, q->base); + target_item->base += q->base - target_item->limit; + target_item->limit = q->base; + } + + // remove from list + target_item->prev->next = target_item->next; + target_item->next->prev = target_item->prev; + if (!dir) + q = p->next; + else + p = q->prev; + + // insert into list at found position + target_item->prev = p; + p->next = target_item; + target_item->next = q; + q->prev = target_item; + + p = target_item; + q = target_item; + goto blocker_test; + + no_blocker: + ; + } #else - return false; + if (size <= gap) + goto found; #endif -found: - // move ourself into found spot, always non-overlapping or downwards - assert(head->move); - head->move(item, p->limit); - //item->limit += p->limit - item->base; - item->base = p->limit; - - // remove from list - item->prev->next = item->next; - item->next->prev = item->prev; - - // insert into list at found position - item->prev = p; - p->next = item; - item->next = q; - q->prev = item; - -resize: - // resize in place (or do the commented code above if moved ourself) - item->limit = item->base + size; - - // keep track of total allocation - head->avail -= size_change; - check_invariants(head); - return true; -} - -bool pool_realloc_base( - struct pool_head *head, - struct pool_item *item, - int size -) { - struct pool_item *p, *q; - int size_change, avail, gap; -#ifdef TRY_BLOCKER - struct pool_item *blocker; - int blocker_size; -#endif + // see if gap can be left alone + avail -= gap; + if (avail < 0) { #ifdef MOVEABLE_POOL - int avail_save; + //printf("compact\n"); + if (!dir) { + if (!head->move) +#ifndef NDEBUG + { + check_invariants(head); #endif - - // item must be already allocated - assert(item->prev && item->next); - - // realloc_base requires at least the move-up routine - // (even though some requests succeed without move) - assert(head->move_up); - - // try to change current block size without copying - size_change = size + item->base - item->limit; -#ifndef TRY_BLOCKER - if (item->limit - size >= item->prev->limit) - goto resize; + return false; +#ifndef NDEBUG + } #endif - - // check size, disregarding fragmentation - avail = head->avail - size_change; - if (avail < 0) - return false; - - // last-fit algorithm, until our own list entry - p = &head->item; - -#ifdef TRY_BLOCKER -blocker_test: - // enter here when blocker has changed - blocker = item->prev; - - // see if we fit, given the new blocker - if (item->limit - size >= blocker->limit) - goto resize; - - // otherwise, see if blocker is moveable - blocker_size = - blocker == &head->item ? INT_MAX : blocker->limit - blocker->base; + head->move(q, p->limit); + q->limit += p->limit - q->base; + q->base = p->limit; + } + else { + if (!head->move_up) +#ifndef NDEBUG + { + check_invariants(head); #endif - - while (true) { - q = p; - p = q->prev; - if (p == item) - break; - - // calculate gap at current position - gap = q->base - p->limit; - - // see if request fits in gap - if (size <= gap) - goto found; - -#ifdef TRY_BLOCKER - // see if blocker fits in gap - if (blocker_size <= gap && head->move) { - // move blocker up into gap - head->move_up(blocker, q->base); - blocker->base += q->base - blocker->limit; - blocker->limit = q->base; - - // remove from list - blocker->prev->next = blocker->next; - blocker->next->prev = blocker->prev; - - // insert into list at gap position - blocker->prev = p; - p->next = blocker; - blocker->next = q; - q->prev = blocker; - - // calculate new blocker - p = blocker; - goto blocker_test; - } + return false; +#ifndef NDEBUG + } #endif - - // see if gap can be left alone - avail -= gap; - if (avail < 0) { - // move block before gap up into gap - if (head->move == NULL) + head->move_up(p, q->base); + p->base += q->base - p->limit; + p->limit = q->base; + } + avail += gap; + + // if we have just moved the target, then the target is + // no longer valid and we should go to blocker_test, but + // the loop is about to terminate anyway => don't bother +#else return false; - - avail += gap; +#endif + } - head->move_up(p, q->base); - p->base += q->base - p->limit; - p->limit = q->base; + assert((dir ? p : q) != &head->item); } + //printf("done %p(%d)->%p(%d)\n", p, p->limit, q, q->base); - assert(p != &head->item); - } - -#ifdef MOVEABLE_POOL - // optional step: try an ordinary realloc in rest of list - // this is because if the pool consists of a tightly packed region - // preceded by a mainly free region, it's best to move us to there - avail_save = avail; -#endif - - // last-fit algorithm, including and before our own list entry, - // the first iteration (ours) is different because p != q->prev, - // this causes us to ignore our own entry in the gap calculation - p = p->prev; - goto loop_entry; - do { - q = p; - p = q->prev; - loop_entry: + // have compacted up from bottom and reached our item, + // or compacted down from top and reached our item + // (test is slightly different here, as we will ignore + // our item for the purpose of calculating the gap) gap = q->base - p->limit; if (size <= gap) goto found; - if (p == &head->item) - break; - avail -= gap; - } while (avail >= 0); -#ifdef MOVEABLE_POOL - if (head->move == NULL) - return false; - - avail = avail_save; - q = item->next; - - // calculate gap that would be left if we didn't move ourself - gap = q->base - item->limit; - - // see if gap can be left alone - avail -= gap; - if (avail < 0) { - // move block before gap (ourself) up into gap - avail += gap; - head->move_up(item, q->base); - item->base += q->base - item->limit; - item->limit = q->base; - - // if didn't do ordinary realloc above, see if we now fit - //if (item->limit - size >= item->prev->limit) - // goto resize; + dir = !dir; + //printf("dir changed to %d\n", dir); + assert(dir != orig_dir); } - // at this point we will not move our own block anymore (because - // a first-fit approach is risky, given the likelihood that we will - // soon want to resize again), compact the remainder up from bottom - q = &head->item; - while (true) { - p = q; - q = p->next; - if (q == item) { - assert(item->limit - size >= item->prev->limit); - goto resize; - } - - // calculate gap at current position - gap = q->base - p->limit; - -#ifdef TRY_BLOCKER - // see if blocker fits in gap - if (blocker_size <= gap && blocker != q) { - // if moveable realloc is used, then user must provide move routine - assert(head->move); - head->move(blocker, p->limit); - blocker->limit += p->limit - blocker->base; - blocker->base = p->limit; - - // remove from list - blocker->prev->next = blocker->next; - blocker->next->prev = blocker->prev; - - // insert into list at gap position - blocker->prev = p; - p->next = blocker; - blocker->next = q; - q->prev = blocker; - - // calculate new blocker - q = blocker; - blocker = item->prev; - - // see if we fit, given the new blocker - if (item->limit - size >= blocker->limit) - goto resize; +found: + //printf("found\n"); + // align ourself in found spot + // (try to allow future extension in desired direction) + if (orig_dir == false) { + new_base = p->limit; + new_limit = new_base + size; + } + else { + new_limit = q->base; + new_base = new_limit - size; + } - // otherwise, see if blocker is moveable - blocker_size = - blocker == &head->item ? INT_MAX : blocker->limit - blocker->base; - continue; + if (offset != INT_MIN) { + // move ourself into found spot + + // we have "offset", which is position of start of existing data + // relative to start of new block, now calculate symmetric one: + // position of end of existing data relative to end of new block + // (new_limit + end_offset) - (new_base + offset) = old_size + // (new_limit - new_base) + (end_offset - offset) = old_size + // size + end_offset - offset = old_size + // end_offset = offset - (size - old_size) + end_offset = offset - size_change; + + old_base_truncated = item->base; + new_base_offset = new_base; + if (offset < 0) + // copy truncated start of old block to base of new block + old_base_truncated -= offset; + else + // copy original start of old block to offset in new block + new_base_offset += offset; + + old_limit_truncated = item->limit; + new_limit_offset = new_limit; + if (end_offset >= 0) + // copy truncated end of old block to limit of new block + old_limit_truncated -= end_offset; + else + // copy original end of old block to offset in new block + new_limit_offset += end_offset; + + offset = new_base_offset - old_base_truncated; // amount to move by + if (offset < 0) { + if (!head->move) +#ifndef NDEBUG + { + check_invariants(head); +#endif + return false; +#ifndef NDEBUG + } +#endif + item->base = old_base_truncated; + item->limit = old_limit_truncated; + head->move(item, new_base_offset); } + else if (offset > 0) { + if (!head->move_up) +#ifndef NDEBUG + { + check_invariants(head); #endif - - // if gap too large, move block after gap down into gap - avail -= gap; - if (avail < 0) { - avail += gap; - - // if moveable realloc is used, user must provide move routine - assert(head->move); - head->move(q, p->limit); - q->limit += p->limit - q->base; - q->base = p->limit; + return false; +#ifndef NDEBUG + } +#endif + item->base = old_base_truncated; + item->limit = old_limit_truncated; + head->move_up(item, new_limit_offset); } - assert(q != &head->item); + // remove from list + item->prev->next = item->next; + item->next->prev = item->prev; } -#else - return false; -#endif - -found: - // move ourself into found spot, always non-overlapping or downwards - assert(head->move_up); - head->move_up(item, q->base); - //item->base += q->base - item->limit; - item->limit = q->base; - - // remove from list - item->prev->next = item->next; - item->next->prev = item->prev; // insert into list at found position item->prev = p; @@ -590,12 +345,16 @@ found: q->prev = item; resize: - // resize in place (or do the commented code above if moved ourself) - item->base = item->limit - size; + //printf("fits %p(%d)->%p(%d) [%d,%d)\n", item->prev, item->prev->limit, item->next, item->next->base, new_base, new_limit); + // resize in place + item->base = new_base; + item->limit = new_limit; // keep track of total allocation head->avail -= size_change; +#ifndef NDEBUG check_invariants(head); +#endif return true; } @@ -613,5 +372,7 @@ void pool_free(struct pool_head *head, struct pool_item *item) { // keep track of total allocation head->avail += item->limit - item->base; +#ifndef NDEBUG check_invariants(head); +#endif } diff --git a/pool.h b/pool.h index 7d59675..8561feb 100644 --- a/pool.h +++ b/pool.h @@ -1,6 +1,7 @@ #ifndef _POOL_H #define _POOL_H 1 +#include #include struct pool_item { @@ -17,6 +18,9 @@ struct pool_head { void (*move_up)(struct pool_item *item, int new_limit); }; +#define pool_alloc(head, item, size, dir) \ + pool_realloc(head, item, size, INT_MIN, dir) + void pool_init( struct pool_head *head, int base, @@ -24,20 +28,12 @@ void pool_init( void (*move)(struct pool_item *item, int new_base), void (*move_up)(struct pool_item *item, int new_limit) ); -bool pool_alloc( - struct pool_head *head, - struct pool_item *item, - int size -); bool pool_realloc( struct pool_head *head, struct pool_item *item, - int size -); -bool pool_realloc_base( - struct pool_head *head, - struct pool_item *item, - int size + int size, + int offset, + bool dir ); void pool_free(struct pool_head *head, struct pool_item *item); diff --git a/pool_test_run.c b/pool_test_run.c index 37d069f..fef6a75 100644 --- a/pool_test_run.c +++ b/pool_test_run.c @@ -26,7 +26,6 @@ void move(struct pool_item *item, int new_base) { void move_up(struct pool_item *item, int new_limit) { int limit = item->limit; - assert(limit != new_limit); int neg_size = item->base - limit; printf( "move_up [%d,%d) to [%d,%d)\n", @@ -69,10 +68,18 @@ int main(int argc, char **argv) { } int n_items = atoi(argv[1]); int pool_size = atoi(argv[2]); - bool moveable = argc >= 4 ? strcmp(argv[3], "false") != 0 : false; + bool dir = argc >= 4 ? strcmp(argv[3], "false") != 0 : false; + bool moveable = argc >= 5 ? strcmp(argv[4], "false") != 0 : false; + printf("dir %d moveable %d\n", dir, moveable); struct pool_head head; - pool_init(&head, 0, pool_size, move, moveable ? move_up : NULL); + pool_init( + &head, + 0, + pool_size, + moveable || !dir ? move : NULL, + moveable || dir ? move_up : NULL + ); struct pool_item *items = malloc(n_items * sizeof(struct pool_item)); rassert(items); @@ -111,7 +118,7 @@ int main(int argc, char **argv) { success ? "true" : "false" ); rassert(items[item].prev == NULL); - bool result = pool_alloc(&head, items + item, size); + bool result = pool_alloc(&head, items + item, size, dir); printf( "... %s\n", result == success ? @@ -172,7 +179,7 @@ int main(int argc, char **argv) { actual_old_size - size, size ); - bool result = pool_realloc(&head, items + item, size); + bool result = pool_realloc(&head, items + item, size, 0, dir); printf( "... %s\n", result == success ? @@ -182,7 +189,7 @@ int main(int argc, char **argv) { if (result) { if (!success) { printf("... undo\n"); - rassert(pool_realloc(&head, items + item, actual_old_size)); + rassert(pool_realloc(&head, items + item, actual_old_size, 0, dir)); } else { base = items[item].base; @@ -233,7 +240,13 @@ int main(int argc, char **argv) { } printf("old region [%d,%d)\n", base, base + actual_old_size); hash_verify(item, base, actual_old_size - size, 0); - bool result = pool_realloc_base(&head, items + item, size); + bool result = pool_realloc( + &head, + items + item, + size, + size - actual_old_size, + !dir + ); printf( "... %s\n", result == success ? @@ -243,7 +256,15 @@ int main(int argc, char **argv) { if (result) { if (!success) { printf("... undo\n"); - rassert(pool_realloc_base(&head, items + item, actual_old_size)); + rassert( + pool_realloc( + &head, + items + item, + actual_old_size, + actual_old_size - size, + !dir + ) + ); } else { base = items[item].base; diff --git a/pp.sh b/pp.sh index 2c06480..10ea60a 100755 --- a/pp.sh +++ b/pp.sh @@ -13,7 +13,7 @@ swap.c \ swap.h do (echo END; sed -e "/\\\\$/{s/.\\n//; N}; s/^\\/\\/#define .*//; s/\\/\\/.*/\"&\"/; s/^\\(#.*\\)\"\\(\\/\\/.*\\)\"$/\\1\\2/; s/^#.*/BEGIN '&'\\n&\\nEND/" <$i; echo BEGIN) >a.c - gcc -E a.c |sed -ne "/^END/,/^BEGIN/{s/\"\\(\\/\\/.*\\)\"$/\\1/; s/^BEGIN '\\(#include .*\\)'$/\\1/; p}" |grep -v '^\(BEGIN\|END\)' |./blank.py >$1/$i + gcc $2 -E a.c |sed -ne "/^END/,/^BEGIN/{s/\"\\(\\/\\/.*\\)\"$/\\1/; s/^BEGIN '\\(#include .*\\)'$/\\1/; p}" |grep -v '^\(BEGIN\|END\)' |./blank.py >$1/$i done sed -e 's/^\$/#/' -i *.[ch] $1/*.[ch] for i in $1/*.h diff --git a/process.c b/process.c index 9461fbb..b9ffefb 100644 --- a/process.c +++ b/process.c @@ -172,7 +172,13 @@ static bool do_swap_out(int swap_out) { #endif #if !defined(INODE_SWAP) && !defined(PREALLOCATE_SWAP) rassert( - pool_realloc(&swap_table, &victim->swap_item, victim_swap_blocks + blocks) + pool_realloc( + &swap_table, + &victim->swap_item, + victim_swap_blocks + blocks, + 0, + false + ) ); #endif goto loop_entry; @@ -207,7 +213,7 @@ static bool do_swap_out(int swap_out) { // add to swap pool victim_swap_blocks = 0; #if !defined(INODE_SWAP) && !defined(PREALLOCATE_SWAP) - rassert(pool_alloc(&swap_table, &victim->swap_item, blocks)); + rassert(pool_alloc(&swap_table, &victim->swap_item, blocks, false)); #endif // remove from LRU list @@ -338,7 +344,13 @@ static bool do_swap_out(int swap_out) { #ifndef PREALLOCATE_CORE // no, reduce core allocation rassert( - pool_realloc_base(&core_table, &victim->core_item, victim_core_blocks) + pool_realloc( + &core_table, + &victim->core_item, + victim_core_blocks, + -blocks, + true + ) ); #endif @@ -397,7 +409,7 @@ bool process_alloc(struct process *process, long size) { if ( process_avail < blocks #if defined(PREALLOCATE_SWAP) && !defined(MOVEABLE_SWAP) - || !pool_alloc(&swap_table, &process->swap_item, blocks) + || !pool_alloc(&swap_table, &process->swap_item, blocks, false) #endif ) return false; @@ -408,9 +420,9 @@ bool process_alloc(struct process *process, long size) { // allocate core and possible swap #ifdef MOVEABLE_CORE - rassert(pool_alloc(&core_table, &process->core_item, blocks)); + rassert(pool_alloc(&core_table, &process->core_item, blocks, false)); #else - if (!pool_alloc(&core_table, &process->core_item, blocks)) { + if (!pool_alloc(&core_table, &process->core_item, blocks, false)) { #ifdef INODE_SWAP //printf("deref inode %d\n", process->swap_inode->c_num); i_deref(process->swap_inode); @@ -421,7 +433,7 @@ bool process_alloc(struct process *process, long size) { } #endif #if defined(PREALLOCATE_SWAP) && defined(MOVEABLE_SWAP) - rassert(pool_alloc(&swap_table, &process->swap_item, blocks)); + rassert(pool_alloc(&swap_table, &process->swap_item, blocks, false)); #endif #ifdef INDIRECT_CORE @@ -483,8 +495,8 @@ bool process_realloc(struct process *process, long size) { #if defined(PREALLOCATE_SWAP) && !defined(MOVEABLE_SWAP) pool_free(&swap_table, &process->swap_item); - if (!pool_alloc(&swap_table, &process->swap_item, blocks)) { - rassert(pool_alloc(&swap_table, &process->swap_item, old_blocks)); + if (!pool_alloc(&swap_table, &process->swap_item, blocks, false)) { + rassert(pool_alloc(&swap_table, &process->swap_item, old_blocks, false)); return false; } #endif @@ -494,19 +506,19 @@ bool process_realloc(struct process *process, long size) { // reallocate core and possible swap #ifdef MOVEABLE_CORE - rassert(pool_realloc(&core_table, &process->core_item, blocks)); + rassert(pool_realloc(&core_table, &process->core_item, blocks, 0, false)); #else - if (!pool_realloc(&core_table, &process->core_item, blocks)) { + if (!pool_realloc(&core_table, &process->core_item, blocks, 0, false)) { #if defined(PREALLOCATE_SWAP) && !defined(MOVEABLE_SWAP) pool_free(&swap_table, &process->swap_item); - rassert(pool_alloc(&swap_table, &process->swap_item, old_blocks)); + rassert(pool_alloc(&swap_table, &process->swap_item, old_blocks, false)); #endif return false; } #endif #if defined(PREALLOCATE_SWAP) && defined(MOVEABLE_SWAP) pool_free(&swap_table, &process->swap_item); - rassert(pool_alloc(&swap_table, &process->swap_item, blocks)); + rassert(pool_alloc(&swap_table, &process->swap_item, blocks, false)); #endif #ifdef INDIRECT_CORE @@ -582,7 +594,7 @@ void process_run(struct process *process) { // add to core pool process_core_blocks = 0; #ifndef PREALLOCATE_CORE - rassert(pool_alloc(&core_table, &process->core_item, blocks)); + rassert(pool_alloc(&core_table, &process->core_item, blocks, false)); #endif goto loop_entry_full; } @@ -617,7 +629,14 @@ void process_run(struct process *process) { udata.u_offset = (long)process_swap_blocks << BLOCK_SHIFT; f_trunc(process->swap_inode); #else - rassert(pool_realloc(&swap_table, &process->swap_item, process_swap_blocks)); + rassert( + pool_realloc( + &swap_table, + &process->swap_item, + process_swap_blocks, + false + ) + ); #endif loop_entry_partial: @@ -631,9 +650,12 @@ void process_run(struct process *process) { // increase core allocation #ifndef PREALLOCATE_CORE rassert( - pool_realloc_base(&core_table, + pool_realloc( + &core_table, &process->core_item, - process_core_blocks + blocks + process_core_blocks + blocks, + blocks, + true ) ); #endif diff --git a/process_test_run.c b/process_test_run.c index d498169..b193c80 100644 --- a/process_test_run.c +++ b/process_test_run.c @@ -38,7 +38,7 @@ void core_hash_init(int process, long base, long size, long offset) { hash = (hash & 0xffffLL) + (hash >> 16); hash = (hash & 0xffLL) + (hash >> 8); hash = (hash & 0xffLL) + (hash >> 8); - assert(core_block_mem[addr] == 0xaa); + rassert(core_block_mem[addr] == 0xaa); core_block_mem[addr] = (uint8_t)hash; } } @@ -61,9 +61,7 @@ void core_hash_verify(int process, long base, long size, long offset) { hash = (hash & 0xffLL) + (hash >> 8); hash = (hash & 0xffLL) + (hash >> 8); rassert(core_block_mem[addr] == (uint8_t)hash); -#ifndef NDEBUG core_block_mem[addr] = 0xaa; -#endif } } @@ -117,9 +115,7 @@ void swap_hash_verify(int process, long base, long size) { hash = (hash & 0xffLL) + (hash >> 8); hash = (hash & 0xffLL) + (hash >> 8); rassert(swap_block_mem[addr] == (uint8_t)hash); -#ifndef NDEBUG swap_block_mem[addr] = 0xaa; -#endif } } #endif @@ -131,9 +127,7 @@ void core_copy(long src_base, long dest_base, long size) { //printf("core_copy %ld(%d) %ld(%d) %ld(%d)\n", src_base, (int)(src_base >> BLOCK_SHIFT), dest_base, (int)(dest_base >> BLOCK_SHIFT), size, (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT)); for (i = 0L; i < size; ++i) { core_block_mem[dest_base + i] = core_block_mem[src_base + i]; -#ifndef NDEBUG core_block_mem[src_base + i] = 0xaa; -#endif } } @@ -144,9 +138,7 @@ void core_copy_up(long src_limit, long dest_limit, long size) { size = -size; for (i = -1L; i >= size; --i) { core_block_mem[dest_limit + i] = core_block_mem[src_limit + i]; -#ifndef NDEBUG core_block_mem[src_limit + i] = 0xaa; -#endif } } #endif @@ -161,10 +153,8 @@ void swap_read( long i, count; //printf("swap_read %d %ld %ld %ld\n", inode->c_num, offset, core_base, size); -#ifndef NDEBUG for (i = 0; i < size; ++i) - assert(core_block_mem[core_base + i] == 0xaa); -#endif + rassert(core_block_mem[core_base + i] == 0xaa); for (i = 0; (count = size - i) > 0; i += count) { if (count > TRANSFER_SIZE) @@ -198,9 +188,7 @@ void swap_write( rassert(writei(inode) == (int)count && udata.u_error == 0); } -#ifndef NDEBUG memset(core_block_mem + core_base, 0xaa, size); -#endif } #else #ifndef INDIRECT_SWAP @@ -210,9 +198,7 @@ void swap_copy(long src_base, long dest_base, long size) { //printf("swap_copy %ld(%d) %ld(%d) %ld(%d)\n", src_base, (int)(src_base >> BLOCK_SHIFT), dest_base, (int)(dest_base >> BLOCK_SHIFT), size, (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT)); for (i = 0; i < size; ++i) { swap_block_mem[dest_base + i] = swap_block_mem[src_base + i]; -#ifndef NDEBUG - swap_block_mem[src_base + i] = 0x55; -#endif + swap_block_mem[src_base + i] = 0xaa; } } @@ -223,9 +209,7 @@ void swap_copy_up(long src_limit, long dest_limit, long size) { size = -size; for (i = -1; i >= size; --i) { swap_block_mem[dest_limit + i] = swap_block_mem[src_limit + i]; -#ifndef NDEBUG - swap_block_mem[src_limit + i] = 0x55; -#endif + swap_block_mem[src_limit + i] = 0xaa; } } #endif @@ -234,28 +218,20 @@ void core_to_swap_copy(long src_base, long dest_base, long size) { long i; //printf("core_to_swap_copy %ld(%d) %ld(%d) %ld(%d)\n", src_base, (int)(src_base >> BLOCK_SHIFT), dest_base, (int)(dest_base >> BLOCK_SHIFT), size, (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT)); -#ifndef NDEBUG for (i = 0; i < size; ++i) - assert(swap_block_mem[dest_base + i] == 0xaa); -#endif + rassert(swap_block_mem[dest_base + i] == 0xaa); memcpy(swap_block_mem + dest_base, core_block_mem + src_base, size); -#ifndef NDEBUG memset(core_block_mem + src_base, 0xaa, size); -#endif } void swap_to_core_copy(long src_base, long dest_base, long size) { long i; //printf("swap_to_core_copy %ld(%d) %ld(%d) %ld(%d)\n", src_base, (int)(src_base >> BLOCK_SHIFT), dest_base, (int)(dest_base >> BLOCK_SHIFT), size, (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT)); -#ifndef NDEBUG for (i = 0; i < size; ++i) - assert(core_block_mem[dest_base + i] == 0xaa); -#endif + rassert(core_block_mem[dest_base + i] == 0xaa); memcpy(core_block_mem + dest_base, swap_block_mem + src_base, size); -#ifndef NDEBUG memset(swap_block_mem + src_base, 0xaa, size); -#endif } #endif @@ -276,10 +252,8 @@ int main(int argc, char **argv) { #endif #if defined(INDIRECT_CORE) || defined(INDIRECT_SWAP) int i, j, k; -#elif !defined(NDEBUG) - int i, j; #else - int i; + int i, j; #endif char buf[256]; int process; @@ -336,9 +310,7 @@ int main(int argc, char **argv) { #endif core_block_mem = malloc((long)n_core_blocks << BLOCK_SHIFT); rassert(core_block_mem); -#ifndef NDEBUG memset(core_block_mem, 0xaa, (long)n_core_blocks << BLOCK_SHIFT); -#endif #ifdef INODE_SWAP fd_open(fs_path); @@ -352,9 +324,7 @@ int main(int argc, char **argv) { #endif swap_block_mem = malloc((long)n_swap_blocks << BLOCK_SHIFT); rassert(swap_block_mem); -#ifndef NDEBUG memset(swap_block_mem, 0xaa, (long)n_swap_blocks << BLOCK_SHIFT); -#endif #endif process_init(n_processes, spare); @@ -698,8 +668,10 @@ done: } #ifdef INDIRECT_CORE +#ifndef NDEBUG for (i = 0; i < core_table_blocks; ++i) rassert(core_table_mem[i] == 0x55555555); +#endif { k = n_core_blocks >> 3; for (j = 0; j < k; ++j) @@ -709,17 +681,17 @@ done: rassert(core_block_bitmap[j] == (uint8_t)~(-1 << k)); } #endif -#ifndef NDEBUG j = n_core_blocks << BLOCK_SHIFT; for (i = 0; i < j; ++i) - assert(core_block_mem[i] == 0xaa); -#endif + rassert(core_block_mem[i] == 0xaa); #ifdef INODE_SWAP printf("free inodes %d blocks %d\n", fs_tab[0].s_tinode, fs_tab[0].s_tfree); #else #ifdef INDIRECT_SWAP +#ifndef NDEBUG for (i = 0; i < swap_table_blocks; ++i) rassert(swap_table_mem[i] == 0x55555555); +#endif { k = n_swap_blocks >> 3; for (j = 0; j < k; ++j) @@ -729,11 +701,9 @@ done: rassert(swap_block_bitmap[j] == (uint8_t)~(-1 << k)); } #endif -#ifndef NDEBUG j = n_swap_blocks << BLOCK_SHIFT; for (i = 0; i < j; ++i) rassert(swap_block_mem[i] == 0xaa); -#endif #endif return 0; diff --git a/swap.c b/swap.c index 27b4e0e..d76d238 100644 --- a/swap.c +++ b/swap.c @@ -191,7 +191,9 @@ bool swap_block_alloc(int *table, int size) { swap_block_bitmap[j] &= ~bits[k]; swap_block_next = (j << 3) | k; +#ifndef NDEBUG // makes us remove the following line in gen.sh as appropriate assert(table[i] == 0x55555555); +#endif table[i] = swap_block_next++; if (swap_block_next >= n_swap_blocks) swap_block_next = 0; @@ -213,7 +215,7 @@ void swap_block_free(int *table, int size) { swap_block_bitmap[j] |= bits[k]; #ifndef NDEBUG table[i] = 0x55555555; -#endif +#endif } swap_block_avail += size;