[libvirt] [RFC PATCH 2/2] qemu: use virObject to manage reference-counting for qemu monitor

Hu Tao hutao at cn.fujitsu.com
Wed Mar 16 10:30:20 UTC 2011


---
 src/qemu/qemu_domain.c  |   26 +-----------
 src/qemu/qemu_monitor.c |  106 ++++++++++++++++++++++++++--------------------
 src/qemu/qemu_monitor.h |    4 +-
 3 files changed, 64 insertions(+), 72 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 8a2b9cc..e056ef0 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -566,7 +566,6 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj)
     qemuDomainObjPrivatePtr priv = obj->privateData;
 
     qemuMonitorLock(priv->mon);
-    qemuMonitorRef(priv->mon);
     virDomainObjUnlock(obj);
 }
 
@@ -578,19 +577,9 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj)
 void qemuDomainObjExitMonitor(virDomainObjPtr obj)
 {
     qemuDomainObjPrivatePtr priv = obj->privateData;
-    int refs;
-
-    refs = qemuMonitorUnref(priv->mon);
-
-    if (refs > 0)
-        qemuMonitorUnlock(priv->mon);
 
+    qemuMonitorUnlock(priv->mon);
     virDomainObjLock(obj);
-
-    if (refs == 0) {
-        virDomainObjUnref(obj);
-        priv->mon = NULL;
-    }
 }
 
 
@@ -608,7 +597,6 @@ void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver,
     qemuDomainObjPrivatePtr priv = obj->privateData;
 
     qemuMonitorLock(priv->mon);
-    qemuMonitorRef(priv->mon);
     virDomainObjUnlock(obj);
     qemuDriverUnlock(driver);
 }
@@ -623,20 +611,10 @@ void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver,
                                         virDomainObjPtr obj)
 {
     qemuDomainObjPrivatePtr priv = obj->privateData;
-    int refs;
-
-    refs = qemuMonitorUnref(priv->mon);
-
-    if (refs > 0)
-        qemuMonitorUnlock(priv->mon);
 
+    qemuMonitorUnlock(priv->mon);
     qemuDriverLock(driver);
     virDomainObjLock(obj);
-
-    if (refs == 0) {
-        virDomainObjUnref(obj);
-        priv->mon = NULL;
-    }
 }
 
 void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver,
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 37401df..d37265e 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -37,6 +37,7 @@
 #include "memory.h"
 #include "logging.h"
 #include "files.h"
+#include "object.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
@@ -44,11 +45,10 @@
 #define DEBUG_RAW_IO 0
 
 struct _qemuMonitor {
+    virObject obj;
     virMutex lock; /* also used to protect fd */
     virCond notify;
 
-    int refs;
-
     int fd;
     int watch;
     int hasSendFD;
@@ -202,35 +202,66 @@ void qemuMonitorUnlock(qemuMonitorPtr mon)
 }
 
 
-static void qemuMonitorFree(qemuMonitorPtr mon)
+static void doMonitorFree(virObjectPtr obj)
 {
+    qemuMonitorPtr mon = (qemuMonitorPtr)obj;
+
     VIR_DEBUG("mon=%p", mon);
     if (mon->cb && mon->cb->destroy)
         (mon->cb->destroy)(mon, mon->vm);
-    if (virCondDestroy(&mon->notify) < 0)
-    {}
+    ignore_value(virCondDestroy(&mon->notify));
     virMutexDestroy(&mon->lock);
     VIR_FREE(mon->buffer);
     VIR_FREE(mon);
 }
 
-int qemuMonitorRef(qemuMonitorPtr mon)
+static qemuMonitorPtr qemuMonitorAlloc(void)
 {
-    mon->refs++;
-    return mon->refs;
+    qemuMonitorPtr mon;
+
+    if (VIR_ALLOC(mon) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    if (virObjectInit(&mon->obj, doMonitorFree)) {
+        VIR_FREE(mon);
+        return NULL;
+    }
+
+    if (virMutexInit(&mon->lock) < 0) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("cannot initialize monitor mutex"));
+        VIR_FREE(mon);
+        return NULL;
+    }
+
+    if (virCondInit(&mon->notify) < 0) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("cannot initialize monitor condition"));
+        virMutexDestroy(&mon->lock);
+        VIR_FREE(mon);
+        return NULL;
+    }
+
+    mon->fd = -1;
+
+    return mon;
 }
 
-int qemuMonitorUnref(qemuMonitorPtr mon)
+static void qemuMonitorFree(qemuMonitorPtr mon)
 {
-    mon->refs--;
+    virObjectUnref(&mon->obj);
+}
 
-    if (mon->refs == 0) {
-        qemuMonitorUnlock(mon);
-        qemuMonitorFree(mon);
-        return 0;
-    }
+void qemuMonitorRef(qemuMonitorPtr mon)
+{
+    virObjectRef(&mon->obj);
+}
 
