[pypy-svn] r16302 - in pypy/dist/pypy/translator/c: . src test
arigo at codespeak.net
arigo at codespeak.net
Tue Aug 23 17:55:30 CEST 2005
Author: arigo
Date: Tue Aug 23 17:55:27 2005
New Revision: 16302
Modified:
pypy/dist/pypy/translator/c/database.py
pypy/dist/pypy/translator/c/genc.py
pypy/dist/pypy/translator/c/node.py
pypy/dist/pypy/translator/c/src/ll_thread.h
pypy/dist/pypy/translator/c/src/main.h
pypy/dist/pypy/translator/c/src/module.h
pypy/dist/pypy/translator/c/src/thread_nt.h
pypy/dist/pypy/translator/c/src/thread_pthread.h
pypy/dist/pypy/translator/c/test/test_extfunc.py
Log:
(rxe, arigo)
Support in genc for prebuilt external objects -- in this case, prebuilt locks.
Split OpaqueNode into xxx_OpaqueNode classes for the various usages of opaque
prebuilt constants.
Lots of changes; this required producing and calling start-up code to the
generated C source.
Each thread_*.h needs to provide in the RPyOpaque_INITEXPR_ThreadLock macro an
expression suitable for a lock initializer (though RPyThreadLockInit() is
still called on the structure from the start-up code).
Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py (original)
+++ pypy/dist/pypy/translator/c/database.py Tue Aug 23 17:55:27 2005
@@ -5,7 +5,7 @@
from pypy.translator.c.primitive import PrimitiveName, PrimitiveType
from pypy.translator.c.primitive import PrimitiveErrorValue
from pypy.translator.c.node import StructDefNode, ArrayDefNode
-from pypy.translator.c.node import ContainerNodeClass, ExtTypeOpaqueDefNode
+from pypy.translator.c.node import ContainerNodeFactory, ExtTypeOpaqueDefNode
from pypy.translator.c.support import cdecl, CNameManager, ErrorValue
from pypy.translator.c.pyobj import PyObjMaker
from pypy.translator.c import gc
@@ -92,8 +92,8 @@
node = self.containernodes[container]
except KeyError:
T = typeOf(container)
- nodecls = ContainerNodeClass[T.__class__]
- node = nodecls(self, T, container)
+ nodefactory = ContainerNodeFactory[T.__class__]
+ node = nodefactory(self, T, container)
self.containernodes[container] = node
self.containerlist.append(node)
return node
Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py (original)
+++ pypy/dist/pypy/translator/c/genc.py Tue Aug 23 17:55:27 2005
@@ -159,6 +159,23 @@
print >> f, line
blank = True
+def gen_startupcode(f, database):
+ # generate the start-up code and put it into a function
+ print >> f, 'char *RPython_StartupCode(void) {'
+ print >> f, '\tchar *error = NULL;'
+ firsttime = True
+ for node in database.containerlist:
+ lines = list(node.startupcode())
+ if lines:
+ if firsttime:
+ firsttime = False
+ else:
+ print >> f, '\tif (error) return error;'
+ for line in lines:
+ print >> f, '\t'+line
+ print >> f, '\treturn error;'
+ print >> f, '}'
+
def gen_source_standalone(database, modulename, targetdir,
entrypointname, defines={}):
assert database.standalone
@@ -184,6 +201,10 @@
#
gen_readable_parts_of_main_c_file(f, database, preimplementationlines)
+ # 3) start-up code
+ print >> f
+ gen_startupcode(f, database)
+
f.close()
return filename
@@ -302,6 +323,8 @@
print >> f, '/***********************************************************/'
print >> f, '/*** Module initialization function ***/'
print >> f
+ gen_startupcode(f, database)
+ print >> f
print >> f, 'MODULE_INITFUNC(%s)' % modulename
print >> f, '{'
print >> f, '\tSETUP_MODULE(%s);' % modulename
Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py (original)
+++ pypy/dist/pypy/translator/c/node.py Tue Aug 23 17:55:27 2005
@@ -346,6 +346,9 @@
lines[-1] += ';'
return lines
+ def startupcode(self):
+ return []
+
def getlength(self):
return 1
@@ -553,7 +556,7 @@
raise ValueError, "don't know how to generate code for %r" % (fnobj,)
-class OpaqueNode(ContainerNode):
+class RuntimeTypeInfo_OpaqueNode(ContainerNode):
globalcontainer = True
includes = ()
@@ -574,6 +577,34 @@
return []
+class ExtType_OpaqueNode(ContainerNode):
+
+ def enum_dependencies(self):
+ return []
+
+ def initializationexpr(self, decoration=''):
+ yield 'RPyOpaque_INITEXPR_%s' % (self.T.tag,)
+
+ def startupcode(self):
+ args = [self.ptrname]
+ # XXX how to make this code more generic?
+ if self.T.tag == 'ThreadLock':
+ lock = self.obj.externalobj
+ if lock.locked():
+ args.append('1')
+ else:
+ args.append('0')
+ yield 'RPyOpaque_SETUP_%s(%s);' % (self.T.tag, ', '.join(args))
+
+
+def opaquenode_factory(db, T, obj):
+ if T == RuntimeTypeInfo:
+ return RuntimeTypeInfo_OpaqueNode(db, T, obj)
+ if hasattr(T, '_exttypeinfo'):
+ return ExtType_OpaqueNode(db, T, obj)
+ raise Exception("don't know about %r" % (T,))
+
+
class PyObjectNode(ContainerNode):
globalcontainer = True
typename = 'PyObject @'
@@ -601,12 +632,12 @@
return []
-ContainerNodeClass = {
+ContainerNodeFactory = {
Struct: StructNode,
GcStruct: StructNode,
Array: ArrayNode,
GcArray: ArrayNode,
FuncType: FuncNode,
- OpaqueType: OpaqueNode,
+ OpaqueType: opaquenode_factory,
PyObjectType: PyObjectNode,
}
Modified: pypy/dist/pypy/translator/c/src/ll_thread.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/ll_thread.h (original)
+++ pypy/dist/pypy/translator/c/src/ll_thread.h Tue Aug 23 17:55:27 2005
@@ -50,3 +50,9 @@
{
return RPyThreadGetIdent();
}
+
+#define RPyOpaque_SETUP_ThreadLock(lock, initially_locked) \
+ if (!RPyThreadLockInit(lock)) \
+ error = "Thread lock init error"; \
+ else if ((initially_locked) && !RPyThreadAcquireLock(lock, 1)) \
+ error = "Cannot acquire thread lock at init";
Modified: pypy/dist/pypy/translator/c/src/main.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/main.h (original)
+++ pypy/dist/pypy/translator/c/src/main.h Tue Aug 23 17:55:27 2005
@@ -1,14 +1,26 @@
#define STANDALONE_ENTRY_POINT PYPY_STANDALONE
+char *RPython_StartupCode(void); /* forward */
+
+
int main(int argc, char *argv[])
{
+ char *errmsg = "out of memory";
int i;
RPyListOfString *list = RPyListOfString_New(argc);
+ if (RPyExceptionOccurred()) goto error;
for (i=0; i<argc; i++) {
RPyString *s = RPyString_FromString(argv[i]);
+ if (RPyExceptionOccurred()) goto error;
RPyListOfString_SetItem(list, i, s);
}
+ errmsg = RPython_StartupCode();
+ if (errmsg) goto error;
+
return STANDALONE_ENTRY_POINT(list);
-}
+ error:
+ fprintf(stderr, "Fatal error during initialization: %s\n", errmsg);
+ return 1;
+}
Modified: pypy/dist/pypy/translator/c/src/module.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/module.h (original)
+++ pypy/dist/pypy/translator/c/src/module.h Tue Aug 23 17:55:27 2005
@@ -19,6 +19,7 @@
PyMODINIT_FUNC init##modname(void)
#define SETUP_MODULE(modname) \
+ char *errmsg; \
PyObject *m = Py_InitModule(#modname, my_methods); \
PyModule_AddStringConstant(m, "__sourcefile__", __FILE__); \
this_module_globals = PyModule_GetDict(m); \
@@ -34,8 +35,12 @@
if (setup_initcode(frozen_initcode, FROZEN_INITCODE_SIZE) < 0) \
return; \
if (setup_globalobjects(globalobjectdefs) < 0) \
- return
-
+ return; \
+ errmsg = RPython_StartupCode(); \
+ if (errmsg) { \
+ PyErr_SetString(PyExc_RuntimeError, errmsg); \
+ return; \
+ }
/*** table of global objects ***/
Modified: pypy/dist/pypy/translator/c/src/thread_nt.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/thread_nt.h (original)
+++ pypy/dist/pypy/translator/c/src/thread_nt.h Tue Aug 23 17:55:27 2005
@@ -76,6 +76,9 @@
HANDLE hevent ;
} NRMUTEX, *PNRMUTEX ;
+#define RPyOpaque_INITEXPR_ThreadLock { 0, 0, NULL }
+
+
typedef PVOID WINAPI interlocked_cmp_xchg_t(PVOID *dest, PVOID exc, PVOID comperand) ;
/* Sorry mate, but we haven't got InterlockedCompareExchange in Win95! */
Modified: pypy/dist/pypy/translator/c/src/thread_pthread.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/thread_pthread.h (original)
+++ pypy/dist/pypy/translator/c/src/thread_pthread.h Tue Aug 23 17:55:27 2005
@@ -114,6 +114,8 @@
int initialized;
};
+#define RPyOpaque_INITEXPR_ThreadLock { { /* sem */ }, 0 }
+
int RPyThreadLockInit(struct RPyOpaque_ThreadLock *lock)
{
int status, error = 0;
@@ -195,6 +197,12 @@
pthread_mutex_t mut;
};
+#define RPyOpaque_INITEXPR_ThreadLock { \
+ 0, 0, \
+ PTHREAD_COND_INITIALIZER, \
+ PTHREAD_MUTEX_INITIALIZER \
+ }
+
int RPyThreadLockInit(struct RPyOpaque_ThreadLock *lock)
{
int status, error = 0;
Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_extfunc.py (original)
+++ pypy/dist/pypy/translator/c/test/test_extfunc.py Tue Aug 23 17:55:27 2005
@@ -372,3 +372,20 @@
f = compile(fn, [])
res = f()
assert res == 42
+
+def test_prebuilt_lock():
+ import thread
+ import pypy.module.thread.rpython.exttable # for declare()/declaretype()
+ lock0 = thread.allocate_lock()
+ lock1 = thread.allocate_lock()
+ lock1.acquire()
+ def fn(i):
+ lock = [lock0, lock1][i]
+ ok = lock.acquire(False)
+ if ok: lock.release()
+ return ok
+ f = compile(fn, [int])
+ res = f(0)
+ assert res is True
+ res = f(1)
+ assert res is False
More information about the Pypy-commit
mailing list