[pypy-commit] pypy portable-threadlocal: in-progress
arigo
noreply at buildbot.pypy.org
Sat Nov 22 20:22:30 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: portable-threadlocal
Changeset: r74639:2d35c55a318d
Date: 2014-11-22 20:22 +0100
http://bitbucket.org/pypy/pypy/changeset/2d35c55a318d/
Log: in-progress
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -1080,6 +1080,9 @@
assert not livevars, "live GC var around %s!" % (hop.spaceop,)
hop.genop("direct_call", [self.root_walker.thread_run_ptr])
self.pop_roots(hop, livevars)
+ else:
+ hop.rename("gc_thread_run") # keep it around for c/gc.py,
+ # unless handled specially above
def gct_gc_thread_start(self, hop):
assert self.translator.config.translation.thread
@@ -1095,6 +1098,7 @@
assert not livevars, "live GC var around %s!" % (hop.spaceop,)
hop.genop("direct_call", [self.root_walker.thread_die_ptr])
self.pop_roots(hop, livevars)
+ hop.rename("gc_thread_die") # keep it around for c/gc.py
def gct_gc_thread_before_fork(self, hop):
if (self.translator.config.translation.thread
diff --git a/rpython/memory/gctransform/shadowstack.py b/rpython/memory/gctransform/shadowstack.py
--- a/rpython/memory/gctransform/shadowstack.py
+++ b/rpython/memory/gctransform/shadowstack.py
@@ -132,8 +132,12 @@
gcdata.root_stack_top/root_stack_base is the one corresponding
to the current thread.
No GC operation here, e.g. no mallocs or storing in a dict!
+
+ Note that here specifically we don't call rthread.get_ident(),
+ but rthread.get_or_make_ident(). We are possibly in a fresh
+ new thread, so we need to be careful.
"""
- tid = get_tid()
+ tid = rthread.get_or_make_ident()
if gcdata.active_tid != tid:
switch_shadow_stacks(tid)
diff --git a/rpython/rlib/rthread.py b/rpython/rlib/rthread.py
--- a/rpython/rlib/rthread.py
+++ b/rpython/rlib/rthread.py
@@ -90,6 +90,10 @@
import thread
return thread.get_ident()
+def get_or_make_ident():
+ assert we_are_translated()
+ return tlfield_thread_ident.get_or_make_raw()
+
@specialize.arg(0)
def start_new_thread(x, y):
"""In RPython, no argument can be passed. You have to use global
@@ -283,12 +287,18 @@
addr = llop.threadlocalref_addr(rffi.CCHARP)
return llop.raw_load(FIELDTYPE, addr, offset)
+ def get_or_make_raw():
+ _threadlocalref_seeme(self)
+ addr = llop.threadlocalref_make(rffi.CCHARP)
+ return llop.raw_load(FIELDTYPE, addr, offset)
+
def setraw(value):
_threadlocalref_seeme(self)
addr = llop.threadlocalref_addr(rffi.CCHARP)
llop.raw_store(lltype.Void, addr, offset, value)
self.getraw = getraw
+ self.get_or_make_raw = get_or_make_raw
self.setraw = setraw
def _freeze_(self):
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -920,12 +920,7 @@
return 0
def op_threadlocalref_addr(self, key, value):
- raise NotImplementedError("threadlocalref_addr") # XXX implement me?
- try:
- d = self.llinterpreter.tlrefsdict
- except AttributeError:
- d = self.llinterpreter.tlrefsdict = {}
- d[key._obj] = value
+ raise NotImplementedError("threadlocalref_addr")
# __________________________________________________________
# operations on addresses
diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -547,6 +547,7 @@
'check_and_clear_exc': LLOp(),
'threadlocalref_addr': LLOp(sideeffects=False),
+ 'threadlocalref_make': LLOp(),
# __________ debugging __________
'debug_view': LLOp(),
diff --git a/rpython/translator/c/gc.py b/rpython/translator/c/gc.py
--- a/rpython/translator/c/gc.py
+++ b/rpython/translator/c/gc.py
@@ -71,13 +71,13 @@
return ''
def OP_GC_THREAD_RUN(self, funcgen, op):
- return ''
+ return '{ char *r; OP_THREADLOCALREF_MAKE(r); (void)r; } '
def OP_GC_THREAD_START(self, funcgen, op):
return ''
def OP_GC_THREAD_DIE(self, funcgen, op):
- return ''
+ return 'RPython_ThreadLocals_ThreadDie();'
def OP_GC_THREAD_BEFORE_FORK(self, funcgen, op):
return '%s = NULL;' % funcgen.expr(op.result)
diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py
--- a/rpython/translator/c/genc.py
+++ b/rpython/translator/c/genc.py
@@ -716,6 +716,7 @@
print >> f, ('#define RPY_TLOFS_%s offsetof(' % field.fieldname +
'struct pypy_threadlocal_s, %s)' % field.fieldname)
print >> f, 'struct pypy_threadlocal_s {'
+ print >> f, '\tint ready;'
print >> f, '\tchar *stack_end;'
for field in fields:
typename = database.gettype(field.FIELDTYPE)
diff --git a/rpython/translator/c/src/threadlocal.c b/rpython/translator/c/src/threadlocal.c
--- a/rpython/translator/c/src/threadlocal.c
+++ b/rpython/translator/c/src/threadlocal.c
@@ -18,7 +18,7 @@
#endif
-static void _RPython_ThreadLocals_Init(void *p)
+static void _RPy_ThreadLocals_Init(void *p)
{
memset(p, 0, sizeof(struct pypy_threadlocal_s));
#ifdef RPY_TLOFS_p_errno
@@ -27,6 +27,7 @@
#ifdef RPY_TLOFS_thread_ident
((struct pypy_threadlocal_s *)p)->thread_ident = RPyThreadGetIdent();
#endif
+ ((struct pypy_threadlocal_s *)p)->ready = 1;
}
@@ -35,20 +36,24 @@
/* ------------------------------------------------------------ */
+/* in this situation, we always have one full 'struct pypy_threadlocal_s'
+ available, managed by gcc. */
__thread struct pypy_threadlocal_s pypy_threadlocal;
void RPython_ThreadLocals_ProgramInit(void)
{
- RPython_ThreadLocals_ThreadStart();
+ _RPy_ThreadLocals_Init(&pypy_threadlocal);
}
-void RPython_ThreadLocals_ThreadStart(void)
+char *_RPython_ThreadLocals_Build(void)
{
- _RPython_ThreadLocals_Init(&pypy_threadlocal);
+ _RPy_ThreadLocals_Init(&pypy_threadlocal);
+ return (char *)&pypy_threadlocal;
}
void RPython_ThreadLocals_ThreadDie(void)
{
+ pypy_threadlocal.ready = 0;
}
@@ -57,6 +62,16 @@
/* ------------------------------------------------------------ */
+/* this is the case where the 'struct pypy_threadlocal_s' is allocated
+ explicitly, with malloc()/free(), and attached to (a single) thread-
+ local key using the API of Windows or pthread. */
+
+#ifdef _WIN32
+# define _RPy_ThreadLocals_Set(p) TlsSetValue(pypy_threadlocal_key, p)
+#else
+# define _RPy_ThreadLocals_Set(p) pthread_setspecific(pypy_threadlocal_key, p)
+#endif
+
void RPython_ThreadLocals_ProgramInit(void)
{
#ifdef _WIN32
@@ -70,10 +85,10 @@
"out of thread-local storage indexes");
abort();
}
- RPython_ThreadLocals_ThreadStart();
+ _RPython_ThreadLocals_Build();
}
-void RPython_ThreadLocals_ThreadStart(void)
+char *_RPython_ThreadLocals_Build(void)
{
void *p = malloc(sizeof(struct pypy_threadlocal_s));
if (!p) {
@@ -81,18 +96,16 @@
"out of memory for the thread-local storage");
abort();
}
- _RPython_ThreadLocals_Init(p);
-#ifdef _WIN32
- TlsSetValue(pypy_threadlocal_key, p);
-#else
- pthread_setspecific(pypy_threadlocal_key, p);
-#endif
+ _RPy_ThreadLocals_Init(p);
+ _RPy_ThreadLocals_Set(p);
+ return (char *)p;
}
void RPython_ThreadLocals_ThreadDie(void)
{
void *p;
OP_THREADLOCALREF_ADDR(p);
+ _RPy_ThreadLocals_Set(NULL);
free(p);
}
diff --git a/rpython/translator/c/src/threadlocal.h b/rpython/translator/c/src/threadlocal.h
--- a/rpython/translator/c/src/threadlocal.h
+++ b/rpython/translator/c/src/threadlocal.h
@@ -5,6 +5,22 @@
#include <src/precommondefs.h>
+/* RPython_ThreadLocals_ProgramInit() is called once at program start-up. */
+RPY_EXTERN void RPython_ThreadLocals_ProgramInit(void);
+
+/* RPython_ThreadLocals_ThreadDie() is called in a thread that is about
+ to die. */
+RPY_EXTERN void RPython_ThreadLocals_ThreadDie(void);
+
+/* There are two llops: 'threadlocalref_addr' and 'threadlocalref_make'.
+ They both return the address of the thread-local structure (of the
+ C type 'struct pypy_threadlocal_s'). The difference is that
+ OP_THREADLOCALREF_MAKE() checks if we have initialized this thread-
+ local structure in the current thread, and if not, calls the following
+ helper. */
+RPY_EXTERN char *_RPython_ThreadLocals_Build(void);
+
+
/* ------------------------------------------------------------ */
#ifdef USE___THREAD
/* ------------------------------------------------------------ */
@@ -14,6 +30,9 @@
RPY_EXTERN __thread struct pypy_threadlocal_s pypy_threadlocal;
#define OP_THREADLOCALREF_ADDR(r) r = (char *)&pypy_threadlocal
+#define OP_THREADLOCALREF_MAKE(r) \
+ (OP_THREADLOCALREF_ADDR(r), \
+ (pypy_threadlocal.ready || (r = _RPython_ThreadLocals_Build())))
/* ------------------------------------------------------------ */
@@ -27,6 +46,9 @@
RPY_EXTERN DWORD pypy_threadlocal_key;
#define OP_THREADLOCALREF_ADDR(r) r = (char *)TlsGetValue( \
pypy_threadlocal_key)
+#define OP_THREADLOCALREF_MAKE(r) \
+ (OP_THREADLOCALREF_ADDR(r), \
+ ((r) || (r = _RPython_ThreadLocals_Build())))
/* ------------------------------------------------------------ */
@@ -41,6 +63,9 @@
RPY_EXTERN pthread_key_t pypy_threadlocal_key;
#define OP_THREADLOCALREF_ADDR(r) r = (char *)pthread_getspecific( \
pypy_threadlocal_key)
+#define OP_THREADLOCALREF_MAKE(r) \
+ (OP_THREADLOCALREF_ADDR(r), \
+ ((r) || (r = _RPython_ThreadLocals_Build())))
/* ------------------------------------------------------------ */
@@ -48,8 +73,4 @@
/* ------------------------------------------------------------ */
-RPY_EXTERN void RPython_ThreadLocals_ProgramInit(void);
-RPY_EXTERN void RPython_ThreadLocals_ThreadStart(void);
-RPY_EXTERN void RPython_ThreadLocals_ThreadDie(void);
-
#endif /* _SRC_THREADLOCAL_H */
More information about the pypy-commit
mailing list