-    return mon->refs;
+void qemuMonitorUnref(qemuMonitorPtr mon)
+{
+    virObjectUnref(&mon->obj);
 }
 
 static void
@@ -238,7 +269,6 @@ qemuMonitorUnwatch(void *monitor)
 {
     qemuMonitorPtr mon = monitor;
 
-    qemuMonitorLock(mon);
     qemuMonitorUnref(mon);
 }
 
@@ -519,7 +549,6 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
 
     /* lock access to the monitor and protect fd */
     qemuMonitorLock(mon);
-    qemuMonitorRef(mon);
 #if DEBUG_IO
     VIR_DEBUG("Monitor %p I/O on watch %d fd %d events %d", mon, watch, fd, events);
 #endif
@@ -587,13 +616,11 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
         virDomainObjPtr vm = mon->vm;
         /* Make sure anyone waiting wakes up now */
         virCondSignal(&mon->notify);
-        if (qemuMonitorUnref(mon) > 0)
-            qemuMonitorUnlock(mon);
+        qemuMonitorUnlock(mon);
         VIR_DEBUG("Triggering EOF callback error? %d", failed);
         (eofNotify)(mon, vm, failed);
     } else {
-        if (qemuMonitorUnref(mon) > 0)
-            qemuMonitorUnlock(mon);
+        qemuMonitorUnlock(mon);
     }
 }
 
@@ -612,30 +639,13 @@ qemuMonitorOpen(virDomainObjPtr vm,
         return NULL;
     }
 
-    if (VIR_ALLOC(mon) < 0) {
-        virReportOOMError();
+    mon = qemuMonitorAlloc();
+    if (!mon)
         return NULL;
-    }
 
-    if (virMutexInit(&mon->lock) < 0) {
-        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                        _("cannot initialize monitor mutex"));
-        VIR_FREE(mon);
-        return NULL;
-    }
-    if (virCondInit(&mon->notify) < 0) {
-        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                        _("cannot initialize monitor condition"));
-        virMutexDestroy(&mon->lock);
-        VIR_FREE(mon);
-        return NULL;
-    }
-    mon->fd = -1;
-    mon->refs = 1;
     mon->vm = vm;
     mon->json = json;
     mon->cb = cb;
-    qemuMonitorLock(mon);
 
     switch (config->type) {
     case VIR_DOMAIN_CHR_TYPE_UNIX:
@@ -668,6 +678,12 @@ qemuMonitorOpen(virDomainObjPtr vm,
     }
 
 
+    /* mon will be accessed by qemuMonitorIO which is called in
+     * event thread, so ref it before passing it to the thread.
+     *
+     * Note: mon is unrefed in qemuMonitorUnwatch
+     */
+    qemuMonitorRef(mon);
     if ((mon->watch = virEventAddHandle(mon->fd,
                                         VIR_EVENT_HANDLE_HANGUP |
                                         VIR_EVENT_HANDLE_ERROR |
@@ -678,10 +694,8 @@ qemuMonitorOpen(virDomainObjPtr vm,
                         _("unable to register monitor events"));
         goto cleanup;
     }
-    qemuMonitorRef(mon);
 
     VIR_DEBUG("New mon %p fd =%d watch=%d", mon, mon->fd, mon->watch);
-    qemuMonitorUnlock(mon);
 
     return mon;
 
@@ -692,8 +706,8 @@ cleanup:
      * so kill the callbacks now.
      */
     mon->cb = NULL;
-    qemuMonitorUnlock(mon);
     qemuMonitorClose(mon);
+    qemuMonitorFree(mon);
     return NULL;
 }
 
@@ -713,8 +727,8 @@ void qemuMonitorClose(qemuMonitorPtr mon)
         VIR_FORCE_CLOSE(mon->fd);
     }
 
-    if (qemuMonitorUnref(mon) > 0)
-        qemuMonitorUnlock(mon);
+    qemuMonitorUnlock(mon);
+    qemuMonitorFree(mon);
 }
 
 
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index ece15a8..4d6b12e 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -130,8 +130,8 @@ int qemuMonitorSetCapabilities(qemuMonitorPtr mon);
 void qemuMonitorLock(qemuMonitorPtr mon);
 void qemuMonitorUnlock(qemuMonitorPtr mon);
 
-int qemuMonitorRef(qemuMonitorPtr mon);
-int qemuMonitorUnref(qemuMonitorPtr mon);
+void qemuMonitorRef(qemuMonitorPtr mon);
+void qemuMonitorUnref(qemuMonitorPtr mon);
 
 /* These APIs are for use by the internal Text/JSON monitor impl code only */
 int qemuMonitorSend(qemuMonitorPtr mon,
-- 
1.7.3.1


-- 
Thanks,
Hu Tao




More information about the libvir-list mailing list