From 3d73718aee9e5982d8aad7760e204f2685b8084a Mon Sep 17 00:00:00 2001 From: Eric-Paul Ickhorn Date: Sat, 2 Mar 2024 08:15:51 +0100 Subject: [PATCH] Added shadow entity lookup, registry and pool. --- core/build-config/tests.txt | 3 +- core/inc-c/context.h | 2 + core/inc-c/shadow.h | 82 +++++++++++++++++ core/src-c/shadow-lookup.c | 90 +++++++++++++++++++ core/src-c/shadow-pool.c | 66 ++++++++++++++ core/src-c/shadow-registry.c | 80 +++++++++++++++++ .../internal/shadow-lookup/include_paths.txt | 1 + core/tests/internal/shadow-lookup/main.c | 55 ++++++++++++ 8 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 core/inc-c/shadow.h create mode 100644 core/src-c/shadow-lookup.c create mode 100644 core/src-c/shadow-pool.c create mode 100644 core/src-c/shadow-registry.c create mode 100644 core/tests/internal/shadow-lookup/include_paths.txt create mode 100644 core/tests/internal/shadow-lookup/main.c diff --git a/core/build-config/tests.txt b/core/build-config/tests.txt index 4800e89..73fff74 100644 --- a/core/build-config/tests.txt +++ b/core/build-config/tests.txt @@ -1 +1,2 @@ -tests/internal/shadow-tag \ No newline at end of file +tests/internal/shadow-tag +tests/internal/shadow-lookup \ No newline at end of file diff --git a/core/inc-c/context.h b/core/inc-c/context.h index 8964957..374bdc5 100644 --- a/core/inc-c/context.h +++ b/core/inc-c/context.h @@ -4,10 +4,12 @@ #include #include +#include typedef struct MtContext { MtShadowTagSystem shadow_tag_system; + MtShadowRegistry *shadow_registry; } MtContext; #endif // MT_CONTEXT_H diff --git a/core/inc-c/shadow.h b/core/inc-c/shadow.h new file mode 100644 index 0000000..c892aa6 --- /dev/null +++ b/core/inc-c/shadow.h @@ -0,0 +1,82 @@ + +#ifndef MT_SHADOW_H +#define MT_SHADOW_H + +#include +#include + +typedef struct MtShadowRegistry MtShadowRegistry; +typedef struct MtShadow MtShadow; +typedef struct MtShadowPool MtShadowPool; +typedef struct MtShadowLookupTree MtShadowLookupTree; + +/// @brief: An MtShadow contains the actual information which is used +/// each time when an entity is modified. It contains the tags and +/// other meta-information as well as data required for optimization. +struct MtShadow +{ + void *context; + MtShadowTag *tag_chain_start; + u32_t identifier; + + MtShadowPool *pool; + MtShadow *pool_next; +}; + +struct MtShadowPool +{ + usz_t capacity; + MtShadow *shadows; + MtShadow *first_free; + MtShadowPool *continuation; +}; + +typedef struct MtShadowLookupLevel3 +{ + MtShadow *next[256]; +} MtShadowLookupLevel3; + +typedef struct MtShadowLookupLevel2 +{ + MtShadowLookupLevel3 *next[256]; +} MtShadowLookupLevel2; + +typedef struct MtShadowLookup1 +{ + MtShadowLookupLevel2 *next[256]; +} MtShadowLookupLevel1; + +struct MtShadowLookupTree +{ + MtShadowLookupLevel1 *next[256]; +}; + +struct MtShadowRegistry +{ + // TODO: The IDs must be assigned using a singly linked list of indices + // to the next free entry, the index representing the ID's value and having + // stored the next free entry's index. Conceptually similar to the internals + // of the old File Allocation Table filesystems (FAT12, FAT16, FAT32). + u32_t id_counter; + MtShadowPool root_pool; + MtShadowLookupTree lookup_tree; + void *context_ptr; +}; + +MtShadowRegistry mt_create_shadow_registry(void *context_ptr); +void mt_cleanup_shadow_registry(MtShadowRegistry *registry); + +MtShadow * mt_create_shadow(MtShadowRegistry *registry); +MtShadow * mt_lookup_shadow(MtShadowRegistry *registry, u32_t identifier); +void mt_delete_shadow(MtShadowRegistry *registry, MtShadow *shadow); + +void mt_cleanup_shadow_pool(MtShadowPool *pool); +void mt_free_shadow_pool(MtShadowPool *pool); +MtShadowLookupTree mt_create_shadow_lookup_tree(); + +void mt_init_shadow_pool(MtShadowPool *pool, usz_t capacity); +MtShadowPool * mt_new_shadow_pool(usz_t capacity); +MtShadow * mt_pool_shadow(MtShadowPool *pool); +void mt_unpool_shadow(MtShadow *shadow); + +#endif // MT_SHADOW_H diff --git a/core/src-c/shadow-lookup.c b/core/src-c/shadow-lookup.c new file mode 100644 index 0000000..7cdb2dc --- /dev/null +++ b/core/src-c/shadow-lookup.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +MtShadowLookupTree mt_create_shadow_lookup_tree() +{ + MtShadowLookupTree lookup_tree; + rr_memset(&lookup_tree.next[0], sizeof(MtShadow *) * 256, 0); + return lookup_tree; +} + +MtShadow * mt_lookup_shadow(MtShadowRegistry *registry, u32_t identifier) +{ + u8_t index_1 = identifier >> 24; + u8_t index_2 = (identifier >> 16) & 0xff; + u8_t index_3 = (identifier >> 8) & 0xff; + u8_t index_4 = identifier & 0xff; + MtShadowLookupLevel1 *level_1 = registry->lookup_tree.next[index_1]; + if(level_1 == NULL) + return NULL; + MtShadowLookupLevel2 *level_2 = level_1->next[index_2]; + if(level_2 == NULL) + return NULL; + MtShadowLookupLevel3 *level_3 = level_2->next[index_3]; + if(level_3 == NULL) + return NULL; + MtShadow *shadow = level_3->next[index_4]; + return shadow; +} + +void mt_delete_shadow(MtShadowRegistry *registry, MtShadow *shadow) +{ + u32_t identifier = shadow->identifier; + mt_unpool_shadow(shadow); + + u8_t index_1 = identifier >> 24; + u8_t index_2 = (identifier >> 16) & 0xff; + u8_t index_3 = (identifier >> 8) & 0xff; + u8_t index_4 = identifier & 0xff; + MtShadowLookupLevel1 *level_1 = registry->lookup_tree.next[index_1]; + if(level_1 == NULL) + return; + MtShadowLookupLevel2 *level_2 = level_1->next[index_2]; + if(level_2 == NULL) + return; + MtShadowLookupLevel3 *level_3 = level_2->next[index_3]; + if(level_3 == NULL) + return; + level_3->next[index_4] = NULL; +} + +void mt_write_shadow_lookup_entry(MtShadowLookupTree *tree, MtShadow *shadow) +{ + u32_t identifier = shadow->identifier; + + u8_t index_1 = identifier >> 24; + u8_t index_2 = (identifier >> 16) & 0xff; + u8_t index_3 = (identifier >> 8) & 0xff; + u8_t index_4 = identifier & 0xff; + MtShadowLookupLevel1 *level_1 = tree->next[index_1]; + if(level_1 == NULL) + { + tree->next[index_1] = calloc(sizeof(MtShadowLookupLevel1), 256); + level_1 = tree->next[index_1]; + } + MtShadowLookupLevel2 *level_2 = level_1->next[index_2]; + if(level_2 == NULL) + { + level_1->next[index_1] = calloc(sizeof(MtShadowLookupLevel2), 256); + level_2 = level_1->next[index_2]; + } + MtShadowLookupLevel3 *level_3 = level_2->next[index_3]; + if(level_3 == NULL) + { + level_2->next[index_1] = calloc(sizeof(MtShadowLookupLevel3), 256); + level_3 = level_2->next[index_3]; + } + level_3->next[index_4] = shadow; +} + +MtShadow * mt_create_shadow(MtShadowRegistry *registry) +{ + MtShadow *shadow = mt_pool_shadow(®istry->root_pool); + shadow->identifier = registry->id_counter; + shadow->context = registry->context_ptr; + shadow->tag_chain_start = NULL; + mt_write_shadow_lookup_entry(®istry->lookup_tree, shadow); + return shadow; +} diff --git a/core/src-c/shadow-pool.c b/core/src-c/shadow-pool.c new file mode 100644 index 0000000..1fc283a --- /dev/null +++ b/core/src-c/shadow-pool.c @@ -0,0 +1,66 @@ +#include +#include + +void mt_init_shadow_pool_allocation(MtShadowPool *pool) +{ + usz_t capacity = pool->capacity; + usz_t shadow_index = 0; + while(shadow_index < capacity) + { + pool->shadows[shadow_index].pool = pool; + pool->shadows[shadow_index].pool_next = &pool->shadows[shadow_index+1]; + ++shadow_index; + } + pool->shadows[capacity-1].pool_next = NULL; +} + +void mt_init_shadow_pool(MtShadowPool *pool, usz_t capacity) +{ + pool->capacity = capacity; + pool->continuation = NULL; + pool->shadows = calloc(sizeof(MtShadow), capacity); + pool->first_free = pool->shadows; + mt_init_shadow_pool_allocation(pool); +} + +void mt_cleanup_shadow_pool(MtShadowPool *pool) +{ + if(pool->continuation != NULL) + { + mt_cleanup_shadow_pool(pool->continuation); + free(pool->continuation); + } + free(pool->shadows); +} + +void mt_free_shadow_pool(MtShadowPool *pool) +{ + mt_cleanup_shadow_pool(pool); + free(pool); +} + +MtShadowPool * mt_new_shadow_pool(usz_t capacity) +{ + MtShadowPool *pool = malloc(sizeof(MtShadowPool)); + mt_init_shadow_pool(pool, capacity); + return pool; +} + +MtShadow * mt_pool_shadow(MtShadowPool *pool) +{ + if(pool->first_free == NULL) + { + if(pool->continuation == NULL) + pool->continuation = mt_new_shadow_pool(pool->capacity * 2); + return mt_pool_shadow(pool->continuation); + } + MtShadow *result = pool->first_free; + pool->first_free = result->pool_next; + return result; +} + +void mt_unpool_shadow(MtShadow *shadow) +{ + shadow->pool_next = shadow->pool->first_free; + shadow->pool->first_free = shadow; +} \ No newline at end of file diff --git a/core/src-c/shadow-registry.c b/core/src-c/shadow-registry.c new file mode 100644 index 0000000..af8e090 --- /dev/null +++ b/core/src-c/shadow-registry.c @@ -0,0 +1,80 @@ +#include +#include +#include + +void mt_delete_shadow_lookup_tree_of_registry(MtShadowRegistry *registry); + +MtShadowRegistry mt_create_shadow_registry(void *context_ptr) +{ + MtShadowRegistry registry; + registry.id_counter = 1; + registry.context_ptr = context_ptr; + registry.lookup_tree = mt_create_shadow_lookup_tree(); + mt_init_shadow_pool(®istry.root_pool, 16384); + return registry; +} + +void mt_cleanup_shadow_registry(MtShadowRegistry *registry) +{ + mt_delete_shadow_lookup_tree_of_registry(registry); + mt_cleanup_shadow_pool(®istry->root_pool); +} + +void mt_cleanup_shadow_data(MtShadow *shadow) +{ + if(shadow->tag_chain_start != NULL) + mt_free_shadow_tag_chain(shadow->tag_chain_start); +} + +void mt_delete_shadow_lookup_tree_of_registry(MtShadowRegistry *registry) +{ + MtShadowLookupTree *lookup_tree = ®istry->lookup_tree; + u32_t index_1 = 0; + while(index_1 < 256) + { + MtShadowLookupLevel1 *level_1 = lookup_tree->next[index_1]; + if(level_1 == NULL) + { + ++index_1; + continue; + } + u32_t index_2 = 0; + while(index_2 < 256) + { + MtShadowLookupLevel2 *level_2 = level_1->next[index_2]; + if(level_2 == NULL) + { + ++index_2; + continue; + } + u32_t index_3 = 0; + while(index_3 < 256) + { + MtShadowLookupLevel3 *level_3 = level_2->next[index_3]; + if(level_3 == NULL) + { + ++index_3; + continue; + } + u32_t index_4 = 0; + while(index_4 < 256) + { + MtShadow *shadow = level_3->next[index_4]; + if(shadow == NULL) + { + ++index_4; + continue; + } + mt_cleanup_shadow_data(shadow); + ++index_4; + } + free(level_3); + ++index_3; + } + free(level_2); + ++index_2; + } + free(level_1); + ++index_1; + } +} diff --git a/core/tests/internal/shadow-lookup/include_paths.txt b/core/tests/internal/shadow-lookup/include_paths.txt new file mode 100644 index 0000000..2dda37e --- /dev/null +++ b/core/tests/internal/shadow-lookup/include_paths.txt @@ -0,0 +1 @@ +core/inc-c \ No newline at end of file diff --git a/core/tests/internal/shadow-lookup/main.c b/core/tests/internal/shadow-lookup/main.c new file mode 100644 index 0000000..d8bdffa --- /dev/null +++ b/core/tests/internal/shadow-lookup/main.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + +MtShadowRegistry registry; + +void cleanup_and_exit(int status_code) +{ + mt_cleanup_shadow_registry(®istry); +} + +void signal_handler(int number) +{ + printf("FAIL: The program crashed because of a memory access error!\n"); + exit(-8); +} + +int main(int argc, char **argv) +{ + signal(SIGSEGV, &signal_handler); + registry = mt_create_shadow_registry(NULL); + MtShadow *original_1 = mt_create_shadow(®istry); + MtShadow *lookedup_1 = mt_lookup_shadow(®istry, original_1->identifier); + + MtShadow *original_2 = mt_create_shadow(®istry); + MtShadow *lookedup_2 = mt_lookup_shadow(®istry, original_2->identifier); + + if(original_1 != lookedup_1) + { + puts("FAIL: In test case 1, the original shadow doesn't match the looked-up one."); + printf("O %p : L %p\n", original_1, lookedup_1); + cleanup_and_exit(-1); + } + if(original_2 != lookedup_2) + { + puts("FAIL: In test case 2, the original shadow doesn't match the looked-up one."); + printf("O %p : L %p\n", original_2, lookedup_2); + cleanup_and_exit(-2); + } + if(original_1 == original_2) + { + puts("FAIL: In test case 3, the first original shadow matches the second!"); + cleanup_and_exit(-3); + } + if(lookedup_1 == lookedup_2) + { + puts("FAIL: In test case 3, the first looked-up shadow matches the second!"); + cleanup_and_exit(-4); + } + puts("Success."); + cleanup_and_exit(0); + return 0; +}