Commits

Armin Rigo committed f0f5f39

Fix start_new_thread with stm.

Comments (0)

Files changed (13)

rpython/memory/gc/stmgc.py

                                needs_finalizer=False,
                                is_finalizer_light=False,
                                contains_weakptr=False):
-        ll_assert(not needs_finalizer, 'XXX')
-        ll_assert(not is_finalizer_light, 'XXX')
-        ll_assert(not contains_weakptr, 'XXX')
+        # XXX finalizers are ignored for now
+        #ll_assert(not needs_finalizer, 'XXX needs_finalizer')
+        #ll_assert(not is_finalizer_light, 'XXX is_finalizer_light')
+        ll_assert(not contains_weakptr, 'XXX contains_weakptr')
         # XXX call optimized versions, e.g. if size < GC_NURSERY_SECTION
         return llop.stm_allocate(llmemory.GCREF, size, typeid16)
 

rpython/memory/gctransform/stmframework.py

 class StmRootWalker(BaseRootWalker):
 
     def need_thread_support(self, gctransformer, getfn):
-        def thread_start():
-            llop.stm_initialize(lltype.Void)
-        def thread_die():
-            llop.stm_finalize(lltype.Void)
-        self.thread_start_ptr = getfn(thread_start, [], annmodel.s_None)
-        self.thread_die_ptr = getfn(thread_die, [], annmodel.s_None)
+        pass
 
     def walk_stack_roots(self, collect_stack_root):
         raise NotImplementedError
 after_external_call._transaction_break_ = True
 
 def enter_callback_call():
-    # XXX assumes that we're not called in a fresh new thread
-    llop.stm_begin_inevitable_transaction(lltype.Void)
-    return 0
+    return llop.stm_enter_callback_call(lltype.Signed)
 enter_callback_call._dont_reach_me_in_del_ = True
 enter_callback_call._transaction_break_ = True
 
-def leave_callback_call(ignored):
-    llop.stm_commit_transaction(lltype.Void)
+def leave_callback_call(token):
+    llop.stm_leave_callback_call(lltype.Void, token)
 leave_callback_call._dont_reach_me_in_del_ = True
 leave_callback_call._transaction_break_ = True
 
+def invoke_around_extcall():
+    """Initialize the STM system.  Must be called once from the start-up."""
+    from rpython.rlib.objectmodel import invoke_around_extcall
+    invoke_around_extcall(before_external_call, after_external_call,
+                          enter_callback_call, leave_callback_call)
+
 # ____________________________________________________________
 
 def make_perform_transaction(func, CONTAINERP):

rpython/rtyper/lltypesystem/lloperation.py

     'stm_change_atomic':      LLOp(),
     'stm_get_atomic':         LLOp(sideeffects=False),
     'stm_perform_transaction':LLOp(),
+    'stm_enter_callback_call':LLOp(),
+    'stm_leave_callback_call':LLOp(),
 
     'stm_threadlocalref_get': LLOp(sideeffects=False),
     'stm_threadlocalref_set': LLOp(),

rpython/translator/c/funcgen.py

     OP_STM_THREADLOCAL_GET = _OP_STM
     OP_STM_THREADLOCAL_SET = _OP_STM
     OP_STM_PERFORM_TRANSACTION = _OP_STM
+    OP_STM_ENTER_CALLBACK_CALL = _OP_STM
+    OP_STM_LEAVE_CALLBACK_CALL = _OP_STM
 
 
     def OP_PTR_NONZERO(self, op):

rpython/translator/stm/funcgen.py

     arg1 = funcgen.expr(op.args[1])
     return 'stm_perform_transaction((gcptr)%s, %s);' % (arg0, arg1)
 
+def stm_enter_callback_call(funcgen, op):
+    result = funcgen.expr(op.result)
+    return '%s = stm_enter_callback_call();' % (result,)
+
+def stm_leave_callback_call(funcgen, op):
+    arg0 = funcgen.expr(op.args[0])
+    return 'stm_leave_callback_call(%s);' % (arg0,)
+
 
 def op_stm(funcgen, op):
     func = globals()[op.opname]

rpython/translator/stm/src_stm/et.c

 
 __thread gcptr stm_thread_local_obj;
 
