[pypy-commit] stmgc default: make HTM work sometimes: copy nearly all logic from paper about ruby; don't

Remi Meier noreply at buildbot.pypy.org
Thu Mar 27 11:12:12 CET 2014


Author: Remi Meier
Branch: 
Changeset: r1099:ae1a7d62c9a2
Date: 2014-03-27 11:12 +0100
http://bitbucket.org/pypy/stmgc/changeset/ae1a7d62c9a2/

Log:	make HTM work sometimes: copy nearly all logic from paper about
	ruby; don't clean whole nursery on commit, only used parts (always
	overflowed)

diff --git a/c7/demo/Makefile b/c7/demo/Makefile
--- a/c7/demo/Makefile
+++ b/c7/demo/Makefile
@@ -30,3 +30,9 @@
 release-%: %.c ${H_FILES} ${C_FILES}
 	clang -I.. -pthread  -g -DNDEBUG -O2 $< -o release-$* \
         -Wall -Werror ../stmgc.c
+
+
+release-htm-%: %.c ../../htm-c7/stmgc.? ../../htm-c7/htm.h
+	clang -I.. -pthread -g -DNDEBUG -O2 $< -o release-htm-$* ../../htm-c7/stmgc.c -Wall -DUSE_HTM
+
+
diff --git a/c7/demo/demo2.c b/c7/demo/demo2.c
--- a/c7/demo/demo2.c
+++ b/c7/demo/demo2.c
@@ -4,11 +4,20 @@
 #include <pthread.h>
 #include <semaphore.h>
 
-#include "stmgc.h"
+#ifdef USE_HTM
+#  include "../../htm-c7/stmgc.h"
+#else
+#  include "stmgc.h"
+#endif
 
-#define NTHREADS    3
-#define LIST_LENGTH 2000
-#define BUNCH       100
+#define LIST_LENGTH 4000
+#define NTHREADS    2
+
+#ifdef USE_HTM
+#  define BUNCH       200
+#else
+#  define BUNCH       200
+#endif
 
 typedef TLPREFIX struct node_s node_t;
 typedef node_t* nodeptr_t;
@@ -234,6 +243,7 @@
 
     setup_list();
 
+
     for (i = 1; i <= NTHREADS; i++) {
         newthread(demo2, (void*)(uintptr_t)i);
     }
diff --git a/gil-c7/stmgc.c b/gil-c7/stmgc.c
--- a/gil-c7/stmgc.c
+++ b/gil-c7/stmgc.c
@@ -267,10 +267,11 @@
         _stm_nursery_base = malloc(NURSERY_SIZE);
         assert(_stm_nursery_base);
         _stm_nursery_end = _stm_nursery_base + NURSERY_SIZE;
+        _stm_nursery_current = _stm_nursery_base;
     }
 
+    memset(_stm_nursery_base, 0, _stm_nursery_current-_stm_nursery_base);
     _stm_nursery_current = _stm_nursery_base;
-    memset(_stm_nursery_base, 0, NURSERY_SIZE);
 }
 
 #define WEAKREF_PTR(wr, sz)  ((object_t * TLPREFIX *)(((char *)(wr)) + (sz) - sizeof(void*)))
