Added shadow entity lookup, registry and pool.

This commit is contained in:
Eric-Paul Ickhorn 2024-03-02 08:15:51 +01:00
parent 726c231561
commit 3d73718aee
8 changed files with 378 additions and 1 deletions

View File

@ -1 +1,2 @@
tests/internal/shadow-tag
tests/internal/shadow-lookup

View File

@ -4,10 +4,12 @@
#include <librr/types.h>
#include <shadow-tag.h>
#include <shadow.h>
typedef struct MtContext
{
MtShadowTagSystem shadow_tag_system;
MtShadowRegistry *shadow_registry;
} MtContext;
#endif // MT_CONTEXT_H

82
core/inc-c/shadow.h Normal file
View File

@ -0,0 +1,82 @@
#ifndef MT_SHADOW_H
#define MT_SHADOW_H
#include <librr/types.h>
#include <shadow-tag.h>
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

View File

@ -0,0 +1,90 @@
#include <shadow.h>
#include <context.h>
#include <stdlib.h>
#include <librr/memory.h>
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(&registry->root_pool);
shadow->identifier = registry->id_counter;
shadow->context = registry->context_ptr;
shadow->tag_chain_start = NULL;
mt_write_shadow_lookup_entry(&registry->lookup_tree, shadow);
return shadow;
}

66
core/src-c/shadow-pool.c Normal file
View File

@ -0,0 +1,66 @@
#include <shadow.h>
#include <stdlib.h>
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;
}

View File

@ -0,0 +1,80 @@
#include <shadow.h>
#include <librr/memory.h>
#include <stdlib.h>
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(&registry.root_pool, 16384);
return registry;
}
void mt_cleanup_shadow_registry(MtShadowRegistry *registry)
{
mt_delete_shadow_lookup_tree_of_registry(registry);
mt_cleanup_shadow_pool(&registry->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 = &registry->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;
}
}

View File

@ -0,0 +1 @@
core/inc-c

View File

@ -0,0 +1,55 @@
#include <shadow.h>
#include <context.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
MtShadowRegistry registry;
void cleanup_and_exit(int status_code)
{
mt_cleanup_shadow_registry(&registry);
}
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(&registry);
MtShadow *lookedup_1 = mt_lookup_shadow(&registry, original_1->identifier);
MtShadow *original_2 = mt_create_shadow(&registry);
MtShadow *lookedup_2 = mt_lookup_shadow(&registry, 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;
}