@@ -315,6 +315,12 @@ struct MigrationState {
* be cleared in the rp_thread!
*/
bool rp_thread_created;
+ /*
+ * Used to synchronize between migration main thread and return
+ * path thread. The migration thread can wait() on this sem, while
+ * other threads (e.g., return path thread) can kick it using a
+ * post().
+ */
QemuSemaphore rp_sem;
/*
* We post to this when we got one PONG from dest. So far it's an
@@ -526,4 +532,13 @@ void migration_populate_vfio_info(MigrationInfo *info);
void migration_reset_vfio_bytes_transferred(void);
void postcopy_temp_page_reset(PostcopyTmpPage *tmp_page);
+/* Migration thread waiting for return path thread. */
+void migration_rp_wait(MigrationState *s);
+/*
+ * Kick the migration thread waiting for return path messages. NOTE: the
+ * name can be slightly confusing (when read as "kick the rp thread"), just
+ * to remember the target is always the migration thread.
+ */
+void migration_rp_kick(MigrationState *s);
+
#endif
@@ -1749,6 +1749,16 @@ void qmp_migrate_continue(MigrationStatus state, Error **errp)
qemu_sem_post(&s->pause_sem);
}
+void migration_rp_wait(MigrationState *s)
+{
+ qemu_sem_wait(&s->rp_state.rp_sem);
+}
+
+void migration_rp_kick(MigrationState *s)
+{
+ qemu_sem_post(&s->rp_state.rp_sem);
+}
+
static struct rp_cmd_args {
ssize_t len; /* -1 = variable */
const char *name;
@@ -1820,7 +1830,7 @@ static int migrate_handle_rp_resume_ack(MigrationState *s,
MIGRATION_STATUS_POSTCOPY_ACTIVE);
/* Notify send thread that time to continue send pages */
- qemu_sem_post(&s->rp_state.rp_sem);
+ migration_rp_kick(s);
return 0;
}
@@ -2447,7 +2457,7 @@ static int postcopy_resume_handshake(MigrationState *s)
qemu_savevm_send_postcopy_resume(s->to_dst_file);
while (s->state == MIGRATION_STATUS_POSTCOPY_RECOVER) {
- qemu_sem_wait(&s->rp_state.rp_sem);
+ migration_rp_wait(s);
}
if (s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE) {
@@ -4143,7 +4143,7 @@ static int ram_dirty_bitmap_sync_all(MigrationState *s, RAMState *rs)
/* Wait until all the ramblocks' dirty bitmap synced */
while (qatomic_read(&rs->postcopy_bmap_sync_requested)) {
- qemu_sem_wait(&s->rp_state.rp_sem);
+ migration_rp_wait(s);
}
trace_ram_dirty_bitmap_sync_complete();
@@ -4151,11 +4151,6 @@ static int ram_dirty_bitmap_sync_all(MigrationState *s, RAMState *rs)
return 0;
}
-static void ram_dirty_bitmap_reload_notify(MigrationState *s)
-{
- qemu_sem_post(&s->rp_state.rp_sem);
-}
-
/*
* Read the received bitmap, revert it as the initial dirty bitmap.
* This is only used when the postcopy migration is paused but wants
@@ -4238,10 +4233,13 @@ int ram_dirty_bitmap_reload(MigrationState *s, RAMBlock *block, Error **errp)
qatomic_dec(&rs->postcopy_bmap_sync_requested);
/*
- * We succeeded to sync bitmap for current ramblock. If this is
- * the last one to sync, we need to notify the main send thread.
+ * We succeeded to sync bitmap for current ramblock. Always kick the
+ * migration thread to check whether all requested bitmaps are
+ * reloaded. NOTE: it's racy to only kick when requested==0, because
+ * we don't know whether the migration thread may still be increasing
+ * it.
*/
- ram_dirty_bitmap_reload_notify(s);
+ migration_rp_kick(s);
ret = 0;
out: