]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
Make python bindings threaded, by dropping/acquiring Python GIL where needed
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 24 Oct 2006 20:28:16 +0000 (20:28 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 24 Oct 2006 20:28:16 +0000 (20:28 +0000)
ChangeLog
python/generator.py
python/libvir.c
python/libvirt_wrap.h

index 9ddb4720ea9cc8b09034c04af65a16bcd1d80234..5cbf24a6ae369d2fb9cc1dbbb37c2596ad0b2ef7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Tue Oct 24 15:31:23 EDT 2006 Daniel P.Berrange <berrange@redhat.com>
+
+       * python/generator.py, python/libvir.c: Drop python interpreter
+       lock when calling into C functions, and re-grab when invoking
+       error callback.
+       * python/libvirt_wrap.h: Convenience macros for grabbing / dropping
+       the python interpreter lock in threaded environment.
+
+
 Mon Oct 16 17:10:15 CEST 2006 Daniel Veillard <veillard@redhat.com>
 
        * config.h.in configure.in libvirt.spec.in docs/libvir.html
index 63f763561cdb8f3dfeff5c08084147f081113961..e973db193a238e28dc3521a0f231c9fbfae5a5a0 100755 (executable)
@@ -421,8 +421,10 @@ def print_function_wrapper(name, output, export, include):
         output.write("        return(NULL);\n")
     if c_convert != "":
         output.write(c_convert)
-                                                              
-    output.write(c_call)
+
+    output.write("LIBVIRT_BEGIN_ALLOW_THREADS;\n");
+    output.write(c_call);
+    output.write("LIBVIRT_END_ALLOW_THREADS;\n");
     output.write(ret_convert)
     output.write("}\n\n")
     if cond != None and cond != "":
index 907383b03f1640d48d8cb3b3f1eb7be67118b087..3d580e58462b95dda9097aeff89d0bfac312effa 100644 (file)
@@ -18,6 +18,8 @@
 void initlibvirmod(void);
 
 PyObject *libvirt_virDomainGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args);
