mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
Make python bindings threaded, by dropping/acquiring Python GIL where needed
This commit is contained in:
parent
297a77f6da
commit
9e5645393e
@ -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
|
||||
|
@ -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 != "":
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user