diff --git a/main.c b/main.c index d8da28f..49aa261 100644 --- a/main.c +++ b/main.c @@ -36,21 +36,44 @@ static size_t table_insert(LVM *lvm, void *ud, size_t argn, set_LValueU *heap, L return 0; } -// This function is intended for small-medium runtimes, since the caller thread's heap is not touchable during this call. +struct ThreadsParallelCtx { + LVM *L; + LFunc *func; + _Atomic uint32_t finished; +}; +static int threads_parallel_worker(void *arg) { + struct ThreadsParallelCtx *ctx = arg; + + LRegSet regset = {}; + lvm_reset_regs(®set); + lvm_run(ctx->L, ctx->func, 0, ®set); + + atomic_fetch_add(&ctx->finished, 1); + + return 0; +} static size_t threads_parallel(LVM *lvm, void *ud, size_t argn, set_LValueU *heap, LRegSet *regset) { size_t no = lvalue_to_int32(regset->regs[0]); LFunc *func = (LFunc*) (regset->regs[1].u & ~LTAG_MASK); - atomic_fetch_sub(&lvm->active_thread_count, 1); - - #pragma omp parallel for - for(size_t i = 0; i < no; i++) { - LRegSet regset = {}; - lvm_reset_regs(®set); - lvm_run(lvm, func, 0, ®set); + if(no == 0) { + return 0; } - atomic_fetch_add(&lvm->active_thread_count, 1); + struct ThreadsParallelCtx ctx = {.L = lvm, .func = func, .finished = 0}; + + thrd_t thrds[no]; + for(size_t i = 1; i < no; i++) { + thrd_create(&thrds[i], threads_parallel_worker, &ctx); + } + + LRegSet set = {.parent = regset}; + lvm_reset_regs(&set); + lvm_call(lvm, func, 0, heap, &set); + + while(atomic_load(&ctx.finished) != no - 1) { + lvm->safepoint_func(lvm, heap, regset); + } return 0; } @@ -122,6 +145,9 @@ int main(int argc, char **argv) { LVM lvm = {}; lvm_init(&lvm); + lvm.unit_count = 1; + lvm.units = calloc(1, sizeof(*lvm.units)); + lvm.units[0] = unit; LRegSet regset = {.parent = NULL}; lvm_reset_regs(®set); diff --git a/parse.c b/parse.c index 8b83f36..d51273d 100644 --- a/parse.c +++ b/parse.c @@ -1195,7 +1195,7 @@ LUnit *lparse(size_t sz, Token *tokens, LTable *environment) { P.unit_functions.data[0].lua_instrs = P.current_chunk.instrs.data; unit->abyss = P.abyss; - unit->func_count = 1; + unit->func_count = P.unit_functions.size; unit->funcs = P.unit_functions.data; for(Expr *e = last_desc; e;) { diff --git a/vm.c b/vm.c index 7015ec3..6bd8669 100644 --- a/vm.c +++ b/vm.c @@ -63,9 +63,10 @@ do_getglobal:; regset->regs[inst->a] = ltable_get(func->env, lvalue_from_string(str)); - set_LValueU_insert(heap, lvalue_from_string(str).u); + free(str); - lvm_gc_alert(L, &privates, sizeof(*str) + len); + //set_LValueU_insert(heap, lvalue_from_string(str).u); + //lvm_gc_alert(L, &privates, sizeof(*str) + len); } DISPATCH(); @@ -421,7 +422,7 @@ static void gc_mark(LValue v) { } static void gc_mark_units(LVM *L) { for(size_t u = 0; u < L->unit_count; u++) { - LUnit *unit = &L->units[u]; + LUnit *unit = L->units[u]; for(size_t f = 0; f < unit->func_count; f++) { LFunc *func = &unit->funcs[f]; gc_mark(lvalue_from_table(func->env)); diff --git a/vm.h b/vm.h index fa69dc7..6ec539f 100644 --- a/vm.h +++ b/vm.h @@ -113,7 +113,7 @@ typedef struct LThreadPrivates { #define L_THREADS_MAX 32 typedef struct LVM { size_t unit_count; - LUnit *units; + LUnit **units; // The following is all used for GC _Atomic bool gcInProgress;