+
+
 /************************************************************************
  *                                                                     *
  *             Global error handler at the Python level                *
@@ -40,6 +42,8 @@ libvirt_virErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, virErrorPtr err)
     if ((err == NULL) || (err->code == VIR_ERR_OK))
         return;
 
+    LIBVIRT_ENSURE_THREAD_STATE;
+
     if ((libvirt_virPythonErrorFuncHandler == NULL) ||
         (libvirt_virPythonErrorFuncHandler == Py_None)) {
         virDefaultErrorFunc(err);
@@ -63,6 +67,8 @@ libvirt_virErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, virErrorPtr err)
         Py_XDECREF(list);
         Py_XDECREF(result);
     }
+
+    LIBVIRT_RELEASE_THREAD_STATE;
 }
 
 static PyObject *
@@ -124,7 +130,9 @@ libvirt_virDomainFree(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
         return(NULL);
     domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
 
+    LIBVIRT_BEGIN_ALLOW_THREADS;
     c_retval = virDomainFree(domain);
+    LIBVIRT_END_ALLOW_THREADS;
     py_retval = libvirt_intWrap((int) c_retval);
     return(py_retval);
 }
@@ -140,7 +148,9 @@ libvirt_virConnectClose(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
         return(NULL);
     conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
 
+    LIBVIRT_BEGIN_ALLOW_THREADS;
     c_retval = virConnectClose(conn);
+    LIBVIRT_END_ALLOW_THREADS;
     py_retval = libvirt_intWrap((int) c_retval);
     return(py_retval);
 }
@@ -158,7 +168,9 @@ libvirt_virConnectListDomainsID(PyObject *self ATTRIBUTE_UNUSED,
         return(NULL);
     conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
 
+    LIBVIRT_BEGIN_ALLOW_THREADS;
     c_retval = virConnectListDomains(conn, &ids[0], 500);
+    LIBVIRT_END_ALLOW_THREADS;
     if (c_retval < 0) {
         Py_INCREF(Py_None);
        return(Py_None);
@@ -182,7 +194,9 @@ libvirt_virDomainGetInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
         return(NULL);
     domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
 
+    LIBVIRT_BEGIN_ALLOW_THREADS;
     c_retval = virDomainGetInfo(domain, &info);
+    LIBVIRT_END_ALLOW_THREADS;
     if (c_retval < 0) {
         Py_INCREF(Py_None);
        return(Py_None);
@@ -209,7 +223,9 @@ libvirt_virNodeGetInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
         return(NULL);
     conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
 
+    LIBVIRT_BEGIN_ALLOW_THREADS;
     c_retval = virNodeGetInfo(conn, &info);
+    LIBVIRT_END_ALLOW_THREADS;
     if (c_retval < 0) {
         Py_INCREF(Py_None);
        return(Py_None);
@@ -232,6 +248,7 @@ libvirt_virDomainGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
     unsigned char uuid[16];
     virDomainPtr domain;
     PyObject *pyobj_domain;
+    int c_retval;
 
     if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetUUID", &pyobj_domain))
         return(NULL);
@@ -241,7 +258,11 @@ libvirt_virDomainGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
         Py_INCREF(Py_None);
        return(Py_None);
     }
-    if (virDomainGetUUID(domain, &uuid[0]) < 0) {
+    LIBVIRT_BEGIN_ALLOW_THREADS;
+    c_retval = virDomainGetUUID(domain, &uuid[0]);
+    LIBVIRT_END_ALLOW_THREADS;
+
+    if (c_retval < 0) {
         Py_INCREF(Py_None);
        return(Py_None);
     }
@@ -268,7 +289,9 @@ libvirt_virDomainLookupByUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
        return(Py_None);
     }
 
+    LIBVIRT_BEGIN_ALLOW_THREADS;
     c_retval = virDomainLookupByUUID(conn, uuid);
+    LIBVIRT_END_ALLOW_THREADS;
     py_retval = libvirt_virDomainPtrWrap((virDomainPtr) c_retval);
     return(py_retval);
 }
index e7452159e7aef9fd5265167aeefa280dbada00cb..906245aeee1b3ab29d0a4d43ef9fb82ebd5e0dc7 100644 (file)
@@ -48,3 +48,53 @@ PyObject * libvirt_charPtrConstWrap(const char *str);
 PyObject * libvirt_virConnectPtrWrap(virConnectPtr node);
 PyObject * libvirt_virDomainPtrWrap(virDomainPtr node);
 
+
+/* Provide simple macro statement wrappers (adapted from GLib, in turn from Perl):
+ *  LIBVIRT_STMT_START { statements; } LIBVIRT_STMT_END;
+ *  can be used as a single statement, as in
+ *  if (x) LIBVIRT_STMT_START { ... } LIBVIRT_STMT_END; else ...
+ *
+ *  When GCC is compiling C code in non-ANSI mode, it will use the
+ *  compiler __extension__ to wrap the statements wihin `({' and '})' braces.
+ *  When compiling on platforms where configure has defined
+ *  HAVE_DOWHILE_MACROS, statements will be wrapped with `do' and `while (0)'.
+ *  For any other platforms (SunOS4 is known to have this issue), wrap the
+ *  statements with `if (1)' and `else (void) 0'.
+ */
+#if !(defined (LIBVIRT_STMT_START) && defined (LIBVIRT_STMT_END))
+# if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
+#  define LIBVIRT_STMT_START (void) __extension__ (
+#  define LIBVIRT_STMT_END )
+# else /* !(__GNUC__ && !__STRICT_ANSI__ && !__cplusplus) */
+#  if defined (HAVE_DOWHILE_MACROS)
+#   define LIBVIRT_STMT_START do
+#   define LIBVIRT_STMT_END while (0)
+#  else /* !HAVE_DOWHILE_MACROS */
+#   define LIBVIRT_STMT_START if (1)
+#   define LIBVIRT_STMT_END else (void) 0
+#  endif /* !HAVE_DOWHILE_MACROS */
+# endif /* !(__GNUC__ && !__STRICT_ANSI__ && !__cplusplus) */
+#endif
+
+#define LIBVIRT_BEGIN_ALLOW_THREADS                    \
+  LIBVIRT_STMT_START {                                 \
+    PyThreadState *_save = NULL;                       \
+    if (PyEval_ThreadsInitialized())                   \
+      _save = PyEval_SaveThread();
+
+#define LIBVIRT_END_ALLOW_THREADS                           \
+  if (PyEval_ThreadsInitialized())                         \
+    PyEval_RestoreThread(_save);                           \
+    } LIBVIRT_STMT_END
+
+#define LIBVIRT_ENSURE_THREAD_STATE                    \
+  LIBVIRT_STMT_START {                                 \
+  PyGILState_STATE _save;                              \
+    if (PyEval_ThreadsInitialized())                   \
+      _save = PyGILState_Ensure();
+
+#define LIBVIRT_RELEASE_THREAD_STATE                           \
+  if (PyEval_ThreadsInitialized())                            \
+    PyGILState_Release(_save);                                \
+  } LIBVIRT_STMT_END
+