@@ -332,6 +333,7 @@
 {
     /* run minor collection */
     //fprintf(stderr, "minor collect\n");
+    _stm_nursery_current -= size_rounded_up;
     stm_collect(0);
 
     char *p = _stm_nursery_current;
diff --git a/htm-c7/stmgc.c b/htm-c7/stmgc.c
--- a/htm-c7/stmgc.c
+++ b/htm-c7/stmgc.c
@@ -7,9 +7,14 @@
 stm_thread_local_t *_stm_tloc;
 struct stm_segment_info_s _stm_segment;
 
+#define TRANSIENT_RETRY_MAX 5
+#define GIL_RETRY_MAX 5
 
+#define ABORT_GIL_LOCKED 1
 
 
+#define smp_spinloop()  asm volatile ("pause":::"memory")
+
 static void acquire_gil(stm_thread_local_t *tl) {
     if (pthread_mutex_lock(&_stm_gil) == 0) {
         _stm_tloc = tl;
@@ -18,32 +23,76 @@
     abort();
 }
 
+static int spin_and_acquire_gil(stm_thread_local_t *tl) {
+    int n = 100;
+    while ((n --> 0) && mutex_locked(&_stm_gil)) {
+        smp_spinloop();
+    }
+
+    if (!mutex_locked(&_stm_gil))
+        return 0;
+
+    acquire_gil(tl);
+    return 1;
+}
+
+static int is_persistent(int status) {
+    if ((status & XBEGIN_XABORT) && XBEGIN_XABORT_ARG(status) == ABORT_GIL_LOCKED)
+        return 0;
+    else if (status & (XBEGIN_MAYBE_RETRY | XBEGIN_NORMAL_CONFLICT))
+        return 0;
+    else if (status == XBEGIN_UNKNOWN)
+        return 0;
+    return 1;
+}
+
 void stm_start_inevitable_transaction(stm_thread_local_t *tl) {
+    /* set_transaction_length(pc) */
+
     if (mutex_locked(&_stm_gil)) {
-        acquire_gil(tl);
-        return;
+        if (spin_and_acquire_gil(tl))
+            return;
     }
 
     volatile int status;
+    volatile int transient_retry_counter = TRANSIENT_RETRY_MAX;
+    volatile int gil_retry_counter = GIL_RETRY_MAX;
+    volatile int first_retry = 1;
+
  transaction_retry:
-
     status = xbegin();
     if (status == XBEGIN_OK) {
         if (mutex_locked(&_stm_gil))
-            xabort(0);
+            xabort(ABORT_GIL_LOCKED);
         /* transaction OK */
     }
     else {
-        if (status & (XBEGIN_MAYBE_RETRY | XBEGIN_NORMAL_CONFLICT | XBEGIN_XABORT)) {
-            goto transaction_retry;
-        } else if (mutex_locked(&_stm_gil)) {
+        if (first_retry) {
+            first_retry = 0;
+            /* adjust_transaction_length(pc) */
+        }
+
+        if (mutex_locked(&_stm_gil)) {
+            gil_retry_counter--;
+            if (gil_retry_counter > 0) {
+                if (spin_and_acquire_gil(tl))
+                    return;
+                else
+                    goto transaction_retry;
+            }
             acquire_gil(tl);
-        }
-        else {
+        } else if (is_persistent(status)) {
+            acquire_gil(tl);
+        } else {
+            /* transient abort */
+            transient_retry_counter--;
+            if (transient_retry_counter > 0)
+                goto transaction_retry;
             acquire_gil(tl);
         }
 
-        fprintf(stderr, "failed HTM: %s\n", xbegin_status(status));
+        /* fprintf(stderr, "failed HTM: %s, t_retry: %d, gil_retry: %d\n", */
+        /*         xbegin_status(status), transient_retry_counter, gil_retry_counter); */
     }
 
     _stm_tloc = tl;
@@ -55,10 +104,10 @@
     if (mutex_locked(&_stm_gil)) {
         assert(!xtest());
         if (pthread_mutex_unlock(&_stm_gil) != 0) abort();
-        //fprintf(stderr, "G");
+        fprintf(stderr, "G");
     } else {
         xend();
-        fprintf(stderr, "==== Committed HTM ====\n");
+        fprintf(stderr, "H");
     }
 }
 
@@ -327,10 +376,11 @@
         _stm_nursery_base = malloc(NURSERY_SIZE);
         assert(_stm_nursery_base);
         _stm_nursery_end = _stm_nursery_base + NURSERY_SIZE;
+        _stm_nursery_current = _stm_nursery_base;
     }
 
+    memset(_stm_nursery_base, 0, _stm_nursery_current-_stm_nursery_base);
     _stm_nursery_current = _stm_nursery_base;
-    memset(_stm_nursery_base, 0, NURSERY_SIZE);
 }
 
 #define WEAKREF_PTR(wr, sz)  ((object_t * TLPREFIX *)(((char *)(wr)) + (sz) - sizeof(void*)))
@@ -392,6 +442,7 @@
 {
     /* run minor collection */
     //fprintf(stderr, "minor collect\n");
+    _stm_nursery_current -= size_rounded_up;
     stm_collect(0);
 
     char *p = _stm_nursery_current;


More information about the pypy-commit mailing list