Word Unperfect
public
Read
Owner: themaster
Branch: main
Commits: 0
Git CLI clone URL
git clone https://www.xt-emporium.com/git/word-unperfect.git
Fullscreen desktop URL
Code
Commits
History
Branches
Bug Reports
Discussions
Compare
Settings
word-unperfect
/
rev
/
wp_memory_manager.c
File editor
#include "wp_memory_manager.h" #include <stdio.h> #include <stdlib.h> #include <string.h> static uint32_t wp_mem_next_tick(WpVirtualMemory *vm) { vm->access_clock += 1U; if (vm->access_clock == 0U) { vm->access_clock = 1U; } return vm->access_clock; } static int wp_mem_find_block(WpVirtualMemory *vm, uint32_t block_id) { int i; for (i = 0; i < vm->pool_size; ++i) { if (vm->ram_pool[i].is_in_ram && vm->ram_pool[i].id == block_id) { return i; } } return -1; } static int wp_mem_choose_slot(WpVirtualMemory *vm) { int i; int victim = -1; uint32_t oldest = UINT32_MAX; for (i = 0; i < vm->pool_size; ++i) { if (!vm->ram_pool[i].is_in_ram) { return i; } if (vm->ram_pool[i].last_access < oldest) { oldest = vm->ram_pool[i].last_access; victim = i; } } return victim; } static FILE *wp_mem_open_swap(const char *path, const char *mode) { FILE *f; if (path == NULL || *path == '\0') { return NULL; } f = fopen(path, mode); if (f == NULL && mode[0] == 'r') { f = fopen(path, "w+b"); } return f; } void wp_mem_init(WpVirtualMemory *vm, int pool_size, const char *swap_path) { int i; if (vm == NULL) { return; } memset(vm, 0, sizeof(*vm)); vm->pool_size = pool_size > 0 ? pool_size : 0; vm->swap_file = swap_path; if (vm->pool_size == 0) { return; } vm->ram_pool = (WpMemBlock *)calloc((size_t)vm->pool_size, sizeof(WpMemBlock)); if (vm->ram_pool == NULL) { vm->pool_size = 0; return; } for (i = 0; i < vm->pool_size; ++i) { vm->ram_pool[i].id = WP_MEM_INVALID_BLOCK; } } void wp_mem_destroy(WpVirtualMemory *vm) { if (vm == NULL) { return; } (void)wp_mem_flush(vm); free(vm->ram_pool); memset(vm, 0, sizeof(*vm)); } void* wp_mem_get_ptr(WpVirtualMemory *vm, uint32_t offset) { uint32_t block_id; uint32_t block_offset; int slot; if (vm == NULL || vm->ram_pool == NULL || vm->pool_size <= 0) { return NULL; } block_id = offset / WP_BLOCK_SIZE; block_offset = offset % WP_BLOCK_SIZE; slot = wp_mem_find_block(vm, block_id); if (slot < 0) { slot = wp_mem_choose_slot(vm); if (slot < 0) { return NULL; } if (vm->ram_pool[slot].is_in_ram && vm->ram_pool[slot].is_dirty) { wp_mem_swap_out(vm, slot); } wp_mem_swap_in(vm, block_id, slot); } vm->ram_pool[slot].last_access = wp_mem_next_tick(vm); return &vm->ram_pool[slot].data[block_offset]; } bool wp_mem_mark_dirty(WpVirtualMemory *vm, uint32_t offset) { uint32_t block_id; int slot; if (vm == NULL || vm->ram_pool == NULL || vm->pool_size <= 0) { return false; } block_id = offset / WP_BLOCK_SIZE; slot = wp_mem_find_block(vm, block_id); if (slot < 0) { return false; } vm->ram_pool[slot].is_dirty = true; vm->ram_pool[slot].last_access = wp_mem_next_tick(vm); return true; } bool wp_mem_flush(WpVirtualMemory *vm) { int i; bool ok = true; if (vm == NULL || vm->ram_pool == NULL) { return true; } for (i = 0; i < vm->pool_size; ++i) { if (vm->ram_pool[i].is_in_ram && vm->ram_pool[i].is_dirty) { wp_mem_swap_out(vm, i); if (vm->ram_pool[i].is_dirty) { ok = false; } } } return ok; } bool wp_mem_read(WpVirtualMemory *vm, uint32_t offset, void *dst, size_t count) { uint8_t *out = (uint8_t *)dst; size_t done = 0; if (count == 0) { return true; } if (vm == NULL || out == NULL) { return false; } if ((uint64_t)offset + (uint64_t)count - 1ULL > UINT32_MAX) { return false; } while (done < count) { uint32_t current = (uint32_t)((uint64_t)offset + (uint64_t)done); size_t block_offset = (size_t)(current % WP_BLOCK_SIZE); size_t chunk = (size_t)WP_BLOCK_SIZE - block_offset; uint8_t *ptr; if (chunk > count - done) { chunk = count - done; } ptr = (uint8_t *)wp_mem_get_ptr(vm, current); if (ptr == NULL) { return false; } memcpy(out + done, ptr, chunk); done += chunk; } return true; } bool wp_mem_write(WpVirtualMemory *vm, uint32_t offset, const void *src, size_t count) { const uint8_t *in = (const uint8_t *)src; size_t done = 0; if (count == 0) { return true; } if (vm == NULL || in == NULL) { return false; } if ((uint64_t)offset + (uint64_t)count - 1ULL > UINT32_MAX) { return false; } while (done < count) { uint32_t current = (uint32_t)((uint64_t)offset + (uint64_t)done); size_t block_offset = (size_t)(current % WP_BLOCK_SIZE); size_t chunk = (size_t)WP_BLOCK_SIZE - block_offset; uint8_t *ptr; if (chunk > count - done) { chunk = count - done; } ptr = (uint8_t *)wp_mem_get_ptr(vm, current); if (ptr == NULL) { return false; } memcpy(ptr, in + done, chunk); if (!wp_mem_mark_dirty(vm, current)) { return false; } done += chunk; } return true; } void wp_mem_swap_out(WpVirtualMemory *vm, int pool_index) { WpMemBlock *block; FILE *f; long pos; if (vm == NULL || vm->ram_pool == NULL || pool_index < 0 || pool_index >= vm->pool_size) { return; } block = &vm->ram_pool[pool_index]; if (!block->is_in_ram || block->id == WP_MEM_INVALID_BLOCK) { return; } f = wp_mem_open_swap(vm->swap_file, "r+b"); if (f == NULL) { return; } pos = (long)block->id * (long)WP_BLOCK_SIZE; if (fseek(f, pos, SEEK_SET) == 0 && fwrite(block->data, 1, WP_BLOCK_SIZE, f) == WP_BLOCK_SIZE) { block->is_dirty = false; } fclose(f); } void wp_mem_swap_in(WpVirtualMemory *vm, uint32_t block_id, int pool_index) { WpMemBlock *block; FILE *f; long pos; size_t got = 0; if (vm == NULL || vm->ram_pool == NULL || pool_index < 0 || pool_index >= vm->pool_size) { return; } block = &vm->ram_pool[pool_index]; memset(block->data, 0, sizeof(block->data)); f = wp_mem_open_swap(vm->swap_file, "rb"); if (f != NULL) { pos = (long)block_id * (long)WP_BLOCK_SIZE; if (fseek(f, pos, SEEK_SET) == 0) { got = fread(block->data, 1, WP_BLOCK_SIZE, f); } (void)got; fclose(f); } block->id = block_id; block->is_in_ram = true; block->is_dirty = false; block->last_access = wp_mem_next_tick(vm); }
Commit message
This repository is read-only for this account.
Repository snapshot
Current branch
main
Visibility
public
Your access
Read
Remote
None
File activity
View file history