Commits

Armin Rigo  committed 0581363

in-progress: API for the pypy jit, with support for a custom
implementation of setjmp/longjmp.

  • Participants
  • Parent commits 111c093

Comments (0)

Files changed (4)

 
   // jump back to the setjmp_buf (this call does not return)
   stm_stop_sharedlock();
-  longjmp(*d->setjmp_buf, 1);
+  if (d->longjmp_callback != NULL)
+    d->longjmp_callback(d->setjmp_buf);
+  else
+    longjmp(*(jmp_buf *)d->setjmp_buf, 1);
+
+  stm_fatalerror("longjmp() call should not return");
 }
 
 void AbortTransactionAfterCollect(struct tx_descriptor *d, int reason)
   gcptrlist_clear(&d->abortinfo);
 }
 
-void BeginTransaction(jmp_buf* buf)
+void stm_begin_transaction(void *buf, void (*longjmp_callback)(void *))
 {
   struct tx_descriptor *d = thread_descriptor;
   init_transaction(d);
   d->active = 1;
   d->setjmp_buf = buf;
+  d->longjmp_callback = longjmp_callback;
   d->old_thread_local_obj = stm_thread_local_obj;
   d->start_time = GetGlobalCurTime(d);
   update_reads_size_limit(d);
 struct tx_descriptor {
   struct tx_public_descriptor *public_descriptor;
   revision_t public_descriptor_index;
-  jmp_buf *setjmp_buf;
+  void *setjmp_buf;
+  void(*longjmp_callback)(void *);
   revision_t start_time;
   revision_t my_lock;
   gcptr *shadowstack;
 /************************************************************/
 
 
-void BeginTransaction(jmp_buf *);
 void BeginInevitableTransaction(void);  /* must save roots around this call */
 void CommitTransaction(void);           /* must save roots around this call */
 void BecomeInevitable(const char *why); /* must save roots around this call */
 void stm_begin_inevitable_transaction(void);
 void stm_become_inevitable(const char *reason);
 
+/* specialized usage: for custom setjmp/longjmp implementation.
+   Must save roots around calls. */
+void stm_begin_transaction(void *buf, void (*longjmp_callback)(void *));
+void stm_transaction_break(void *buf, void (*longjmp_callback)(void *));
+void stm_invalidate_jmp_buf(void *buf);
+
 /* debugging: check if we're currently running a transaction or not. */
 int stm_in_transaction(void);
 

File c4/stmsync.c

             d->reads_size_limit_nonatomic = limit;
         }
         if (!d->atomic) {
-            BeginTransaction(&_jmpbuf);
+            stm_begin_transaction(&_jmpbuf, NULL);
         }
         else {
             /* atomic transaction: a common case is that callback() returned
     assert(stm_shadowstack == v_saved_value);
 }
 
+void stm_transaction_break(void *buf, void (*longjmp_callback)(void *))
+{   /* must save roots around this call */
+    struct tx_descriptor *d = thread_descriptor;
+    if (d->atomic) {
+        assert(d->active >= 1);
+        stm_possible_safe_point();
+    }
+    else {
+        CommitTransaction();
+        if (d->active != 2) {
+            unsigned long limit = d->reads_size_limit_nonatomic;
+            if (limit != 0 && limit < (stm_regular_length_limit >> 1))
+                limit = (limit << 1) | 1;
+            else
+                limit = stm_regular_length_limit;
+            d->reads_size_limit_nonatomic = limit;
+        }
+        stm_begin_transaction(buf, longjmp_callback);
+    }
+}
+
+void stm_invalidate_jmp_buf(void *buf)
+{   /* must save roots around this call */
+    struct tx_descriptor *d = thread_descriptor;
+    if (d->setjmp_buf == buf) {
+        BecomeInevitable("stm_invalidate_jmp_buf with atomic");
+    }
+}
+
 void stm_commit_transaction(void)
 {   /* must save roots around this call */
     struct tx_descriptor *d = thread_descriptor;