summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2006-10-24 20:28:16 +0000
committerDaniel P. Berrange <berrange@redhat.com>2006-10-24 20:28:16 +0000
commit54db0825da704d121264647798fdd829a3ade6e2 (patch)
tree6b8a35f79a855041cdf8c3b57156a566516d149d
parent6606a75667802eaf7d956fb6a61ffaeaece9385d (diff)
downloadlibvirt-python-split-54db0825da704d121264647798fdd829a3ade6e2.tar.gz
libvirt-python-split-54db0825da704d121264647798fdd829a3ade6e2.tar.xz
libvirt-python-split-54db0825da704d121264647798fdd829a3ade6e2.zip
Make python bindings threaded, by dropping/acquiring Python GIL where needed
-rwxr-xr-xgenerator.py6
-rw-r--r--libvir.c25
-rw-r--r--libvirt_wrap.h50
3 files changed, 78 insertions, 3 deletions
diff --git a/generator.py b/generator.py
index 63f7635..e973db1 100755
--- a/generator.py
+++ b/generator.py
@@ -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 != "":
diff --git a/libvir.c b/libvir.c
index 907383b..3d580e5 100644
--- a/libvir.c
+++ b/libvir.c
@@ -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);
}
diff --git a/libvirt_wrap.h b/libvirt_wrap.h
index e745215..906245a 100644
--- a/libvirt_wrap.h
+++ b/libvirt_wrap.h
@@ -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
+