From 70fdbb348cdd02049eb37577f63963f994473fd4 Mon Sep 17 00:00:00 2001 From: hwwang Date: Wed, 3 Jul 2024 20:29:42 +0800 Subject: [PATCH] need modify thirdparty hashmap --- .env | 2 +- .gitmodules | 3 + .vscode/launch.json | 25 ++++- .vscode/settings.json | 13 ++- runtime/Makefile | 8 +- runtime/include/hash.h | 52 +++++++++ runtime/include/map.h | 193 ++++++++++++++++++++++++++++++++++ runtime/include/module.h | 6 +- runtime/include/xmalloc.h | 14 +++ runtime/src/current_sandbox.c | 28 ++++- runtime/src/module.c | 93 ++++++++++++++-- runtime/tests/Makefile | 7 +- runtime/tests/graph.json | 16 +++ runtime/thirdparty/Makefile | 7 +- runtime/thirdparty/hashmap | 1 + runtime/utest/map | Bin 0 -> 16696 bytes runtime/utest/maptest.c | 77 ++++++++++++++ sledge.log | 24 +++++ 18 files changed, 541 insertions(+), 28 deletions(-) create mode 100644 runtime/include/hash.h create mode 100644 runtime/include/map.h create mode 100644 runtime/include/xmalloc.h create mode 100644 runtime/tests/graph.json create mode 160000 runtime/thirdparty/hashmap create mode 100755 runtime/utest/map create mode 100644 runtime/utest/maptest.c create mode 100755 sledge.log diff --git a/.env b/.env index 25bcbe5..f5db799 100644 --- a/.env +++ b/.env @@ -1,3 +1,3 @@ -LD_LIBRARY_PATH=/home/hai/sledge-serverless-framework/runtime/bin +LD_LIBRARY_PATH=/home/hai/sledge-old/runtime/bin SLEDGE_SCHEDULER=EDF SLEDGE_SANDBOX_PERF_LOG=/home/hai/sledge-serverless-framework/debuglog.txt diff --git a/.gitmodules b/.gitmodules index 0dd3c7c..0fc0e82 100644 --- a/.gitmodules +++ b/.gitmodules @@ -11,6 +11,9 @@ url = https://github.com/gwsystems/ck.git [submodule "jsmn"] path = runtime/thirdparty/jsmn url = https://github.com/gwsystems/jsmn.git +[submodule "hash"] +path = runtime/thirdparty/hashmap +url = https://github.com/tidwall/hashmap.c.git [submodule "runtime/tests/gocr"] path = runtime/tests/gocr url = https://github.com/gwsystems/gocr.git diff --git a/.vscode/launch.json b/.vscode/launch.json index 670e39e..84201fc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -47,6 +47,29 @@ "ignoreFailures": true } ] + }, + { + "name": "graph", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/runtime/bin/sledgert", + "args": [ + "${workspaceFolder}/runtime/tests/graph.json" + ], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "sourceFileMap": {"/sledge/runtime": "${workspaceFolder}/runtime"}, + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "envFile": "${workspaceFolder}/.env", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] } ] -} \ No newline at end of file +} diff --git a/.vscode/settings.json b/.vscode/settings.json index ee67b69..ce4f9d8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -95,7 +95,15 @@ "compare": "c", "cstdint": "c", "format": "c", - "jsmn.h": "c" + "jsmn.h": "c", + "__bit_reference": "c", + "algorithm": "c", + "lock_time.h": "c", + "mcs.h": "c", + "map.h": "c", + "stdio.h": "c", + "hashmap.h": "c", + "mutex": "cpp" }, "files.exclude": { "**/.git": true, @@ -144,6 +152,7 @@ "**/runtime/thirdparty/http-parser/**": true, "**/runtime/thirdparty/jsmn/**": true, "**/runtime/thirdparty/dist/**": true, + "**/runtime/thirdparty/hashmap/**": true, "*.o": true, "*.bc": true, "*.wasm": true @@ -207,4 +216,4 @@ "C_Cpp_Runner.msvcSecureNoWarnings": false, "git.detectSubmodules": true, "git.enabled": true -} \ No newline at end of file +} diff --git a/runtime/Makefile b/runtime/Makefile index bfce289..5dc1f3e 100644 --- a/runtime/Makefile +++ b/runtime/Makefile @@ -10,10 +10,10 @@ PAGE_SIZE := $(shell getconf PAGESIZE) # Compiler Settings CC=clang -CC_OPTIONS = -O3 -flto -g -pthread -D_GNU_SOURCE +# CC_OPTIONS = -O3 -flto -g -pthread -D_GNU_SOURCE # CC_OPTIONS for Debugging -# CC_OPTIONS = -O0 -g -pthread -D_GNU_SOURCE +CC_OPTIONS = -O0 -g -pthread -D_GNU_SOURCE # CFI Sanitizer # CC_OPTIONS = -O0 -g -pthread -D_GNU_SOURCE -flto -fvisibility=default -fsanitize=cfi @@ -59,8 +59,8 @@ CFLAGS += -DLOG_TO_FILE # CFLAGS += -DLOG_PREEMPTION # CFLAGS += -DLOG_MODULE_LOADING # CFLAGS += -DOPT_AVOID_GLOBAL_QUEUE -# CFLAGS += -DLOG_RUNTIME_FILE_LOG - CFLAGS += -DLOG_RUNTIME_MEM_LOG +CFLAGS += -DLOG_RUNTIME_FILE_LOG +CFLAGS += -DLOG_RUNTIME_MEM_LOG # This dumps per module *.csv files containing the cycle a sandbox has been in RUNNING when each # page is allocated. This helps understand the relationship to memory allocation and execution time. diff --git a/runtime/include/hash.h b/runtime/include/hash.h new file mode 100644 index 0000000..6d1049d --- /dev/null +++ b/runtime/include/hash.h @@ -0,0 +1,52 @@ +#pragma once + +#include "hashmap.h" +#include "lock.h" +#include "xmalloc.h" + +typedef struct +{ + struct hashmap* map; + lock_t lock; +}lockhashmap; + +static inline lockhashmap +*hashmap_lock_new( + size_t elsize, size_t cap, uint64_t seed0, + uint64_t seed1, + uint64_t (*hash)(const void *item, uint64_t seed0, uint64_t seed1), + int (*compare)(const void *a, const void *b, void *udata), + void (*elfree)(void *item), + void *udata +) +{ + lockhashmap* node = (lockhashmap *)xmalloc(sizeof(lockhashmap)); + node->map = hashmap_new(elsize, cap, seed0, seed1, hash, compare, elfree, udata); + LOCK_INIT(&node->lock); + return node; +} + +/*void threadsafe_hashmap_free(ThreadSafeHashmap *thm) { + if (thm) { + spinlock_acquire(&thm->lock); + hashmap_free(thm->map); + spinlock_release(&thm->lock); + spinlock_destroy(&thm->lock); + free(thm); + } +} + +bool threadsafe_hashmap_set(ThreadSafeHashmap *thm, const void *item) { + spinlock_acquire(&thm->lock); + const void *result = hashmap_set(thm->map, item); + spinlock_release(&thm->lock); + return result != NULL; +} + +const void *threadsafe_hashmap_get(ThreadSafeHashmap *thm, const void *item) { + spinlock_acquire(&thm->lock); + const void *result = hashmap_get(thm->map, item); + spinlock_release(&thm->lock); + return result; +} +*/ diff --git a/runtime/include/map.h b/runtime/include/map.h new file mode 100644 index 0000000..047d716 --- /dev/null +++ b/runtime/include/map.h @@ -0,0 +1,193 @@ +#pragma once + +#include +#include +#include +#include + +#include "lock.h" +#include "xmalloc.h" + +/* Simple K-V store based on The Practice of Programming by Kernighan and Pike */ + +/* Bucket count is sized to be a prime that is approximately 20% larger than the desired capacity (6k keys) */ +#define MAP_BUCKET_COUNT 7907 +#define MAP_HASH jenkins_hash + +struct map_node { + struct map_node *next; + char *key; + void *value; + uint32_t key_len; + uint32_t value_len; + uint32_t hash; +}; + +struct map_bucket { + lock_t lock; + struct map_node *head; +}; + +struct hashmap { + struct map_bucket buckets[MAP_BUCKET_COUNT]; +}; + +static inline void +map_init(struct hashmap *restrict map) +{ + for (int i = 0; i < MAP_BUCKET_COUNT; i++) { + map->buckets[i].head = NULL; + LOCK_INIT(&map->buckets[i].lock); + } +}; + +/* See https://en.wikipedia.org/wiki/Jenkins_hash_function */ +static inline uint32_t +jenkins_hash(char *key, uint32_t key_len) +{ + uint32_t i = 0; + uint32_t hash = 0; + while (i != key_len) { + hash += key[i++]; + hash += hash << 10; + hash ^= hash >> 6; + } + hash += hash << 3; + hash ^= hash >> 11; + hash += hash << 15; + return hash; +} + +static inline void * +map_get(struct hashmap *map, char *key, uint32_t key_len, uint32_t *ret_value_len) +{ + void *value = NULL; + + uint32_t hash = MAP_HASH(key, key_len); + + struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT]; + + LOCK_LOCK(&bucket->lock); + for (struct map_node *node = bucket->head; node != NULL; node = node->next) { + if (node->hash == hash) { + value = node->value; + *ret_value_len = node->value_len; + goto DONE; + } + } + + if (value == NULL) *ret_value_len = 0; + +DONE: + LOCK_UNLOCK(&bucket->lock); + return value; +} + +static inline bool +map_set(struct hashmap *map, char *key, uint32_t key_len, void *value, uint32_t value_len) +{ + bool did_set = false; + + uint32_t hash = MAP_HASH(key, key_len); + struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT]; + LOCK_LOCK(&bucket->lock); + for (struct map_node *node = bucket->head; node != NULL; node = node->next) { + if (node->hash == hash) goto DONE; + } + + struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node)); + *(new_node) = (struct map_node){ .hash = hash, + .key = xmalloc(key_len), + .key_len = key_len, + .value = value, + .value_len = value_len, + .next = bucket->head }; + + // Copy Key and Value + memcpy(new_node->key, key, key_len); + //memcpy(new_node->value, value, value_len); + + bucket->head = new_node; + did_set = true; + +DONE: + LOCK_UNLOCK(&bucket->lock); + return did_set; +} + +/** + * @returns boolean if node was deleted or not + */ +static inline bool +map_delete(struct hashmap *map, char *key, uint32_t key_len) +{ + bool did_delete = false; + + uint32_t hash = MAP_HASH(key, key_len); + struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT]; + LOCK_LOCK(&bucket->lock); + + struct map_node *prev = bucket->head; + if (prev != NULL && prev->hash == hash) { + bucket->head = prev->next; + free(prev->key); + //free(prev->value); + free(prev); + did_delete = true; + goto DONE; + } + + for (struct map_node *node = prev->next; node != NULL; prev = node, node = node->next) { + prev->next = node->next; + free(node->key); + //free(node->value); + free(node); + did_delete = true; + goto DONE; + } + +DONE: + LOCK_UNLOCK(&bucket->lock); + return did_delete; +} + +/* static inline void +map_upsert(struct hashmap *map, char *key, uint32_t key_len, void *value, uint32_t value_len) +{ + uint32_t hash = MAP_HASH(key, key_len); + struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT]; + LOCK_LOCK(&bucket->lock); + + for (struct map_node *node = bucket->head; node != NULL; node = node->next) { + if (node->hash == hash) { + node->value_len = value_len; + //node->value = realloc(node->value, value_len); + node->value = value; + assert(node->value); + //memcpy(node->value, value, value_len); + goto DONE; + } + } + + struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node)); + + *(new_node) = (struct map_node){ .hash = hash, + .key = xmalloc(key_len), + .key_len = key_len, + .value = xmalloc(value_len), + .value_len = value_len, + .next = bucket->head }; + + assert(new_node->key); + assert(new_node->value); + + // Copy Key and Value + memcpy(new_node->key, key, key_len); + new_node->value = value; + //memcpy(new_node->value, value, value_len); + + bucket->head = new_node; + +DONE: + LOCK_UNLOCK(&bucket->lock); +} */ diff --git a/runtime/include/module.h b/runtime/include/module.h index 76f757a..27a1e89 100644 --- a/runtime/include/module.h +++ b/runtime/include/module.h @@ -78,7 +78,11 @@ struct module { /* Entry Function to invoke serverless function */ mod_main_fn_t main; - struct module *next_module; /* the next module in the chain */ + struct module **next_module; /* the next module in the DAG */ + struct module **pre_module; /* the previous module in the DAG */ + char **next_module_names; /* the next modules name in the DAG */ + uint32_t next_module_count; + uint32_t pre_module_count; }; /************************* diff --git a/runtime/include/xmalloc.h b/runtime/include/xmalloc.h new file mode 100644 index 0000000..8449da0 --- /dev/null +++ b/runtime/include/xmalloc.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +#include "likely.h" +#include "panic.h" + +static inline void * +xmalloc(size_t size) +{ + void *allocation = malloc(size); + if (unlikely(allocation == NULL)) panic("xmalloc failed!\n"); + return allocation; +} diff --git a/runtime/src/current_sandbox.c b/runtime/src/current_sandbox.c index 9ef5819..8159c72 100644 --- a/runtime/src/current_sandbox.c +++ b/runtime/src/current_sandbox.c @@ -8,6 +8,8 @@ #include "scheduler.h" #include "module.h" #include "software_interrupt.h" +#include "map.h" +#include "hashmap.h" extern uint64_t system_start_timestamp; @@ -70,7 +72,17 @@ current_sandbox_start(void) char *error_message = ""; sandbox_initialize_stdio(sandbox); - struct module * next_module = sandbox->module->next_module; + int next_module_idx = sandbox->module->next_module_count; + static struct hashmap *sandbox_req_map = NULL; + if (sandbox_req_map == NULL) { + sandbox_req_map = malloc(sizeof(struct hashmap)); + assert(sandbox_req_map != NULL); + map_init(sandbox_req_map); + } + + + + struct module **next_module = sandbox->module->next_module; /* * Add the client fd to epoll if it is the first or last sandbox in the chain because they @@ -131,9 +143,15 @@ current_sandbox_start(void) //uint64_t current_rs = enqueue_timestamp - system_start_timestamp; //mem_log("time %lu request id:%d executing, name:%s remaining slack %lu\n", current_rs, // sandbox->id, sandbox->module->name, sandbox->remaining_slack); - struct sandbox_request *sandbox_request = - sandbox_request_allocate(next_module, false, sandbox->request_length, - next_module->name, sandbox->client_socket_descriptor, + assert(next_module_idx); + assert(next_module); + for (size_t i = 0; i < next_module_idx; i++) + { + struct module * next_module_node = next_module[i]; + assert(next_module_node); + struct sandbox_request *sandbox_request = + sandbox_request_allocate(next_module_node, false, sandbox->request_length, + next_module_node->name, sandbox->client_socket_descriptor, (const struct sockaddr *)&sandbox->client_address, sandbox->request_arrival_timestamp, enqueue_timestamp, sandbox->remaining_slack, true, pre_func_output, output_length); @@ -166,6 +184,8 @@ current_sandbox_start(void) sandbox_remove_from_epoll(sandbox); } sandbox_set_as_returned(sandbox, SANDBOX_RUNNING); + + } } else { /* Retrieve the result, construct the HTTP response, and send to client */ if (sandbox_send_response(sandbox) < 0) { diff --git a/runtime/src/module.c b/runtime/src/module.c index f0810fe..63ffaa2 100644 --- a/runtime/src/module.c +++ b/runtime/src/module.c @@ -19,6 +19,7 @@ const int JSON_MAX_ELEMENT_COUNT = 16; const int JSON_MAX_ELEMENT_SIZE = 1024; +const int PRE_MODULE_COUNT = 4; /************************* * Private Static Inline * @@ -374,7 +375,11 @@ module_new_from_json(char *file_name) int module_count = 0; char *request_headers = NULL; char *reponse_headers = NULL; - struct module *tail_module = NULL; + //struct module *tail_module = NULL; + struct module **nodes = malloc(JSON_MAX_ELEMENT_COUNT * sizeof(struct module*)); + if (nodes == NULL) { + fprintf(stderr, "Memory allocation failed for nodes array\n"); + } for (int i = 0; i < total_tokens; i++) { assert(tokens[i].type == JSMN_OBJECT); @@ -397,6 +402,8 @@ module_new_from_json(char *file_name) } memset(reponse_headers, 0, HTTP_MAX_HEADER_LENGTH * HTTP_MAX_HEADER_COUNT); + uint32_t next_module_count = 0; + uint32_t pre_module_count = 0; int32_t request_size = 0; int32_t response_size = 0; int32_t argument_count = 0; @@ -412,6 +419,7 @@ module_new_from_json(char *file_name) int ntoks = 2 * tokens[i].size; char request_content_type[HTTP_MAX_HEADER_VALUE_LENGTH] = { 0 }; char response_content_type[HTTP_MAX_HEADER_VALUE_LENGTH] = { 0 }; + char **next_module_names = NULL; for (; j < ntoks;) { int ntks = 1; @@ -445,6 +453,28 @@ module_new_from_json(char *file_name) argument_count = atoi(val); if (argument_count < 0 || argument_count > 127) panic("Expected argument count between 0 and 127, saw %d\n", argument_count); + } else if (strcmp(key, "pre_module_count") == 0) + { + pre_module_count = atoi(val); + if (pre_module_count < 0) + panic("Expected pre_module_count to be nonnegative, saw %d\n", pre_module_count); + } else if (strcmp(key, "next_modules") == 0) + { + assert(tokens[i + j + 1].type == JSMN_ARRAY); + request_count = tokens[i + j + 1].size; + ntks += request_count; + ntoks += request_count; + next_module_names = malloc(request_count * sizeof(char *)); + next_module_count = request_count; + int array_index = 0; + for (int k = 1; k <= request_count; k++) { + jsmntok_t *g = &tokens[i + j + k + 1]; + int name_length = g->end - g->start; + next_module_names[array_index] = malloc(name_length + 1); + strncpy(next_module_names[array_index], file_buffer + g->start, name_length); + next_module_names[array_index][name_length] = '\0'; + array_index++; + } } else if (strcmp(key, "active") == 0) { assert(tokens[i + j + 1].type == JSMN_PRIMITIVE); if (val[0] == 't') { @@ -566,28 +596,71 @@ module_new_from_json(char *file_name) relative_deadline_us, port, request_size, response_size, admissions_percentile, expected_execution_us); if (module == NULL) goto module_new_err; + module->next_module_names = malloc(next_module_count * sizeof(struct module*)); + for (int i = 0; i < next_module_count; i++) { + module->next_module_names[i] = strdup(next_module_names[i]); + if (module->next_module_names[i] == NULL) { + fprintf(stderr, "Memory allocation failed for next_module_names[%d].\n", i); + exit(EXIT_FAILURE); + } + } + if (module->next_module_names == NULL) + { + panic("Failed to allocate memory for next_module_names"); + } + module->next_module_count = next_module_count; + module->pre_module_count = pre_module_count; + module->next_module = NULL; + module->pre_module = NULL; assert(module); - - if (tail_module != NULL) { tail_module->next_module = module; } - tail_module = module; - tail_module->next_module = NULL; - - /* if this is the tail module, reset tail_module to NULL to build another new chain */ - if (is_tail_module) { - tail_module = NULL; - } module_set_http_info(module, request_count, request_headers, request_content_type, response_count, reponse_headers, response_content_type); + nodes[module_count] = module; module_count++; } free(request_headers); free(reponse_headers); + for (int i = 0; i < next_module_count; i++) { + free(next_module_names[i]); // 释放每个字符串的内存 + } + free(next_module_names); // 最后释放指针数组的内存 } if (module_count == 0) panic("%s contained no active modules\n", file_name); + + for (ssize_t i = 0; i < module_count; i++) { + assert(nodes[i]); + ssize_t count = nodes[i]->next_module_count; + + if (count == 0) continue; + nodes[i]->next_module = (struct module**) malloc(count * sizeof(struct module*)); + if (nodes[i]->next_module == NULL) panic("Failed to allocate memory for next_module"); + + for (size_t j = 0; j < count; j++) { + for (size_t m = i + 1; m < module_count; m++) { + if (strcmp(nodes[i]->next_module_names[j], nodes[m]->name) == 0) { + assert(nodes[m]); + uint32_t precount = nodes[m]->pre_module_count; + if (nodes[m]->pre_module == NULL) { + nodes[m]->pre_module = (struct module**) malloc(precount * sizeof(struct module*)); + if (nodes[m]->pre_module == NULL) panic("Failed to allocate memory for pre_module"); + } + nodes[i]->next_module[j] = nodes[m]; + int preflag = 0; + while (nodes[m]->pre_module[preflag]) { + preflag++; + assert(preflag < precount); + } + nodes[m]->pre_module[preflag] = nodes[i]; + break; + } + } + } + } + free(nodes); #ifdef LOG_MODULE_LOADING debuglog("Loaded %d module%s!\n", module_count, module_count > 1 ? "s" : ""); #endif diff --git a/runtime/tests/Makefile b/runtime/tests/Makefile index ec79e33..04deabc 100644 --- a/runtime/tests/Makefile +++ b/runtime/tests/Makefile @@ -2,16 +2,17 @@ include Makefile.inc #TESTS=fibonacci fibonacci2 fibonacci3 big_fibonacci C-Image-Manip empty work work1k work10k work100k work1m forever filesys sockserver sockclient empty TESTS=fibonacci big_fibonacci C-Image-Manip empty work work1k work10k work100k work1m forever filesys sockserver sockclient empty - +TESTS2= TESTSRT=$(TESTS:%=%_rt) - -.PHONY: all clean rttests tinyekf cifar10 gocr sod +TESTSRT2=$(TESTS2:%=%_rt) +.PHONY: all clean rttests tinyekf cifar10 gocr sod add all: rttests tinyekf cifar10 gocr sod @echo "Test Compilation done!" rttests: $(TESTSRT) +add: $(TESTSRT2) clean: @echo "Cleaning Test Applications" diff --git a/runtime/tests/graph.json b/runtime/tests/graph.json new file mode 100644 index 0000000..a0d128b --- /dev/null +++ b/runtime/tests/graph.json @@ -0,0 +1,16 @@ +{ + "active": true, + "name": "work", + "path": "work_wasm.so", + "port": 10000, + "relative-deadline-us": 50000, + "argsize": 1, + "pre_module_count": 0, + "next_modules": [], + "http-req-headers": [], + "http-req-content-type": "text/plain", + "http-req-size": 1048776, + "http-resp-headers": [], + "http-resp-size": 1048776, + "http-resp-content-type": "text/plain" +} diff --git a/runtime/thirdparty/Makefile b/runtime/thirdparty/Makefile index ed69cc7..c85cb59 100644 --- a/runtime/thirdparty/Makefile +++ b/runtime/thirdparty/Makefile @@ -3,7 +3,7 @@ DIST_PREFIX=${CURR_DIR}/dist/ all: clean build -build: ck jsmn http-parser +build: ck jsmn http-parser hashmap ck: mkdir -p ${DIST_PREFIX} @@ -19,8 +19,11 @@ jsmn: mkdir -p ${DIST_PREFIX}/include/ cp jsmn/jsmn.h ${DIST_PREFIX}/include/ +hashmap: hashmap/hashmap.c + cd hashmap; $(CC) $(CFLAGS) -I. -c hashmap.c; mv hashmap.o ${DIST_PREFIX}/lib/; cp hashmap.h ${DIST_PREFIX}/include/ + clean: make -C ck uninstall rm -rf ${DIST_PREFIX} -.PHONY: clean all build ck jsmn http-parser +.PHONY: clean all build ck jsmn http-parser hashmap diff --git a/runtime/thirdparty/hashmap b/runtime/thirdparty/hashmap new file mode 160000 index 0000000..1c13992 --- /dev/null +++ b/runtime/thirdparty/hashmap @@ -0,0 +1 @@ +Subproject commit 1c139923fe08f36143ecc0ba37cd674684f87f9c diff --git a/runtime/utest/map b/runtime/utest/map new file mode 100755 index 0000000000000000000000000000000000000000..4095234ca7cbbeaa100992921bad08912dfe2742 GIT binary patch literal 16696 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 literal 0 HcmV?d00001 diff --git a/runtime/utest/maptest.c b/runtime/utest/maptest.c new file mode 100644 index 0000000..eea9ca4 --- /dev/null +++ b/runtime/utest/maptest.c @@ -0,0 +1,77 @@ +#include "../include/map.h" +#include +#include + +typedef struct { + int id; + char name[100]; + float salary; +} Employee; + + +int main() { + // 初始化哈希表 + struct hashmap myMap; + map_init(&myMap); + + // 创建并初始化一些 Employee 结构体 + Employee *alice = malloc(sizeof(Employee)); + alice->id = 1; + strcpy(alice->name, "Alice"); + alice->salary = 50000.0; + + Employee *bob = malloc(sizeof(Employee)); + bob->id = 2; + strcpy(bob->name, "Bob"); + bob->salary = 52000.0; + + // 将 Employee 结构体存入哈希表 + char *key1 = "employee1"; + map_set(&myMap, key1, strlen(key1), alice, sizeof(Employee*)); + + char *key2 = "employee2"; + map_set(&myMap, key2, strlen(key2), bob, sizeof(Employee*)); + + // 尝试从哈希表中检索 Employee + uint32_t ret_value_len; + Employee *retrieved_employee = (Employee *)map_get(&myMap, key1, strlen(key1), &ret_value_len); + if (retrieved_employee) { + printf("Retrieved Employee: %s, ID: %d, Salary: %.2f\n", + retrieved_employee->name, retrieved_employee->id, retrieved_employee->salary); + } else { + printf("Employee not found.\n"); + } + alice->id = 12; + char *key3 = "employee1"; + strcat(alice->name, key3); + retrieved_employee = (Employee *)map_get(&myMap, key1, strlen(key1), &ret_value_len); + if (retrieved_employee) { + printf("Retrieved Employee: %s, ID: %d, Salary: %.2f\n", + retrieved_employee->name, retrieved_employee->id, retrieved_employee->salary); + } else { + printf("Employee not found.\n"); + } + map_delete(&myMap, key1, strlen(key1)); + retrieved_employee = (Employee *)map_get(&myMap, key1, strlen(key1), &ret_value_len); + if (retrieved_employee) { + printf("Retrieved Employee: %s, ID: %d, Salary: %.2f\n", + retrieved_employee->name, retrieved_employee->id, retrieved_employee->salary); + } else { + printf("Employee not found.\n"); + } + map_set(&myMap, key1, strlen(key1), alice, sizeof(Employee*)); + retrieved_employee = (Employee *)map_get(&myMap, key1, strlen(key1), &ret_value_len); + if (retrieved_employee) { + printf("Retrieved Employee: %s, ID: %d, Salary: %.2f\n", + retrieved_employee->name, retrieved_employee->id, retrieved_employee->salary); + } else { + printf("Employee not found.\n"); + } + + // 清理 + free(alice); + free(bob); + + // 也许还需要遍历哈希表并释放所有节点,这里假设只是一个简单的示例 + return 0; +} diff --git a/sledge.log b/sledge.log new file mode 100755 index 0000000..85c256d --- /dev/null +++ b/sledge.log @@ -0,0 +1,24 @@ +Runtime Environment: + CPU Speed: 2400 MHz + Processor Speed: 2400 MHz + RLIMIT_DATA: Infinite + RLIMIT_NOFILE: 1048576 (Increased from 8192) + Core Count: 8 + Listener core ID: 1 + First Worker core ID: 2 + Worker core count: 6 + Scheduler Policy: EDF + Sigalrm Policy: BROADCAST + Preemption: Enabled + Quantum: 5000 us + Sandbox Performance Log: /home/hai/sledge-serverless-framework/debuglog.txt +Starting listener thread + Listener core thread: 7ffff7a006c0 +Starting 6 worker thread(s) +C: 01, T: 0x7ffff7bfdd80, F: runtime_start_runtime_worker_threads> + Sandboxing environment ready! + +C: 01, T: 0x7ffff7bfdd80, F: module_new> + Stack Size: 524288 +sledgert: src/software_interrupt.c:181: void software_interrupt_handle_signals(int, siginfo_t *, void *): Assertion `TEST_RECORDING_BUFFER_LEN > software_interrupt_SIGALRM_kernel_count + software_interrupt_SIGALRM_thread_count' failed. +sledgert: src/software_interrupt.c:181: void software_interrupt_handle_signals(int, siginfo_t *, void *): Assertion `TEST_RECORDING_BUFFER_LEN > software_interrupt_SIGALRM_kernel_count + software_interrupt_SIGALRM_thread_count' failed.