#include "core.h"
#include "process.h"
#include "rassert.h"
+
+#ifdef INODE_SWAP
+#define UCP 1
+#include "fuzix_fs.h"
+#else
#include "swap.h"
+#endif
struct process *processes;
int n_processes;
-int process_avail, process_spare;
+#ifdef INODE_SWAP
+long process_avail;
+#else
+int process_avail;
+#endif
struct lru_item lru_head;
struct process *victim;
-#if 1
-// won't work when compiled with NDEBUG
-static void check_invariants() {
- int avail =
-#ifdef INDIRECT_CORE
- n_core_blocks +
-#else
- core_table.item.base -
- core_table.item.limit +
-#endif
-#ifdef INDIRECT_SWAP
- n_swap_blocks -
-#else
- swap_table.item.base -
- swap_table.item.limit -
-#endif
- process_spare;
-#if defined(PREALLOCATE_CORE)
- if (avail > core_table.item.base - core_table.item.limit)
- avail = core_table.item.base - core_table.item.limit;
-#endif
-#if defined(PREALLOCATE_SWAP)
- if (avail > swap_table.item.base - swap_table.item.limit)
- avail = swap_table.item.base - swap_table.item.limit;
-#endif
- if (victim == NULL) {
-#ifdef PREALLOCATE_CORE
- assert(victim_core_blocks == 0);
-#endif
-#ifdef PREALLOCATE_SWAP
- assert(victim_swap_blocks == 0);
-#endif
- }
- for (int i = 0; i < n_processes; ++i)
- if (processes[i].size == -1L) {
- assert(
- processes[i].core_item.prev == NULL &&
- processes[i].core_item.next == NULL
- );
- assert(
- processes[i].swap_item.prev == NULL &&
- processes[i].swap_item.next == NULL
- );
- }
- else {
-#ifdef PREALLOCATE_CORE
- assert(processes[i].core_item.prev && processes[i].core_item.next);
-#endif
-#ifdef PREALLOCATE_SWAP
- assert(processes[i].swap_item.prev && processes[i].swap_item.next);
-#endif
- if (processes[i].lru_item.prev) {
- assert(processes + i != victim);
- assert(processes[i].lru_item.prev->next == &processes[i].lru_item);
- assert(processes[i].lru_item.next->prev == &processes[i].lru_item);
-#ifndef PREALLOCATE_CORE
- assert(processes[i].core_item.prev && processes[i].core_item.next);
- assert(
- (int)((processes[i].size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT) ==
- processes[i].core_item.limit - processes[i].core_item.base
- );
-#endif
-#ifndef PREALLOCATE_SWAP
- assert(
- processes[i].swap_item.prev == NULL &&
- processes[i].swap_item.next == NULL
- );
-#endif
- }
- else if (processes + i == victim) {
- assert(victim->core_item.prev && victim->core_item.next);
-#ifndef PREALLOCATE_CORE
- int victim_core_blocks =
- victim->core_item.limit - victim->core_item.base;
-#endif
- assert(victim_core_blocks);
- assert(victim->swap_item.prev && victim->swap_item.next);
-#ifndef PREALLOCATE_SWAP
- int victim_swap_blocks =
- victim->swap_item.limit - victim->swap_item.base;
-#endif
- assert(victim_swap_blocks);
- assert(
- (int)((processes[i].size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT) ==
- victim_core_blocks + victim_swap_blocks
- );
- }
- else {
-#ifndef PREALLOCATE_CORE
- assert(
- processes[i].core_item.prev == NULL &&
- processes[i].core_item.next == NULL
- );
-#endif
-#ifndef PREALLOCATE_SWAP
- assert(processes[i].swap_item.prev && processes[i].swap_item.next);
- assert(
- (int)((processes[i].size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT) ==
- processes[i].swap_item.limit - processes[i].swap_item.base
- );
-#endif
- }
- avail -= (int)((processes[i].size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+#ifdef INODE_SWAP
+long estimate_size(long size) {
+ long core_size;
+ int blocks, disk_blocks;
+ long disk_size;
+
+ core_size = (size + (BLOCK_SIZE - 1)) & ~(BLOCK_SIZE - 1);
+ assert(size < (long)DISK_BLOCK_SIZE << 16);
+ blocks = (int)((size + (DISK_BLOCK_SIZE - 1)) >> DISK_BLOCK_SHIFT);
+ disk_blocks = blocks;
+ if (blocks > 18) {
+ // has indirect blocks
+ blocks = (blocks + (DISK_INDIRECT_SIZE - 1 - 18)) >> DISK_INDIRECT_SHIFT;
+ disk_blocks += blocks;
+ if (blocks > 1) {
+ // has double indirect disk_blocks
+ blocks = (blocks + (DISK_INDIRECT_SIZE - 1 - 1)) >> DISK_INDIRECT_SHIFT;
+ assert(blocks == 1);
+ disk_blocks += blocks;
}
- assert(avail == process_avail);
+ }
+ disk_size = (long)disk_blocks << DISK_BLOCK_SHIFT;
+ return core_size >= disk_size ? core_size : disk_size;
}
#endif
void process_init(int n, int spare) {
+#if defined(INODE_SWAP) && defined(PREALLOCATE_CORE)
+ long core_table_avail;
+#endif
+
processes = calloc(n, sizeof(struct process));
rassert(processes);
n_processes = n;
processes[i].size = -1L;
#endif
+#ifdef INODE_SWAP
+ process_avail =
+ ((long)(core_avail() - spare) << BLOCK_SHIFT) +
+ ((long)fs_tab[0].s_tfree << DISK_BLOCK_SHIFT);
+#ifdef PREALLOCATE_CORE
+ core_table_avail = (long)core_table.avail << BLOCK_SHIFT;
+ if (process_avail > core_table.avail)
+ process_avail = core_table.avail;
+#endif
+#else
process_avail = core_avail() + swap_avail() - spare;
#ifdef PREALLOCATE_CORE
if (process_avail > core_table.avail)
if (process_avail > swap_table.avail)
process_avail = swap_table.avail;
#endif
- process_spare = spare;
+#endif
lru_head.prev = &lru_head;
lru_head.next = &lru_head;
victim_swap_blocks = 0;
#endif
#endif
- check_invariants();
}
static void do_swap_out(int swap_out) {
#ifndef PREALLOCATE_SWAP
int victim_swap_blocks;
#endif
+#ifdef INODE_SWAP
+ int blocks, core_base;
+#else
int blocks, swap_base, core_base;
+#endif
long size;
#if defined(INDIRECT_CORE) || defined(INDIRECT_SWAP)
int i, j;
if (victim) {
// calculate amount to swap out
#ifndef PREALLOCATE_CORE
- victim_core_blocks = victim->core_item.limit - victim->core_item.base;
+ victim_core_blocks =
+ victim->core_item.limit - victim->core_item.base;
#endif
#ifndef PREALLOCATE_SWAP
- victim_swap_blocks = victim->swap_item.limit - victim->swap_item.base;
+ victim_swap_blocks =
+#ifdef INODE_SWAP
+ (int)(victim->swap_inode->c_node.i_size >> BLOCK_SHIFT);
+#else
+ victim->swap_item.limit - victim->swap_item.base;
+#endif
#endif
blocks = swap_out < victim_core_blocks ? swap_out : victim_core_blocks;
printf("existing victim %d, swap out %d of %d\n", (int)(victim - processes), blocks, victim_core_blocks);
// increase swap allocation
-#ifndef PREALLOCATE_SWAP
+#if !defined(INODE_SWAP) && !defined(PREALLOCATE_SWAP)
rassert(
swap_table_realloc(&victim->swap_item, victim_swap_blocks + blocks)
);
// add to swap pool, using dedicated swap item
victim_swap_blocks = 0;
-#ifndef PREALLOCATE_SWAP
+#if !defined(INODE_SWAP) && !defined(PREALLOCATE_SWAP)
rassert(swap_table_alloc(&victim->swap_item, blocks));
#endif
loop_entry:
// calculate transfer parameters
+#ifndef INODE_SWAP
#ifdef PREALLOCATE_SWAP
swap_base = victim->swap_item.base + victim_swap_blocks;
#else
swap_base = victim->swap_item.limit - blocks;
#endif
+#endif
#ifdef PREALLOCATE_CORE
core_base = victim->core_item.base + victim_swap_blocks;
#else
if (victim_core_blocks == 0)
// yes, correct size for partial last block
size += ((victim->size - 1L) | -BLOCK_SIZE) + 1L;
- victim_swap_blocks += blocks;
// transfer data to swap
#ifdef INDIRECT_SWAP
rassert(swap_block_alloc(swap_table_mem + swap_base, blocks));
#endif
+#ifdef INODE_SWAP
+ printf("swap_write core [%d,%d) to swap [%d,%d)\n", core_base, core_base + blocks, victim_swap_blocks, victim_swap_blocks + blocks);
+#else
printf("swap_write core [%d,%d) to swap [%d,%d)\n", core_base, core_base + blocks, swap_base, swap_base + blocks);
+#endif
#if !defined(INDIRECT_CORE) && !defined(INDIRECT_SWAP)
+#ifdef INODE_SWAP
+ swap_write(
+ victim->swap_inode,
+ (long)victim_swap_blocks << BLOCK_SHIFT,
+ (long)core_base << BLOCK_SHIFT,
+ size
+ );
+#else
core_to_swap_copy(
(long)core_block << BLOCK_SHIFT,
(long)swap_block << BLOCK_SHIFT,
size
);
+#endif
#else
j = (int)(size >> BLOCK_SHIFT);
printf("blocks");
core_block = core_table_mem[core_block];
printf(" %d", core_block);
#endif
+#ifdef INODE_SWAP
+ swap_write(
+ victim->swap_inode,
+ (long)(victim_swap_blocks + i) << BLOCK_SHIFT,
+ (long)core_block << BLOCK_SHIFT,
+ size;
+ );
+#else
int swap_block = swap_base + i;
#ifdef INDIRECT_SWAP
swap_block = swap_table_mem[swap_block];
(long)swap_block << BLOCK_SHIFT,
BLOCK_SIZE
);
+#endif
}
j = (int)size & (BLOCK_SIZE - 1);
if (j) {
core_block = core_table_mem[core_block];
printf(" %d", core_block);
#endif
+#ifdef INODE_SWAP
+ swap_write(
+ victim->swap_inode,
+ (long)(victim_swap_blocks + i) << BLOCK_SHIFT,
+ (long)core_block << BLOCK_SHIFT,
+ j;
+ );
+#else
int swap_block = swap_base + i;
#ifdef INDIRECT_SWAP
swap_block = swap_table_mem[swap_block];
(long)swap_block << BLOCK_SHIFT,
j
);
+#endif
}
printf("\n");
#endif
#ifdef INDIRECT_CORE
core_block_free(core_table_mem + core_base, blocks);
#endif
+ victim_swap_blocks += blocks;
// see if victim fully swapped out
if (victim_core_blocks) {
}
bool process_alloc(struct process *process, long size) {
+#ifdef INODE_SWAP
+ long estimated_size;
+#endif
int blocks, swap_out;
// must not be already allocated
assert(process->size == -1L);
// check blocks
+#ifdef INODE_SWAP
+ estimated_size = estimate_size(size);
+ if (
+ process_avail < estimated_size ||
+ (process->swap_inode = i_open(0, 0)) == NULL
+ )
+ return false;
+
+ // initialize swap inode
+ process->swap_inode->c_node.i_uid = udata.u_euid;
+ process->swap_inode->c_node.i_gid = udata.u_egid;
+
+ process->swap_inode->c_node.i_mode = F_REG; /* For the time being */
+ process->swap_inode->c_node.i_nlink = 0;
+ process->swap_inode->c_node.i_size = 0;
+ for (int i = 0; i < 20; ++i)
+ process->swap_inode->c_node.i_addr[i] = 0;
+ wr_inode(process->swap_inode);
+
+ blocks = (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+#else
blocks = (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
if (
process_avail < blocks
#endif
)
return false;
+#endif
// free up as much core as we need to
swap_out = blocks - core_avail();
rassert(core_table_alloc(&process->core_item, blocks));
#else
if (!core_table_alloc(&process->core_item, blocks)) {
-#if defined(PREALLOCATE_SWAP) && !defined(MOVEABLE_SWAP)
+#ifdef INODE_SWAP
+ i_deref(process->core_inode);
+#elif defined(PREALLOCATE_SWAP) && !defined(MOVEABLE_SWAP)
swap_table_free(&process->swap_item);
#endif
return false;
// track total allocation
process->size = size;
+#ifdef INODE_SWAP
+ process_avail -= estimated_size;
+#else
process_avail -= blocks;
- check_invariants();
+#endif
return true;
}
bool process_realloc(struct process *process, long size) {
+#ifdef INODE_SWAP
+ long estimated_size, old_estimated_size, estimated_size_change;
+#endif
int blocks, old_blocks, swap_out;
// must be already allocated
assert(process->lru_item.prev != NULL);
// check blocks
+#ifdef INODE_SWAP
+ estimated_size = estimate_size(size);
+ old_estimated_size = estimate_size(process->size);
+ estimated_size_change = estimated_size - old_estimated_size;
+ if (process_avail < estimated_size_change)
+ return false;
+
+ blocks = (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+ old_blocks = (int)((process->size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+ int blocks_change = blocks - old_blocks;
+#else
blocks = (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
old_blocks = (int)((process->size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
int blocks_change = blocks - old_blocks;
if (process_avail < blocks_change)
return false;
+#endif
+
#if defined(PREALLOCATE_SWAP) && !defined(MOVEABLE_SWAP)
swap_table_free(&process->swap_item);
if (!swap_table_alloc(&process->swap_item, blocks)) {
// track total allocation
process->size = size;
+#ifdef INODE_SWAP
+ process_avail -= estimated_size_change;
+#else
process_avail -= blocks_change;
- check_invariants();
+#endif
return true;
}
void process_run(struct process *process) {
- int blocks, swap_out, excess;
+ int blocks, swap_out;
+#ifndef INODE_SWAP // temporarily remove until we can fix the logic
+#if !defined(PREALLOCATE_SWAP) || defined(INDIRECT_SWAP)
+ int excess;
+#endif
+#endif
int process_core_blocks, process_swap_blocks;
+#ifdef INODE_SWAP
+ int core_base;
+#else
int swap_base, core_base;
+#endif
long size;
#if defined(INDIRECT_CORE) || defined(INDIRECT_SWAP)
int i, j;
if (process != victim) {
// fully in swap, only the swap item is meaningful
process_swap_blocks =
+#ifdef INODE_SWAP
+ (int)(
+ ((long)process->swap_inode->c_node.i_size + (BLOCK_SIZE - 1)) >>
+ BLOCK_SHIFT
+ );
+#else
process->swap_item.limit - process->swap_item.base;
+#endif
// calculate amounts to swap out then in
blocks = process_swap_blocks;
swap_out = blocks - core_avail();
+#ifndef INODE_SWAP // temporarily remove until we can fix the logic
#if !defined(PREALLOCATE_SWAP) || defined(INDIRECT_SWAP)
excess = swap_out - swap_avail();
if (excess > 0) {
blocks -= excess;
swap_out = swap_avail();
}
+#endif
#endif
// free up as much core as we can
#endif
#else
process_swap_blocks =
+#ifdef INODE_SWAP
+ (int)(victim->swap_inode->c_node.i_size >> BLOCK_SHIFT);
+#else
victim->swap_item.limit - victim->swap_item.base;
+#endif
#endif
victim = NULL;
#ifndef PREALLOCATE_SWAP
do {
#ifndef PREALLOCATE_SWAP
// reduce swap allocation
+#ifdef INODE_SWAP
+ udata.u_offset = (long)process_swap_blocks << BLOCK_SHIFT;
+ f_trunc(process->swap_inode);
+#else
rassert(swap_table_realloc(&process->swap_item, process_swap_blocks));
+#endif
loop_entry_partial:
#endif
// calculate amounts to swap out then in
blocks = process_swap_blocks;
swap_out = blocks - core_avail();
+#ifndef INODE_SWAP // temporarily remove until we can fix the logic
#if !defined(PREALLOCATE_SWAP) || defined(INDIRECT_SWAP)
- if (swap_out > swap_avail()) {
- blocks += swap_avail() - swap_out;
+ excess = swap_out - swap_avail();
+ if (excess > 0) {
+ blocks -= excess;
swap_out = swap_avail();
}
+#endif
#endif
// free up as much core as we can
loop_entry_full:
// calculate transfer parameters
process_swap_blocks -= blocks;
+#ifndef INODE_SWAP
#ifdef PREALLOCATE_SWAP
swap_base = process->swap_item.base + process_swap_blocks;
#else
swap_base = process->swap_item.limit - blocks;
#endif
+#endif
#ifdef PREALLOCATE_CORE
core_base = process->core_item.base + process_swap_blocks;
#else
#ifdef INDIRECT_CORE
core_block_alloc(core_table_mem + core_base, blocks);
#endif
+#ifdef INODE_SWAP
+ printf("swap_read swap [%d,%d) to core [%d,%d)\n", process_swap_blocks, process_swap_blocks + blocks, core_base, core_base + blocks);
+#else
printf("swap_read swap [%d,%d) to core [%d,%d)\n", swap_base, swap_base + blocks, core_base, core_base + blocks);
+#endif
#if !defined(INDIRECT_CORE) && !defined(INDIRECT_SWAP)
+#ifdef INODE_SWAP
+ swap_read(
+ process->swap_inode,
+ (long)process_swap_blocks << BLOCK_SHIFT,
+ (long)core_base << BLOCK_SHIFT,
+ size
+ );
+#else
swap_to_core_copy(
(long)swap_block << BLOCK_SHIFT,
(long)core_block << BLOCK_SHIFT,
size
);
+#endif
#else
j = (int)(size >> BLOCK_SHIFT);
printf("blocks");
for (i = 0; i < j; ++i) {
- int swap_block = swap_base + i;
-#ifdef INDIRECT_SWAP
- swap_block = swap_table_mem[swap_block];
- printf(" %d", swap_block);
-#endif
int core_block = core_base + i;
#ifdef INDIRECT_CORE
core_block = core_table_mem[core_block];
+ printf(" %d", core_block);
+#endif
+#ifdef INODE_SWAP
+ swap_read(
+ process->swap_inode,
+ (long)(process_swap_blocks + i) << BLOCK_SHIFT,
+ (long)core_block << BLOCK_SHIFT,
+ BLOCK_SIZE;
+ );
+#else
+ int swap_block = swap_base + i;
#ifdef INDIRECT_SWAP
- printf(",%d", core_block);
+ swap_block = swap_table_mem[swap_block];
+#ifdef INDIRECT_SWAP
+ printf(",%d", swap_block);
#else
- printf(" %d", core_block);
+ printf(" %d", swap_block);
#endif
#endif
swap_to_core_copy(
(long)core_block << BLOCK_SHIFT,
BLOCK_SIZE
);
+#endif
}
j = (int)size & (BLOCK_SIZE - 1);
if (j) {
- int swap_block = swap_base + i;
-#ifdef INDIRECT_SWAP
- swap_block = swap_table_mem[swap_block];
- printf(" %d", swap_block);
-#endif
int core_block = core_base + i;
#ifdef INDIRECT_CORE
core_block = core_table_mem[core_block];
+ printf(" %d", core_block);
+#endif
+#ifdef INODE_SWAP
+ swap_read(
+ process->swap_inode,
+ (long)(process_swap_blocks + i) << BLOCK_SHIFT,
+ (long)core_block << BLOCK_SHIFT,
+ BLOCK_SIZE;
+ );
+#else
+ int swap_block = swap_base + i;
+#ifdef INDIRECT_SWAP
+ swap_block = swap_table_mem[swap_block];
#ifdef INDIRECT_SWAP
- printf(",%d", core_block);
+ printf(",%d", swap_block);
#else
- printf(" %d", core_block);
+ printf(" %d", swap_block);
#endif
#endif
- putchar('*');
swap_to_core_copy(
(long)swap_block << BLOCK_SHIFT,
(long)core_block << BLOCK_SHIFT,
j
);
+#endif
}
printf("\n");
#endif
#endif
} while (process_swap_blocks);
-#ifndef PREALLOCATE_SWAP
+#ifdef INODE_SWAP
+ // delete swap data, retain swap inode
+ udata.u_offset = 0;
+ f_trunc(process->swap_inode);
+#elif !defined(PREALLOCATE_SWAP)
// remove from swap pool
swap_table_free(&process->swap_item);
#endif
process->lru_item.next = lru_head.next;
process->lru_item.prev->next = &process->lru_item;
process->lru_item.next->prev = &process->lru_item;
- check_invariants();
}
void process_free(struct process *process) {
#endif
#ifdef PREALLOCATE_SWAP
victim_swap_blocks = 0;
-#else
+#elif !defined(INODE_SWAP)
swap_table_free(&victim->swap_item);
#endif
#ifdef INDIRECT_CORE
#ifdef PREALLOCATE_CORE
#if defined(PREALLOCATE_SWAP) || defined(INDIRECT_SWAP)
core_base = victim->core_item.base + victim_swap_blocks;
+#elif defined(INODE_SWAP)
+ core_base =
+ victim->core_item.base +
+ (int)(victim->swap_inode.c_node.i_size >> BLOCK_SHIFT);
#else
core_base =
victim->core_item.base +
process->swap_item.limit - swap_base
);
#endif
-#ifndef PREALLOCATE_SWAP
+#if !defined(INODE_SWAP) && !defined(PREALLOCATE_SWAP)
swap_table_free(&process->swap_item);
#endif
}
#endif
#ifdef PREALLOCATE_SWAP
swap_table_free(&process->swap_item);
+#elif defined(INODE_SWAP)
+ i_deref(process->swap_inode);
#endif
// track total allocation
+#ifdef INODE_SWAP
+ process_avail += estimate_size(process->size);
+#else
process_avail += (int)((process->size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+#endif
#ifndef NDEBUG
process->size = -1L;
#endif
- check_invariants();
}
#include "core.h"
#include "process.h"
#include "rassert.h"
+
+#ifdef INODE_SWAP
+#define UCP 1
+#include "fuzix_fs.h"
+#include "util.h"
+#else
#include "swap.h"
+#endif
+
+#define TRANSFER_SIZE 0x8000
uint8_t *core_block_mem;
+#ifndef INODE_SWAP
uint8_t *swap_block_mem;
+#endif
void core_hash_init(int process, long base, long size, long offset) {
//printf("core_hash_init %d %ld(%d) %ld(%d) %ld(%d)\n", process, base, (int)(base >> BLOCK_SHIFT), size, (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT), offset, (int)(offset >> BLOCK_SHIFT));
}
}
-void swap_hash_verify(int process, long base, long size, long offset) {
- //printf("swap_hash_verify %d %ld(%d) %ld(%d) %ld(%d)\n", process, base, (int)(base >> BLOCK_SHIFT), size, (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT), offset, (int)(offset >> BLOCK_SHIFT));
+#ifdef INODE_SWAP
+void swap_hash_verify(int process, struct cinode *inode) {
+ long count;
+ for (
+ long offset = 0;
+ (count = (long)inode->c_node.i_size - offset) > 0;
+ offset += count
+ ) {
+ if (count > TRANSFER_SIZE)
+ count = TRANSFER_SIZE;
+
+ uint8_t buf[TRANSFER_SIZE];
+ udata.u_base = (char *)buf;
+ udata.u_count = count;
+ udata.u_offset = offset;
+ udata.u_error = 0;
+ rassert(readi(inode) == count && udata.u_error == 0);
+
+ for (int i = 0; i < count; ++i) {
+ long long hash = process * 17 + (i + offset) * 29;
+ hash = (hash & 0xffffffffLL) + (hash >> 32);
+ hash = (hash & 0xffffLL) + (hash >> 16);
+ hash = (hash & 0xffLL) + (hash >> 8);
+ hash = (hash & 0xffLL) + (hash >> 8);
+ rassert(buf[i] == (uint8_t)hash);
+ }
+ }
+}
+#else
+void swap_hash_verify(int process, long base, long size) {
+ //printf("swap_hash_verify %d %ld(%d) %ld(%d)\n", process, base, (int)(base >> BLOCK_SHIFT), size, (int)((size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT));
for (long i = 0L; i < size; ++i) {
long addr = base + i;
#ifdef INDIRECT_SWAP
(swap_table_mem[addr >> BLOCK_SHIFT] << BLOCK_SHIFT) |
(addr & (BLOCK_SIZE - 1));
#endif
- long long hash = process * 17 + (i + offset) * 29;
+ long long hash = process * 17 + i * 29;
hash = (hash & 0xffffffffLL) + (hash >> 32);
hash = (hash & 0xffffLL) + (hash >> 16);
hash = (hash & 0xffLL) + (hash >> 8);
swap_block_mem[addr] = 0xaa;
}
}
+#endif
#ifndef INDIRECT_CORE
void core_copy(long src_base, long dest_base, long size) {
}
#endif
+#ifdef INODE_SWAP
+void swap_read(
+ struct cinode *inode,
+ long offset,
+ long core_base,
+ long size
+) {
+ //printf("read %ld %ld %ld\n", offset, core_base, size);
+ for (long i = 0; i < size; ++i)
+ rassert(core_block_mem[core_base + i] == 0xaa);
+
+ long count;
+ for (long i = 0; (count = size - i) > 0; i += count) {
+ if (count > TRANSFER_SIZE)
+ count = TRANSFER_SIZE;
+
+ udata.u_base = (char *)(core_block_mem + core_base + i);
+ udata.u_count = (int)count;
+ udata.u_offset = (uint32_t)(offset + i);
+ udata.u_error = 0;
+ rassert(readi(inode) == (int)count && udata.u_error == 0);
+ }
+}
+
+void swap_write(
+ struct cinode *inode,
+ long offset,
+ long core_base,
+ long size
+) {
+ //printf("write %ld %ld %ld\n", offset, core_base, size);
+ long count;
+ for (long i = 0; (count = size - i) > 0; i += count) {
+ if (count > TRANSFER_SIZE)
+ count = TRANSFER_SIZE;
+
+ udata.u_base = (char *)(core_block_mem + core_base + i);
+ udata.u_count = (int)count;
+ udata.u_offset = (uint32_t)(offset + i);
+ udata.u_error = 0;
+ rassert(writei(inode) == (int)count && udata.u_error == 0);
+ }
+
+ memset(core_block_mem + core_base, 0xaa, size);
+}
+#else
#ifndef INDIRECT_SWAP
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));
memcpy(core_block_mem + dest_base, swap_block_mem + src_base, size);
memset(swap_block_mem + src_base, 0xaa, size);
}
+#endif
int main(int argc, char **argv) {
if (argc < 5) {
+ printf(
+ "usage: %s n_processes n_core_blocks "
+#ifdef INODE_SWAP
+ "fs_path "
+#else
+ "n_swap_blocks "
+#endif
+ "spare"
#if defined(INDIRECT_CORE) && defined(INDIRECT_SWAP)
- printf("usage: %s n_processes n_core_blocks n_swap_blocks spare [core_table_blocks [swap_table_blocks]]\n", argv[0]);
+ "[core_table_blocks [swap_table_blocks]]"
#elif defined(INDIRECT_CORE)
- printf("usage: %s n_processes n_core_blocks n_swap_blocks spare [core_table_blocks]\n", argv[0]);
+ "[core_table_blocks]"
#elif defined(INDIRECT_SWAP)
- printf("usage: %s n_processes n_core_blocks n_swap_blocks spare [swap_table_blocks]\n", argv[0]);
-#else
- printf("usage: %s n_processes n_core_blocks n_swap_blocks spare\n", argv[0]);
+ "[swap_table_blocks]"
#endif
+ "\n",
+ argv[0]
+ );
exit(EXIT_FAILURE);
}
int n_processes = atoi(argv[1]);
int n_core_blocks = atoi(argv[2]);
+#ifdef INODE_SWAP
+ char *fs_path = argv[3];
+#else
int n_swap_blocks = atoi(argv[3]);
+#endif
int spare = atoi(argv[4]);
#if defined(INDIRECT_CORE) && defined(INDIRECT_SWAP)
int core_table_blocks = argc >= 6 ? atoi(argv[5]) : n_core_blocks;
#elif defined(INDIRECT_SWAP)
int swap_table_blocks = argc >= 6 ? atoi(argv[5]) : n_swap_blocks;
#endif
- swap_block_mem = malloc((long)n_swap_blocks << BLOCK_SHIFT);
- rassert(swap_block_mem);
- memset(swap_block_mem, 0xaa, (long)n_swap_blocks << BLOCK_SHIFT);
#ifdef INDIRECT_CORE
core_init(n_core_blocks, core_table_blocks);
rassert(core_block_mem);
memset(core_block_mem, 0xaa, (long)n_core_blocks << BLOCK_SHIFT);
+#ifdef INODE_SWAP
+ fd_open(fs_path);
+ xfs_init(0);
+ printf("free inodes %d blocks %d\n", fs_tab[0].s_tinode, fs_tab[0].s_tfree);
+#else
#ifdef INDIRECT_SWAP
swap_init(n_swap_blocks, swap_table_blocks);
#else
swap_init(n_swap_blocks);
#endif
+ swap_block_mem = malloc((long)n_swap_blocks << BLOCK_SHIFT);
+ rassert(swap_block_mem);
+ memset(swap_block_mem, 0xaa, (long)n_swap_blocks << BLOCK_SHIFT);
+#endif
+
process_init(n_processes, spare);
for (int i = 0; i < n_processes; ++i)
processes[i].size = -1L;
printf("... not allocated, ignore\n");
else {
int core_base = processes[process].core_item.base;
- int actual_old_size = processes[process].size;
+ long actual_old_size = processes[process].size;
int actual_old_blocks =
(int)((actual_old_size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
rassert(
core_blocks = processes[process].core_item.limit - core_base;
core_size = processes[process].size;
}
- else if (processes + process == victim) { // victim
- swap_base = victim->swap_item.base;
+ else {
+#ifdef INODE_SWAP
+ swap_base = 0;
+ swap_size = (long)processes[process].swap_inode->c_node.i_size;
+ swap_blocks = (int)((swap_size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+#endif
+ if (processes + process == victim) { // victim
+#ifndef INODE_SWAP
+ swap_base = victim->swap_item.base;
#ifdef PREALLOCATE_SWAP
- swap_blocks = victim_swap_blocks;
+ swap_blocks = victim_swap_blocks;
#else
- swap_blocks = victim->swap_item.limit - victim->swap_item.base;
+ swap_blocks = victim->swap_item.limit - victim->swap_item.base;
+#endif
+ swap_size = swap_blocks << BLOCK_SHIFT;
#endif
- swap_size = swap_blocks << BLOCK_SHIFT;
#ifdef PREALLOCATE_CORE
- core_base = victim->core_item.base + swap_blocks;
- core_blocks = victim_core_blocks;
+ core_base = victim->core_item.base + swap_blocks;
+ core_blocks = victim_core_blocks;
#else
- core_base = victim->core_item.base;
- core_blocks = victim->core_item.limit - core_base;
+ core_base = victim->core_item.base;
+ core_blocks = victim->core_item.limit - core_base;
#endif
- core_size = victim->size - swap_size;
- }
- else { // fully in swap
- swap_base = processes[process].swap_item.base;
- swap_blocks = processes[process].swap_item.limit - swap_base;
- swap_size = processes[process].size;
- core_base = -1;
- core_blocks = 0;
- core_size = 0L;
+ core_size = victim->size - swap_size;
+ }
+ else { // fully in swap
+#ifndef INODE_SWAP
+ swap_base = processes[process].swap_item.base;
+ swap_blocks = processes[process].swap_item.limit - swap_base;
+ swap_size = processes[process].size;
+#endif
+ core_base = -1;
+ core_blocks = 0;
+ core_size = 0L;
+ }
}
rassert(core_blocks + swap_blocks == actual_old_blocks);
printf("old core [%d,%d) swap [%d,%d)\n", core_base, core_base + core_blocks, swap_base, swap_base + swap_blocks);
);
swap_hash_verify(
process,
+#ifdef INODE_SWAP
+ processes[process].swap_inode
+#else
(long)swap_base << BLOCK_SHIFT,
- swap_size,
- 0L
+ swap_size
+#endif
);
process_free(processes + process);
processes[process].size = -1L;
core_blocks = processes[i].core_item.limit - core_base;
core_size = processes[i].size;
}
- else if (processes + i == victim) { // victim
- swap_base = victim->swap_item.base;
+ else {
+#ifdef INODE_SWAP
+ swap_base = 0;
+ swap_size = (long)processes[i].swap_inode->c_node.i_size;
+ swap_blocks = (int)((swap_size + (BLOCK_SIZE - 1)) >> BLOCK_SHIFT);
+#endif
+ if (processes + i == victim) { // victim
+#ifndef INODE_SWAP
+ swap_base = victim->swap_item.base;
#ifdef PREALLOCATE_SWAP
- swap_blocks = victim_swap_blocks;
+ swap_blocks = victim_swap_blocks;
#else
- swap_blocks = victim->swap_item.limit - victim->swap_item.base;
+ swap_blocks = victim->swap_item.limit - victim->swap_item.base;
+#endif
+ swap_size = swap_blocks << BLOCK_SHIFT;
#endif
- swap_size = swap_blocks << BLOCK_SHIFT;
#ifdef PREALLOCATE_CORE
- core_base = victim->core_item.base + swap_blocks;
- core_blocks = victim_core_blocks;
+ core_base = victim->core_item.base + swap_blocks;
+ core_blocks = victim_core_blocks;
#else
- core_base = victim->core_item.base;
- core_blocks = victim->core_item.limit - core_base;
+ core_base = victim->core_item.base;
+ core_blocks = victim->core_item.limit - core_base;
#endif
- core_size = victim->size - swap_size;
- }
- else { // fully in swap
- swap_base = processes[i].swap_item.base;
- swap_blocks = processes[i].swap_item.limit - swap_base;
- swap_size = processes[i].size;
- core_base = -1;
- core_blocks = 0;
- core_size = 0L;
+ core_size = victim->size - swap_size;
+ }
+ else { // fully in swap
+#ifndef INODE_SWAP
+ swap_base = processes[i].swap_item.base;
+ swap_blocks = processes[i].swap_item.limit - swap_base;
+ swap_size = processes[i].size;
+#endif
+ core_base = -1;
+ core_blocks = 0;
+ core_size = 0L;
+ }
}
rassert(
core_blocks + swap_blocks ==
#endif
swap_hash_verify(
i,
+#ifdef INODE_SWAP
+ processes[i].swap_inode
+#else
(long)swap_base << BLOCK_SHIFT,
- swap_size,
- 0L
+ swap_size
+#endif
);
-#ifdef INDIRECT_SWAP
+#ifdef INODE_SWAP
+ i_deref(processes[i].swap_inode);
+#elif defined(INDIRECT_SWAP)
swap_block_free(swap_table_mem + swap_base, swap_blocks);
#endif
}
for (int i = 0; i < j; ++i)
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
for (int i = 0; i < swap_table_blocks; ++i)
rassert(swap_table_mem[i] == 0x55555555);
for (int i = 0; i < j; ++i)
rassert(swap_block_mem[i] == 0xaa);
}
+#endif
return 0;
}