-int DescriptorInit(void)
+void DescriptorInit(void)
 {
   if (GCFLAG_PREBUILT != PREBUILT_FLAGS)
     {
       stm_fatalerror("fix PREBUILT_FLAGS in stmgc.h by giving "
                      "it the same value as GCFLAG_PREBUILT!\n");
     }
-
-  if (thread_descriptor == NULL)
+  else
     {
       revision_t i;
       struct tx_descriptor *d = stm_malloc(sizeof(struct tx_descriptor));
       d->tx_next = stm_tx_head;
       if (d->tx_next != NULL) d->tx_next->tx_prev = d;
       stm_tx_head = d;
+      assert(thread_descriptor == NULL);
       thread_descriptor = d;
 
       dprintf(("[%lx] pthread %lx starting\n",
                (long)d->public_descriptor_index, (long)pthread_self()));
 
       stmgcpage_init_tls();
-      return 1;
     }
-  else
-    return 0;
 }
 
 void DescriptorDone(void)

rpython/translator/stm/src_stm/et.h

 _Bool stm_has_got_any_lock(struct tx_descriptor *);
 
 struct tx_public_descriptor *stm_get_free_public_descriptor(revision_t *);
-int DescriptorInit(void);
+void DescriptorInit(void);
 void DescriptorDone(void);
 
 #endif  /* _ET_H */

rpython/translator/stm/src_stm/revision

-bf56c12295c8
+637f6c9d19f7

rpython/translator/stm/src_stm/stmgc.h

 void stm_initialize(void);
 void stm_finalize(void);
 
+/* alternate initializers/deinitializers, to use for places that may or
+   may not be recursive, like callbacks from C code.  The return value
+   of the first one must be passed as argument to the second. */
+int stm_enter_callback_call(void);
+void stm_leave_callback_call(int);
+
 /* read/write barriers (the most general versions only for now) */
 #if 0     // (optimized version below)
 gcptr stm_read_barrier(gcptr);

rpython/translator/stm/src_stm/stmsync.c

     d->max_aborts = max_aborts;
 }
 
+int stm_enter_callback_call(void)
+{
+    int token = (thread_descriptor == NULL);
+    if (token == 1) {
+        stmgcpage_acquire_global_lock();
+        DescriptorInit();
+        stmgc_init_nursery();
+        init_shadowstack();
+        stmgcpage_release_global_lock();
+    }
+    BeginInevitableTransaction();
+    return token;
+}
+
+void stm_leave_callback_call(int token)
+{
+    if (token == 1)
+        stmgc_minor_collect();   /* force everything out of the nursery */
+
+    CommitTransaction();
+
+    if (token == 1) {
+        stmgcpage_acquire_global_lock();
+        done_shadowstack();
+        stmgc_done_nursery();
+        DescriptorDone();
+        stmgcpage_release_global_lock();
+    }
+}
+
 void stm_initialize(void)
 {
-    stmgcpage_acquire_global_lock();
-    int r = DescriptorInit();
+    int r = stm_enter_callback_call();
     if (r != 1)
-        stm_fatalerror("stm_initialize: DescriptorInit failure\n");
-    stmgc_init_nursery();
-    init_shadowstack();
-    //stmgcpage_init_tls();
-    stmgcpage_release_global_lock();
-    BeginInevitableTransaction();
+        stm_fatalerror("stm_initialize: already initialized\n");
 }
 
 void stm_finalize(void)
 {
-    stmgc_minor_collect();   /* force everything out of the nursery */
-    CommitTransaction();
-    stmgcpage_acquire_global_lock();
-    //stmgcpage_done_tls();
-    done_shadowstack();
-    stmgc_done_nursery();
-    DescriptorDone();
-    stmgcpage_release_global_lock();
+    stm_leave_callback_call(1);
 }
 
 /************************************************************/

rpython/translator/stm/test/targetdemo2.py

 import time
 from rpython.rlib import rthread
 from rpython.rlib import rstm, jit
-from rpython.rlib.objectmodel import invoke_around_extcall, we_are_translated
+from rpython.rlib.objectmodel import we_are_translated
 from rpython.rlib.objectmodel import compute_identity_hash
 from rpython.rlib.debug import ll_assert
 from rpython.rtyper.lltypesystem import lltype, rffi, rclass
 def setup_threads():
     #space.threadlocals.setup_threads(space)
     bootstrapper.setup()
-    invoke_around_extcall(rstm.before_external_call, rstm.after_external_call,
-                          rstm.enter_callback_call, rstm.leave_callback_call)
+    rstm.invoke_around_extcall()
 
 def start_thread(args):
     bootstrapper.acquire(args)

rpython/translator/stm/test/test_ztranslated.py

         glob = Global()
         #
         def threadfn():
-            rthread.gc_thread_start()
             x = Global()
             x.value = 0
             glob.seen = x
-            rthread.gc_thread_die()
         def entry_point(argv):
+            rstm.invoke_around_extcall()
             glob.seen = None
             rthread.start_new_thread(threadfn, ())
             while glob.seen is None: