[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