From dd4354d7409ade206984c1aa8609060f314ab128 Mon Sep 17 00:00:00 2001 From: Richard Ore Date: Sat, 12 Oct 2024 06:51:49 +0100 Subject: [PATCH] Partially-Functional Draft 3 --- .github/workflows/ci.yml | 4 +- .github/workflows/release.yml | 4 +- CMakeLists.txt | 3 +- scripts/install.sh | 18 ++++++++ src/standard/thread.c | 86 +++++++++++++++++++++++++++++------ src/vm.c | 67 --------------------------- src/vm.h | 3 -- thirdparty/threads/threads.h | 14 ++++-- 8 files changed, 107 insertions(+), 92 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 473fe9ae..b58fad1b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: run: | sudo apt-get update sudo apt-get remove libgd3 - sudo apt-get install curl libcurl4-openssl-dev libgd-dev libavif-dev libffi-dev -y + sudo apt-get install curl libpthread-stubs0-dev libcurl4-openssl-dev libgd-dev libavif-dev libffi-dev -y cmake -B . cmake --build . -- -j 12 chmod +x blade/blade @@ -99,7 +99,7 @@ jobs: run: | ${{ env.VCPKG_ROOT }}/vcpkg update ${{ env.VCPKG_ROOT }}/vcpkg version - ${{ env.VCPKG_ROOT }}/vcpkg install pkgconf curl:x64-windows libffi:x64-windows openssl:x64-windows libgd:x64-windows + ${{ env.VCPKG_ROOT }}/vcpkg install pkgconf pthreads:x64-windows curl:x64-windows libffi:x64-windows openssl:x64-windows libgd:x64-windows ${{ env.VCPKG_ROOT }}/vcpkg list - name: Save vcpkg dependencies cache id: vcpkg-cache-save diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c328860b..cc6131a0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: run: | sudo apt-get update sudo apt-get remove libgd3 - sudo apt-get install curl libcurl4-openssl-dev libgd-dev libavif-dev libffi-dev -y + sudo apt-get install curl libpthread-stubs0-dev libcurl4-openssl-dev libgd-dev libavif-dev libffi-dev -y cmake -B . cmake --build . -- -j 12 - name: Create ZIP Archive @@ -94,7 +94,7 @@ jobs: run: | ${{ env.VCPKG_ROOT }}/vcpkg update ${{ env.VCPKG_ROOT }}/vcpkg version - ${{ env.VCPKG_ROOT }}/vcpkg install pkgconf curl:x64-windows libffi:x64-windows openssl:x64-windows libgd:x64-windows + ${{ env.VCPKG_ROOT }}/vcpkg install pkgconf pthreads:x64-windows curl:x64-windows libffi:x64-windows openssl:x64-windows libgd:x64-windows ${{ env.VCPKG_ROOT }}/vcpkg list - name: Compile run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 4efa3efe..b29fe3a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,11 +190,12 @@ if(UNIX) target_link_libraries(libblade PRIVATE m) if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - target_link_libraries(libblade PRIVATE pthread) target_link_libraries(libblade PRIVATE dl) endif() endif(UNIX) +target_link_libraries(libblade PRIVATE pthread) + if(WIN32) add_dependencies(libblade mman) target_link_libraries(libblade PRIVATE mman) diff --git a/scripts/install.sh b/scripts/install.sh index 02839e3f..95526790 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -85,6 +85,23 @@ install_build_env() { fi } +install_platform_specific_tools() { + # shellcheck disable=SC2154 + if [ -x "$(command -v apt-get)" ]; then + sudo apt-get install libpthread-stubs0-dev -y + elif [ -x "$(command -v apk)" ]; then + sudo apk add --no-cache glibc-headers + elif [ -x "$(command -v dnf)" ]; then + sudo dnf install glibc-headers -y + elif [ -x "$(command -v zypper)" ]; then + sudo zypper install glibc-devel -y + elif [ -x "$(command -v yum)" ]; then + sudo yum install glibc-headers -y + elif [ -x "$(command -v pacman)" ]; then + sudo pacman -Sy glibc + fi +} + remove_redundant_libraries() { # shellcheck disable=SC2154 if [ -x "$(command -v apt-get)" ]; then @@ -151,6 +168,7 @@ echo "Beginning installation of Blade..." install_build_env remove_redundant_libraries +install_platform_specific_tools if [[ -z "${IS_LINUX-}" ]]; then diff --git a/src/standard/thread.c b/src/standard/thread.c index 3ccce3b3..c0430ee6 100644 --- a/src/standard/thread.c +++ b/src/standard/thread.c @@ -14,43 +14,96 @@ static b_thread_handle *create_thread_handle(b_vm *vm, b_obj_closure *closure, b b_thread_handle *handle = ALLOCATE(b_thread_handle, 1); if(handle != NULL) { - thrd_t *thread = ALLOCATE(thrd_t, 1); + pthread_t *thread = ALLOCATE(pthread_t, 1); if(thread) { - handle->thread = (void *)thread; handle->vm = copy_vm(vm, ++last_thread_vm_id); + + if(handle->vm == NULL) { + FREE(pthread_t, thread); + FREE(b_thread_handle, handle); + return NULL; + } + + handle->thread = (void *)thread; handle->closure = closure; handle->args = args; ((b_obj *)closure)->stale = true; ((b_obj *)args)->stale = true; + } else { + FREE(b_thread_handle, handle); + return NULL; } } return handle; } -static int b_thread_callback_function(void *data) { + +static void push_thread(b_vm *vm, b_thread_handle *thread) { + if(vm->threads_capacity == vm->threads_count) { + size_t capacity = GROW_CAPACITY(vm->threads_capacity); + vm->threads = GROW_ARRAY(b_thread_handle *, vm->threads, vm->threads_capacity, capacity); + vm->threads_capacity = capacity; + + vm->threads[vm->threads_count] = thread; + thread->parent_thead_index = vm->threads_count; + thread->parent_vm = vm; + } else { + for(int i = 0; i < vm->threads_capacity; i++) { + if(vm->threads[i] == NULL) { + vm->threads[i] = thread; + thread->parent_thead_index = i; + thread->parent_vm = vm; + break; + } + } + } + + vm->threads_count++; +} + +static void free_thread_handle(b_thread_handle *thread) { + if(thread != NULL && thread->parent_vm) { + // make slot available for another thread + + b_vm *vm = thread->parent_vm; + thread->parent_vm->threads[thread->parent_thead_index] = NULL; + thread->parent_vm->threads_count--; + + free_vm(thread->vm); + free(thread->thread); + + thread->parent_vm = NULL; + thread->vm = NULL; + thread->thread = NULL; + thread->closure = NULL; + thread->args = NULL; + + FREE(b_thread_handle *, thread); + thread = NULL; + } +} + +static void *b_thread_callback_function(void *data) { b_thread_handle *handle = (b_thread_handle *) data; if(handle == NULL || handle->vm == NULL || handle->parent_vm == NULL) { - thrd_exit(0); - return 1; + pthread_exit(NULL); } for(int i = 0; i < handle->args->items.count; i++) { push(handle->vm, handle->args->items.values[i]); } - bool result = 1; if(run_closure_call(handle->vm, handle->closure, handle->args) == PTR_OK) { - result = 0; + // do nothing for now... } ((b_obj *)handle->closure)->stale = false; ((b_obj *)handle->args)->stale = false; -// free_thread_handle(handle); - return result; + return NULL; } DECLARE_MODULE_METHOD(thread__run) { @@ -61,9 +114,17 @@ DECLARE_MODULE_METHOD(thread__run) { b_thread_handle *thread = create_thread_handle(vm, AS_CLOSURE(args[0]), AS_LIST(args[1])); if(thread) { push_thread(vm, thread); - if(thrd_create((thrd_t *)thread->thread, b_thread_callback_function, thread) == thrd_success) { + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 64 * 1024); // Reduce stack size to 8KB + + if(pthread_create((pthread_t *)thread->thread, NULL, b_thread_callback_function, thread) == thrd_success) { + pthread_attr_destroy(&attr); RETURN_NAMED_PTR(thread, B_THREAD_PTR_NAME); } + + pthread_attr_destroy(&attr); } RETURN_FALSE; @@ -76,7 +137,6 @@ DECLARE_MODULE_METHOD(thread__dispose) { b_thread_handle *thread = AS_PTR(args[0])->pointer; if(thread) { free_thread_handle(thread); - vm->threads_count--; } RETURN; } @@ -86,7 +146,7 @@ DECLARE_MODULE_METHOD(thread__await) { ENFORCE_ARG_TYPE(await, 0, IS_PTR); b_thread_handle *thread = AS_PTR(args[0])->pointer; - bool success = thrd_join(*((thrd_t *)thread->thread), 0) == thrd_success; + bool success = pthread_join(*((pthread_t *)thread->thread), NULL) == 0; free_thread_handle(thread); RETURN_BOOL(success); @@ -96,7 +156,7 @@ DECLARE_MODULE_METHOD(thread__detach) { ENFORCE_ARG_COUNT(detach, 1); ENFORCE_ARG_TYPE(detach, 0, IS_PTR); b_thread_handle *thread = AS_PTR(args[0])->pointer; - RETURN_BOOL(thrd_detach(*((thrd_t *)thread->thread)) == thrd_success); + RETURN_BOOL(pthread_detach(*((pthread_t *)thread->thread)) == 0); } CREATE_MODULE_LOADER(thread) { diff --git a/src/vm.c b/src/vm.c index 8e3e9695..58da3f1d 100644 --- a/src/vm.c +++ b/src/vm.c @@ -247,30 +247,6 @@ inline b_error_frame* pop_error(b_vm *vm) { return *vm->error_top; } -inline void push_thread(b_vm *vm, b_thread_handle *thread) { - if(vm->threads_capacity == vm->threads_count) { - size_t capacity = GROW_CAPACITY(vm->threads_capacity); - vm->threads = GROW_ARRAY(b_thread_handle *, vm->threads, vm->threads_capacity, capacity); - vm->threads_capacity = capacity; - - vm->threads[vm->threads_count] = thread; - thread->parent_thead_index = vm->threads_count; - thread->parent_vm = vm; - vm->threads_count++; - } else { - for(int i = 0; i < vm->threads_capacity; i++) { - if(vm->threads[i] == NULL) { - vm->threads[i] = thread; - thread->parent_thead_index = i; - thread->parent_vm = vm; - break; - } - } - - vm->threads_count++; - } -} - inline b_error_frame* peek_error(b_vm *vm) { return vm->error_top[-1]; } @@ -639,27 +615,6 @@ b_vm *copy_vm(b_vm *src, uint64_t id) { vm->id = id; - /*init_table(&vm->modules); - table_add_all(vm, &src->modules, &vm->modules); - init_table(&vm->strings); - table_add_all(vm, &src->strings, &vm->strings); - init_table(&vm->globals); - table_add_all(vm, &src->globals, &vm->globals); - - // object methods tables - init_table(&vm->methods_string); - table_add_all(vm, &src->methods_string, &vm->methods_string); - init_table(&vm->methods_list); - table_add_all(vm, &src->methods_list, &vm->methods_list); - init_table(&vm->methods_dict); - table_add_all(vm, &src->methods_dict, &vm->methods_dict); - init_table(&vm->methods_file); - table_add_all(vm, &src->methods_file, &vm->methods_file); - init_table(&vm->methods_bytes); - table_add_all(vm, &src->methods_bytes, &vm->methods_bytes); - init_table(&vm->methods_range); - table_add_all(vm, &src->methods_range, &vm->methods_range);*/ - return vm; } @@ -691,28 +646,6 @@ void free_vm(b_vm *vm) { free(vm); } -void free_thread_handle(b_thread_handle *thread) { - if(thread != NULL && thread->parent_vm) { - // make slot available for another thread - - b_vm *vm = thread->parent_vm; - thread->parent_vm->threads[thread->parent_thead_index] = NULL; - thread->parent_vm->threads_count--; - - free_vm(thread->vm); - free(thread->thread); - - thread->parent_vm = NULL; - thread->vm = NULL; - thread->thread = NULL; - thread->closure = NULL; - thread->args = NULL; - - FREE(b_thread_handle *, thread); - thread = NULL; - } -} - static inline bool is_private(b_obj_string *name) { return name->length > 0 && name->chars[0] == '_'; } diff --git a/src/vm.h b/src/vm.h index fc6d58a3..0b7fbe84 100644 --- a/src/vm.h +++ b/src/vm.h @@ -113,9 +113,6 @@ void push_error(b_vm *vm, b_error_frame *frame); b_error_frame* pop_error(b_vm *vm); b_error_frame* peek_error(b_vm *vm); -void push_thread(b_vm *vm, b_thread_handle *thread); -void free_thread_handle(b_thread_handle *thread); - static inline void add_module(b_vm *vm, b_obj_module *module) { cond_dbg(vm->current_frame, printf("Adding module %s from %s to %s in %s\n", module->name, diff --git a/thirdparty/threads/threads.h b/thirdparty/threads/threads.h index a9bc8f0e..2ac5b4dd 100644 --- a/thirdparty/threads/threads.h +++ b/thirdparty/threads/threads.h @@ -349,14 +349,12 @@ static inline int mtx_unlock(mtx_t *mtx) { /*------------------- 7.25.5 Thread functions -------------------*/ // 7.25.5.1 static inline int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { - struct impl_thrd_param *pack; - uintptr_t handle; assert(thr != NULL); - pack = (struct impl_thrd_param *)malloc(sizeof(struct impl_thrd_param)); + struct impl_thrd_param *pack = (struct impl_thrd_param *)malloc(sizeof(struct impl_thrd_param)); if (!pack) return thrd_nomem; pack->func = func; pack->arg = arg; - handle = _beginthreadex(NULL, 0, impl_thrd_routine, pack, 0, NULL); + uintptr_t handle = _beginthreadex(NULL, 8 * 1024, impl_thrd_routine, pack, 0, NULL); if (handle == 0) { if (errno == EAGAIN || errno == EACCES) return thrd_nomem; @@ -727,10 +725,18 @@ static inline int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { if (!pack) return thrd_nomem; pack->func = func; pack->arg = arg; + +// pthread_attr_t attr; +// pthread_attr_init(&attr); +// pthread_attr_setstacksize(&attr, 8 * 1024); // Reduce stack size to 8KB + if (pthread_create(thr, NULL, impl_thrd_routine, pack) != 0) { free(pack); +// pthread_attr_destroy(&attr); return thrd_error; } + +// pthread_attr_destroy(&attr); return thrd_success; }