[pypy-commit] pypy stm-thread: Fish from the history stm_perform_transaction().
arigo
noreply at buildbot.pypy.org
Sun May 6 15:16:13 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: stm-thread
Changeset: r54909:61d19c0aebe3
Date: 2012-05-06 15:15 +0200
http://bitbucket.org/pypy/pypy/changeset/61d19c0aebe3/
Log: Fish from the history stm_perform_transaction(). Now, it is the only
way to start a non-inevitable transaction.
diff --git a/pypy/rlib/rstm.py b/pypy/rlib/rstm.py
--- a/pypy/rlib/rstm.py
+++ b/pypy/rlib/rstm.py
@@ -1,8 +1,12 @@
+import threading
from pypy.translator.stm import stmgcintf
from pypy.rlib.debug import ll_assert
-from pypy.rpython.lltypesystem import lltype
+from pypy.rlib.objectmodel import keepalive_until_here, specialize
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass
from pypy.rpython.lltypesystem.lloperation import llop
-
+from pypy.rpython.annlowlevel import (cast_base_ptr_to_instance,
+ cast_instance_to_base_ptr,
+ llhelper)
def before_external_call():
llop.stm_stop_transaction(lltype.Void)
@@ -36,8 +40,31 @@
leave_callback_call._dont_reach_me_in_del_ = True
leave_callback_call._transaction_break_ = True
-def do_yield_thread():
- stmgcintf.StmOperations.do_yield_thread()
-do_yield_thread._gctransformer_hint_close_stack_ = True
-do_yield_thread._dont_reach_me_in_del_ = True
-do_yield_thread._transaction_break_ = True
+# ____________________________________________________________
+
+ at specialize.memo()
+def _get_stm_callback(func, argcls):
+ def _stm_callback(llarg, retry_counter):
+ llop.stm_start_transaction(lltype.Void)
+ llarg = rffi.cast(rclass.OBJECTPTR, llarg)
+ arg = cast_base_ptr_to_instance(argcls, llarg)
+ try:
+ func(arg, retry_counter)
+ finally:
+ llop.stm_stop_transaction(lltype.Void)
+ return _stm_callback
+
+ at specialize.arg(0, 1)
+def perform_transaction(func, argcls, arg):
+ ll_assert(arg is None or isinstance(arg, argcls),
+ "perform_transaction: wrong class")
+ before_external_call()
+ llarg = cast_instance_to_base_ptr(arg)
+ llarg = rffi.cast(rffi.VOIDP, llarg)
+ adr_of_top = llop.gc_adr_of_root_stack_top(llmemory.Address)
+ #
+ callback = _get_stm_callback(func, argcls)
+ llcallback = llhelper(stmgcintf.StmOperations.CALLBACK_TX, callback)
+ stmgcintf.StmOperations.perform_transaction(llcallback, llarg, adr_of_top)
+ after_external_call()
+ keepalive_until_here(arg)
diff --git a/pypy/translator/stm/src_stm/core.c b/pypy/translator/stm/src_stm/core.c
--- a/pypy/translator/stm/src_stm/core.c
+++ b/pypy/translator/stm/src_stm/core.c
@@ -188,18 +188,15 @@
d->active = 0;
}
-static void tx_cleanup(struct tx_descriptor *d)
+static void tx_restart(struct tx_descriptor *d)
{
// release the locks and restore version numbers
releaseAndRevertLocks(d);
+ // notifies the CPU that we're potentially in a spin loop
+ tx_spinloop(0);
// reset all lists
common_cleanup(d);
-}
-
-static void tx_restart(struct tx_descriptor *d)
-{
- tx_cleanup(d);
- tx_spinloop(0);
+ // jump back to the setjmp_buf (this call does not return)
longjmp(*d->setjmp_buf, 1);
}
@@ -542,22 +539,27 @@
while (1)
{
- mutex_lock();
- unsigned long curtime = get_global_timestamp(d) & ~1;
- if (change_global_timestamp(d, curtime, curtime + 1))
+ unsigned long curtime = get_global_timestamp(d);
+ if (curtime & 1)
{
- d->start_time = curtime;
- break;
+ /* already an inevitable transaction: wait */
+ tx_spinloop(6);
+ mutex_lock();
+ mutex_unlock();
}
- mutex_unlock();
- tx_spinloop(6);
+ else
+ if (change_global_timestamp(d, curtime, curtime + 1))
+ {
+ d->start_time = curtime;
+ break;
+ }
}
}
void stm_commit_transaction(void)
{
struct tx_descriptor *d = thread_descriptor;
- assert(d != NULL);
+ assert(d->active != 0);
// if I don't have writes, I'm committed
if (!redolog_any_entry(&d->redolog))
@@ -740,6 +742,27 @@
return is_inevitable(d);
}
+void stm_perform_transaction(void(*callback)(void*, long), void *arg,
+ void *save_and_restore)
+{
+ jmp_buf _jmpbuf;
+ long volatile v_counter = 0;
+ long counter;
+ void *volatile saved_value;
+ struct tx_descriptor *d = thread_descriptor;
+ assert(d->active == 0);
+ saved_value = *(void**)save_and_restore;
+ /***/
+ setjmp(_jmpbuf);
+ /***/
+ *(void**)save_and_restore = saved_value;
+ begin_transaction(&_jmpbuf);
+ counter = v_counter;
+ v_counter = counter + 1;
+ callback(arg, counter);
+ stm_commit_transaction();
+}
+
#undef GETVERSION
#undef GETVERSIONREF
#undef SETVERSION
diff --git a/pypy/translator/stm/src_stm/et.h b/pypy/translator/stm/src_stm/et.h
--- a/pypy/translator/stm/src_stm/et.h
+++ b/pypy/translator/stm/src_stm/et.h
@@ -30,6 +30,8 @@
long stm_in_transaction(void);
long stm_is_inevitable(void);
+void stm_perform_transaction(void(*)(void*, long), void*, void*);
+
/* these functions are declared by generated C code from pypy.rlib.rstm
and from the GC (see llop.nop(...)) */
extern void pypy_g__stm_thread_starting(void);
diff --git a/pypy/translator/stm/stmgcintf.py b/pypy/translator/stm/stmgcintf.py
--- a/pypy/translator/stm/stmgcintf.py
+++ b/pypy/translator/stm/stmgcintf.py
@@ -35,8 +35,8 @@
'4f': rffi.FLOAT}
INIT_DONE = lltype.Ptr(lltype.FuncType([], lltype.Void))
- RUN_TRANSACTION = lltype.Ptr(lltype.FuncType([rffi.VOIDP, lltype.Signed],
- rffi.VOIDP))
+ CALLBACK_TX = lltype.Ptr(lltype.FuncType([rffi.VOIDP, lltype.Signed],
+ lltype.Void))
GETSIZE = lltype.Ptr(lltype.FuncType([llmemory.Address],
lltype.Signed))
CALLBACK_ENUM = lltype.Ptr(lltype.FuncType([llmemory.Address]*3,
@@ -54,8 +54,9 @@
'stm_begin_inevitable_transaction', [], lltype.Void)
commit_transaction = smexternal(
'stm_commit_transaction', [], lltype.Void)
- do_yield_thread = smexternal('stm_do_yield_thread',
- [], lltype.Void)
+ perform_transaction = smexternal('stm_perform_transaction',
+ [CALLBACK_TX, rffi.VOIDP, llmemory.Address],
+ lltype.Void)
# for the GC: store and read a thread-local-storage field, as well
# as initialize and shut down the internal thread_descriptor
diff --git a/pypy/translator/stm/test/targetdemo2.py b/pypy/translator/stm/test/targetdemo2.py
--- a/pypy/translator/stm/test/targetdemo2.py
+++ b/pypy/translator/stm/test/targetdemo2.py
@@ -64,11 +64,15 @@
def run(self):
try:
for value in range(glob.LENGTH):
- add_at_end_of_chained_list(glob.anchor, value, self.index)
- #rstm.do_yield_thread()
+ self.value = value
+ rstm.perform_transaction(ThreadRunner.run_really,
+ ThreadRunner, self)
finally:
self.finished_lock.release()
+ def run_really(self, retry_counter):
+ add_at_end_of_chained_list(glob.anchor, self.value, self.index)
+
# ____________________________________________________________
# bah, we are really missing an RPython interface to threads
More information about the pypy-commit
mailing list