From: Jérémie Astor Date: Mon, 22 Nov 2021 17:29:06 +0000 (+0100) Subject: :art: Add helgrind debug capacity X-Git-Tag: nightly~400 X-Git-Url: http://10.10.0.4:5575/?a=commitdiff_plain;h=ee69f1383a4e2d9d2f5325b71fb80bcf30a47ebc;p=gwion.git :art: Add helgrind debug capacity --- diff --git a/Makefile b/Makefile index 7ee29152..1424f0ba 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,10 @@ ifneq (${BUILD_ON_WINDOWS}, 1) LDFLAGS += -ldl -lpthread endif +ifeq (${USE_HELGRIND}, 1) +CFLAGS += -DUSE_HELGRIND +endif + src_obj := $(src:.c=.o) gcda := $(src:.c=.gcda) gcno := $(src:.c=.gcno) diff --git a/include/object.h b/include/object.h index 872df60a..6223889b 100644 --- a/include/object.h +++ b/include/object.h @@ -16,7 +16,7 @@ ANN void fork_clean(const VM_Shred, const Vector); ANN ANEW M_Object new_array(MemPool, const Type t, const m_uint length); ANEW M_Object new_string(const struct Gwion_ *, const m_str); ANEW M_Object new_shred(const VM_Shred); -ANN void fork_launch(const M_Object, const m_uint); +ANN void fork_launch(const M_Object); ANN void __release(const M_Object, const VM_Shred); ANN void broadcast(const M_Object); @@ -27,9 +27,23 @@ ANN void broadcast(const M_Object); #define ARRAY(o) (&*(struct M_Vector_ *)((M_Object)o)->data) #define IO_FILE(o) (*(FILE **)(((M_Object)o)->data + SZ_INT)) +#ifdef USE_HELGRIND +#include "valgrind/helgrind.h" +#endif static inline void _release(const restrict M_Object obj, const restrict VM_Shred shred) { - if (!--obj->ref) __release(obj, shred); + if (!--obj->ref) { +#ifdef USE_HELGRIND + ANNOTATE_HAPPENS_AFTER(obj); + ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(obj); +#endif + __release(obj, shred); + } +#ifdef USE_HELGRIND + else { + ANNOTATE_HAPPENS_BEFORE(obj); + } +#endif } static inline void release(const restrict M_Object obj, const restrict VM_Shred shred) { diff --git a/include/vm.h b/include/vm.h index b88f3e7d..c5ff5ac6 100644 --- a/include/vm.h +++ b/include/vm.h @@ -94,6 +94,7 @@ struct VM_Shred_ { size_t pc; struct ShredTick_ *tick; struct ShredInfo_ *info; + MUTEX_TYPE mutex; }; REF_FUNC(VM_Code, vmcode) ANN2(1, 4) diff --git a/src/emit/emit.c b/src/emit/emit.c index 37aa075a..2758ac5b 100644 --- a/src/emit/emit.c +++ b/src/emit/emit.c @@ -1866,7 +1866,6 @@ ANN static void spork_ini(const Emitter emit, const struct Sporker *sp) { regpushi(emit, (m_uint)sp->type); const Instr instr = emit_add_instr(emit, ForkIni); instr->m_val = (m_uint)sp->vm_code; - instr->m_val2 = sp->type->size; } ANN m_bool emit_exp_spork(const Emitter emit, const Exp_Unary *unary) { diff --git a/src/lib/object.c b/src/lib/object.c index 01184047..724cf984 100644 --- a/src/lib/object.c +++ b/src/lib/object.c @@ -66,7 +66,8 @@ ANN static inline void release_not_union(const m_bit *data, const VM_Shred shred ANN static void do_release(const M_Object o, const VM_Shred shred, const Type t) { const Type next = next_type(t); - if(!next) return; + if(!next) + return; if (!tflag(t, tflag_union)) release_not_union(o->data, shred, t->nspc->info->value); if (tflag(t, tflag_dtor)) { diff --git a/src/lib/shred.c b/src/lib/shred.c index c52f511a..067a5faa 100644 --- a/src/lib/shred.c +++ b/src/lib/shred.c @@ -14,12 +14,10 @@ #include "specialid.h" #include "gwi.h" -static m_int o_fork_thread, o_fork_mutex, o_shred_cancel, - o_fork_done, o_fork_ev, o_fork_retsize; +static m_int o_fork_thread, o_shred_cancel, + o_fork_done, o_fork_ev; #define FORK_THREAD(o) *(THREAD_TYPE *)(o->data + o_fork_thread) -#define FORK_MUTEX(o) *(MUTEX_TYPE *)(o->data + o_fork_mutex) -#define FORK_RETSIZE(o) *(m_int *)(o->data + o_fork_retsize) VM_Shred new_shred_base(const VM_Shred shred, const VM_Code code) { const VM_Shred sh = new_vm_shred(shred->info->mp, code); @@ -157,15 +155,17 @@ static DTOR(shred_dtor) { free_vm_shred(s); } -static MFUN(shred_lock) { if(ME(o)->tick) MUTEX_LOCK(ME(o)->tick->shreduler->mutex); } +static MFUN(shred_lock) { if(ME(o)->tick) MUTEX_LOCK(ME(o)->mutex); } -static MFUN(shred_unlock) { if(ME(o)->tick) MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex); } +static MFUN(shred_unlock) { if(ME(o)->tick) MUTEX_UNLOCK(ME(o)->mutex); } static void stop(const M_Object o) { VM *vm = ME(o)->info->vm; MUTEX_LOCK(vm->shreduler->mutex); + MUTEX_LOCK(ME(o)->mutex); vm->shreduler->bbq->is_running = 0; *(m_int *)(o->data + o_shred_cancel) = 1; + MUTEX_UNLOCK(ME(o)->mutex); MUTEX_UNLOCK(vm->shreduler->mutex); } @@ -178,12 +178,15 @@ static inline void join(const M_Object o) { static DTOR(fork_dtor) { VM *parent = ME(o)->info->vm->parent; - MUTEX_LOCK(parent->shreduler->mutex); +// MUTEX_LOCK(parent->shreduler->mutex); + MUTEX_LOCK(ME(o)->mutex); *(m_int *)(o->data + o_fork_done) = 1; - MUTEX_UNLOCK(parent->shreduler->mutex); + MUTEX_UNLOCK(ME(o)->mutex); stop(o); join(o); +// MUTEX_UNLOCK(parent->shreduler->mutex); MUTEX_LOCK(parent->shreduler->mutex); +// MUTEX_LOCK(ME(o)->mutex); if (parent->gwion->data->child.ptr) { const m_int idx = vector_find(&parent->gwion->data->child, (vtype)o); if (idx > -1) VPTR(&parent->gwion->data->child, idx) = 0; @@ -191,6 +194,7 @@ static DTOR(fork_dtor) { if (!parent->gwion->data->child2.ptr) vector_init(&parent->gwion->data->child2); vector_add(&parent->gwion->data->child2, (vtype)ME(o)->info->vm->gwion); +// MUTEX_UNLOCK(ME(o)->mutex); MUTEX_UNLOCK(parent->shreduler->mutex); vmcode_remref(ME(o)->code, ME(o)->info->vm->gwion); } @@ -204,16 +208,20 @@ static MFUN(fork_join) { static MFUN(shred_cancel) { if(!ME(o)->tick)return; -// MUTEX_LOCK(ME(o)->tick->shreduler->mutex); +// vm_lock(ME(o)->info->vm); + MUTEX_LOCK(ME(o)->mutex); *(m_int *)(o->data + o_shred_cancel) = *(m_int *)MEM(SZ_INT); -// MUTEX_UNLOCK(ME(o)->tick->shreduler->mutex); + MUTEX_UNLOCK(ME(o)->mutex); +// vm_unlock(ME(o)->info->vm); } static MFUN(shred_test_cancel) { -// VM *parent = ME(o)->info->vm; -// MUTEX_LOCK(parent->shreduler->mutex); - if (*(m_int *)(o->data + o_shred_cancel)) vm_shred_exit(ME(o)); -// MUTEX_UNLOCK(parent->shreduler->mutex); + MUTEX_LOCK(ME(o)->mutex); + if (*(m_int *)(o->data + o_shred_cancel)) { + MUTEX_UNLOCK(ME(o)->mutex); + vm_shred_exit(ME(o)); + } else + MUTEX_UNLOCK(ME(o)->mutex); } static MFUN(fork_test_cancel) { @@ -230,9 +238,11 @@ static MFUN(fork_test_cancel) { } static MFUN(shred_now) { - VM *vm = shred->info->vm; + VM *vm = ME(o)->info->vm; while (vm->parent) vm = vm->parent; + MUTEX_LOCK(vm->shreduler->mutex); *(m_float *)RETURN = vm->bbq->pos; + MUTEX_UNLOCK(vm->shreduler->mutex); } struct ThreadLauncher { @@ -242,8 +252,12 @@ struct ThreadLauncher { }; static inline int fork_running(VM *vm, const M_Object o) { + MUTEX_LOCK(ME(o)->mutex); + const int cancel = *(m_int *)(o->data + o_shred_cancel); + MUTEX_UNLOCK(ME(o)->mutex); + if(cancel)return false; MUTEX_LOCK(vm->shreduler->mutex); - const int ret = vm->bbq->is_running && !*(m_int *)(o->data + o_shred_cancel); + const int ret = vm->bbq->is_running; MUTEX_UNLOCK(vm->shreduler->mutex); return ret; } @@ -256,37 +270,45 @@ static ANN THREAD_FUNC(fork_run) { MUTEX_COND_LOCK(mutex); THREAD_COND_SIGNAL(tl->cond); MUTEX_COND_UNLOCK(mutex); +// THREAD_COND_CLEANUP(tl->cond); +// MUTEX_CLEANUP(tl->mutex); while (fork_running(vm, me)) { vm_run(vm); ++vm->bbq->pos; } gwion_end_child(ME(me), vm->gwion); - MUTEX_LOCK(vm->parent->shreduler->mutex); +vm_lock(vm); +// MUTEX_LOCK(vm->shreduler->mutex); +// MUTEX_LOCK(vm->parent->shreduler->mutex); + MUTEX_LOCK(ME(me)->mutex); if (!*(m_int *)(me->data + o_shred_cancel) && me->type_ref != vm->gwion->type[et_fork]) memcpy(me->data + vm->gwion->type[et_fork]->nspc->offset, ME(me)->reg, - FORK_RETSIZE(me)); - MUTEX_UNLOCK(vm->parent->shreduler->mutex); + ((Type)vector_front(&me->type_ref->info->tuple->types))->size); *(m_int *)(me->data + o_fork_done) = 1; + MUTEX_UNLOCK(ME(me)->mutex); if (!*(m_int *)(me->data + o_shred_cancel)) broadcast(*(M_Object *)(me->data + o_fork_ev)); +vm_unlock(vm); +// MUTEX_UNLOCK(vm->parent->shreduler->mutex); +// MUTEX_UNLOCK(vm->shreduler->mutex); THREAD_RETURN(0); } -ANN void fork_launch(const M_Object o, const m_uint sz) { - FORK_RETSIZE(o) = sz; - MUTEX_SETUP(FORK_MUTEX(o)); +ANN void fork_launch(const M_Object o) { + MUTEX_TYPE mutex; + MUTEX_SETUP(mutex); THREAD_COND_TYPE cond; THREAD_COND_SETUP(cond); struct ThreadLauncher tl = { - .mutex = FORK_MUTEX(o), .cond = cond, .vm = ME(o)->info->vm}; + .mutex = mutex, .cond = cond, .vm = ME(o)->info->vm}; ++o->ref; - MUTEX_COND_LOCK(tl.mutex); + MUTEX_COND_LOCK(mutex); THREAD_CREATE(FORK_THREAD(o), fork_run, &tl); - THREAD_COND_WAIT(cond, tl.mutex); - MUTEX_COND_UNLOCK(tl.mutex); + THREAD_COND_WAIT(cond, mutex); + MUTEX_COND_UNLOCK(mutex); THREAD_COND_CLEANUP(cond); - MUTEX_CLEANUP(FORK_MUTEX(o)); + MUTEX_CLEANUP(mutex); } ANN void fork_clean(const VM_Shred shred, const Vector v) { @@ -385,15 +407,11 @@ GWION_IMPORT(shred) { gwi->gwion->type[et_fork] = t_fork; o_fork_thread = t_fork->nspc->offset; t_fork->nspc->offset += SZ_INT; - o_fork_mutex = t_fork->nspc->offset; - t_fork->nspc->offset += SZ_INT; gwi_item_ini(gwi, "int", "is_done"); GWI_BB((o_fork_done = gwi_item_end(gwi, ae_flag_const, num, 0))) gwi_item_ini(gwi, "Event", "ev"); GWI_BB((o_fork_ev = gwi_item_end(gwi, ae_flag_const, num, 0))) - gwi_item_ini(gwi, "int", "retsize"); - GWI_BB((o_fork_retsize = gwi_item_end(gwi, ae_flag_const, num, 0))) gwi_func_ini(gwi, "void", "join"); GWI_BB(gwi_func_end(gwi, fork_join, ae_flag_none)) gwi_func_ini(gwi, "void", "test_cancel"); diff --git a/src/vm/shreduler.c b/src/vm/shreduler.c index 50ba435c..9266ba83 100644 --- a/src/vm/shreduler.c +++ b/src/vm/shreduler.c @@ -40,9 +40,15 @@ ANN static inline void shreduler_child(const Vector v) { ANN static void shreduler_erase(const Shreduler s, struct ShredTick_ *const tk) { - if (tk->parent) vector_rem2(&tk->parent->child, (vtype)tk->self); + MUTEX_LOCK(tk->self->mutex); + if (tk->parent) { + MUTEX_LOCK(tk->parent->self->mutex); + vector_rem2(&tk->parent->child, (vtype)tk->self); + MUTEX_UNLOCK(tk->parent->self->mutex); + } if (tk->child.ptr) shreduler_child(&tk->child); vector_rem2(&s->active_shreds, (vtype)tk->self); + MUTEX_UNLOCK(tk->self->mutex); } ANN void shreduler_remove(const Shreduler s, const VM_Shred out, diff --git a/src/vm/vm.c b/src/vm/vm.c index f125e9ba..8bb3f6bd 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -98,18 +98,12 @@ ANN static bool unwind(const VM_Shred shred, const Symbol effect, const m_uint s const VM_Code code = shred->code; if (code->live_values.ptr) clean_values(shred); -// if (!size) return true; if (!size) return false; -// if (code->live_values.ptr) -// clean_values(shred); if (code->handlers.ptr) return find_handle(shred, effect, size); // there might be no more stack to unwind if (shred->mem == (m_bit *)shred + sizeof(struct VM_Shred_) + SIZEOF_REG) return false; -// else -// return true; -// return false; shred_unwind(shred); return unwind(shred, effect, size - 1); } @@ -270,12 +264,12 @@ ANN /*static inline */ VM_Shred init_spork_shred(const VM_Shred shred, ANN M_Object new_fork(const VM_Shred, const VM_Code code, const Type); ANN static VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code, - const Type t, const m_uint retsz) { + const Type t) { const M_Object o = new_fork(shred, code, t); VM * vm = shred->info->vm; if (!vm->gwion->data->child.ptr) vector_init(&vm->gwion->data->child); vector_add(&vm->gwion->data->child, (vtype)o); - fork_launch(o, retsz); + fork_launch(o); return ME(o); } @@ -511,7 +505,7 @@ vm_run(const VM *vm) { // lgtm [cpp/use-of-goto] PRAGMA_PUSH() register VM_Shred child; PRAGMA_POP() - MUTEX_LOCK(s->mutex); +// MUTEX_LOCK(s->mutex); do { SDISPATCH(); regsetimm: @@ -976,7 +970,7 @@ vm_run(const VM *vm) { // lgtm [cpp/use-of-goto] DISPATCH() forkini: reg -= SZ_INT; - child = init_fork_shred(shred, (VM_Code)VAL, *(Type *)reg, VAL2), + child = init_fork_shred(shred, (VM_Code)VAL, *(Type *)reg), DISPATCH() sporkfunc: PRAGMA_PUSH() @@ -1291,13 +1285,14 @@ vm_run(const VM *vm) { // lgtm [cpp/use-of-goto] VM_OUT vm_shred_exit(shred); } while (s->curr); - MUTEX_UNLOCK(s->mutex); +// MUTEX_UNLOCK(s->mutex); } } // remove me ANN void next_bbq_pos(const VM *vm) { Driver *const di = vm->bbq; + MUTEX_LOCK(vm->shreduler->mutex); if(++di->pos == 16777216-1) { const Vector v = &vm->shreduler->active_shreds; for(m_uint i = 0; i < vector_size(v); i++) { @@ -1306,6 +1301,7 @@ ANN void next_bbq_pos(const VM *vm) { } di->pos = 0; } + MUTEX_UNLOCK(vm->shreduler->mutex); } static void vm_run_audio(const VM *vm) { diff --git a/src/vm/vm_shred.c b/src/vm/vm_shred.c index cfbf1dc1..61e1c1a1 100644 --- a/src/vm/vm_shred.c +++ b/src/vm/vm_shred.c @@ -36,6 +36,7 @@ VM_Shred new_vm_shred(MemPool p, VM_Code c) { shred->reg = (m_bit *)shred + sizeof(struct VM_Shred_); shred->base = shred->mem = shred->reg + SIZEOF_REG; shred->info = new_shredinfo(p, c); + MUTEX_SETUP(shred->mutex); return shred; } @@ -46,5 +47,6 @@ void free_vm_shred(VM_Shred shred) { const MemPool mp = shred->info->mp; mp_free(mp, ShredTick, shred->tick); free_shredinfo(mp, shred->info); + MUTEX_CLEANUP(shred->mutex); mp_free(mp, Stack, shred); }