[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