]> Nishi Git Mirror - gwion.git/commitdiff
:art: Add helgrind debug capacity
authorJérémie Astor <fennecdjay@gmail.com>
Mon, 22 Nov 2021 17:29:06 +0000 (18:29 +0100)
committerJérémie Astor <fennecdjay@gmail.com>
Mon, 22 Nov 2021 17:29:06 +0000 (18:29 +0100)
Makefile
include/object.h
include/vm.h
src/emit/emit.c
src/lib/object.c
src/lib/shred.c
src/vm/shreduler.c
src/vm/vm.c
src/vm/vm_shred.c

index 7ee2915205743dc00134c74d56d33a7acfc01701..1424f0ba929d5229bfe1908d36f2850df3a9330f 100644 (file)
--- 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)
index 872df60a2289d82e9406d4ac554bde42835255ea..6223889b1dbbcca0ee8e17fc2fef6d21319fdc6c 100644 (file)
@@ -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) {
index b88f3e7d295b7829f3df922609c3f06be19ea2b6..c5ff5ac637c68dcdbbfa3cb2fae050e41d0abfd2 100644 (file)
@@ -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)
index 37aa075aee27a2629c1a2346acd9460672673cf8..2758ac5bdcc00fee3a21800cdcb008bdbeb25aee 100644 (file)
@@ -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) {
index 011840471b498c03f56a97793bf69cdf7bb185e7..724cf9843541354fb9bacfd902ef9ca58b191b56 100644 (file)
@@ -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)) {
index c52f511aaaef67b6487bcf293525ba94b35811ae..067a5faa04d79cc4758db6f451b10e6f153ae939 100644 (file)
 #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");
index 50ba435c273924d18b00cbd38fd3bfc4918f7297..9266ba83835f43f1997542e46a7ff30c85fd70c4 100644 (file)
@@ -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,
index f125e9bae5190b5d76ac92f9ea4f1085a20924be..8bb3f6bd3f2e3ad5f8532dc404e8906ebd907dab 100644 (file)
@@ -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) {
index cfbf1dc1f4c03ce8eb4050dd1123c6aa46408812..61e1c1a10ae3b915b94b1208ef40cac378a361c6 100644 (file)
@@ -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);
 }