[libvirt] [PATCH 10/10] qemu: Use thread queues for asyncAbort

Jiri Denemark jdenemar at redhat.com
Thu May 21 22:42:43 UTC 2015


To avoid polling for asyncAbort flag changes.

Any thread which enters an async job is automatically registered to be
woken up whenever asyncAbort is set (as long as the thread is waiting
for its thread condition).

Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
---
 src/qemu/qemu_domain.c    | 37 +++++++++++++++++++++----------------
 src/qemu/qemu_domain.h    |  4 +++-
 src/qemu/qemu_migration.c | 11 ++++-------
 3 files changed, 28 insertions(+), 24 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 35cfe20..68811aa 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -130,16 +130,25 @@ void qemuDomainEventQueue(virQEMUDriverPtr driver,
 }
 
 
+static void
+qemuDomainObjFreeJob(qemuDomainObjPrivatePtr priv)
+{
+    VIR_FREE(priv->job.current);
+    VIR_FREE(priv->job.completed);
+    virCondDestroy(&priv->job.cond);
+    virCondDestroy(&priv->job.asyncCond);
+    virThreadQueueFree(priv->job.abortQueue);
+}
+
 static int
 qemuDomainObjInitJob(qemuDomainObjPrivatePtr priv)
 {
     memset(&priv->job, 0, sizeof(priv->job));
 
-    if (virCondInit(&priv->job.cond) < 0)
-        return -1;
-
-    if (virCondInit(&priv->job.asyncCond) < 0) {
-        virCondDestroy(&priv->job.cond);
+    if (virCondInit(&priv->job.cond) < 0 ||
+        virCondInit(&priv->job.asyncCond) < 0 ||
+        !(priv->job.abortQueue = virThreadQueueNew())) {
+        qemuDomainObjFreeJob(priv);
         return -1;
     }
 
@@ -169,7 +178,8 @@ qemuDomainObjResetAsyncJob(qemuDomainObjPrivatePtr priv)
     job->phase = 0;
     job->mask = QEMU_JOB_DEFAULT_MASK;
     job->dump_memory_only = false;
-    job->asyncAbort = false;
+    virThreadQueueUnregister(job->abortQueue);
+    job->abortJob = false;
     VIR_FREE(job->current);
 }
 
@@ -190,15 +200,6 @@ qemuDomainObjRestoreJob(virDomainObjPtr obj,
     qemuDomainObjResetAsyncJob(priv);
 }
 
-static void
-qemuDomainObjFreeJob(qemuDomainObjPrivatePtr priv)
-{
-    VIR_FREE(priv->job.current);
-    VIR_FREE(priv->job.completed);
-    virCondDestroy(&priv->job.cond);
-    virCondDestroy(&priv->job.asyncCond);
-}
-
 static bool
 qemuDomainTrackJob(qemuDomainJob job)
 {
@@ -1344,6 +1345,7 @@ qemuDomainObjSetJobPhase(virQEMUDriverPtr driver,
 
     priv->job.phase = phase;
     priv->job.asyncOwner = me;
+    virThreadQueueRegister(priv->job.abortQueue);
     qemuDomainObjSaveJob(driver, obj);
 }
 
@@ -1383,6 +1385,7 @@ qemuDomainObjReleaseAsyncJob(virDomainObjPtr obj)
                  qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
                  priv->job.asyncOwner);
     }
+    virThreadQueueUnregister(priv->job.abortQueue);
     priv->job.asyncOwner = 0;
 }
 
@@ -1482,6 +1485,7 @@ qemuDomainObjBeginJobInternal(virQEMUDriverPtr driver,
         priv->job.asyncOwnerAPI = virThreadJobGet();
         priv->job.asyncStarted = now;
         priv->job.current->started = now;
+        virThreadQueueRegister(priv->job.abortQueue);
     }
 
     if (qemuDomainTrackJob(job))
@@ -1652,7 +1656,8 @@ qemuDomainObjAbortAsyncJob(virDomainObjPtr obj)
               qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
               obj, obj->def->name);
 
-    priv->job.asyncAbort = true;
+    priv->job.abortJob = true;
+    virThreadQueueBroadcast(priv->job.abortQueue);
 }
 
 /*
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 2117a3d..12c784b 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -136,7 +136,9 @@ struct qemuDomainJobObj {
     bool dump_memory_only;              /* use dump-guest-memory to do dump */
     qemuDomainJobInfoPtr current;       /* async job progress data */
     qemuDomainJobInfoPtr completed;     /* statistics data of a recently completed job */
-    bool asyncAbort;                    /* abort of async job requested */
+
+    virThreadQueuePtr abortQueue;	/* threads listening to abortJob */
+    bool abortJob;                      /* abort of the job requested */
 };
 
 typedef void (*qemuDomainCleanupCallback)(virQEMUDriverPtr driver,
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 1db6979..43ecea5 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2043,12 +2043,10 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
     }
 
     while ((rv = qemuMigrationDriveMirrorReady(driver, vm)) != 1) {
-        unsigned long long now;
-
         if (rv < 0)
             goto cleanup;
 
-        if (priv->job.asyncAbort) {
+        if (priv->job.abortJob) {
             priv->job.current->type = VIR_DOMAIN_JOB_CANCELLED;
             virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"),
                            qemuDomainAsyncJobTypeToString(priv->job.asyncJob),
@@ -2056,8 +2054,7 @@ qemuMigrationDriveMirror(virQEMUDriverPtr driver,
             goto cleanup;
         }
 
-        if (virTimeMillisNow(&now) < 0 ||
-            virThreadCondWaitUntil(&vm->parent.lock, now + 500) < 0)
+        if (virThreadCondWait(&vm->parent.lock) < 0)
             goto cleanup;
     }
 
@@ -4053,10 +4050,10 @@ qemuMigrationRun(virQEMUDriverPtr driver,
                                        QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
         goto cleanup;
 
-    if (priv->job.asyncAbort) {
+    if (priv->job.abortJob) {
         /* explicitly do this *after* we entered the monitor,
          * as this is a critical section so we are guaranteed
-         * priv->job.asyncAbort will not change */
+         * priv->job.abortJob will not change */
         ignore_value(qemuDomainObjExitMonitor(driver, vm));
         priv->job.current->type = VIR_DOMAIN_JOB_CANCELLED;
         virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"),
-- 
2.4.1




More information about the libvir-list mailing list