|
|
|
@@ -362,8 +362,6 @@ struct {
|
|
|
|
|
MultiFDPages_t *pages;
|
|
|
|
|
/* global number of generated multifd packets */
|
|
|
|
|
uint64_t packet_num;
|
|
|
|
|
/* send channels ready */
|
|
|
|
|
QemuSemaphore channels_ready;
|
|
|
|
|
/*
|
|
|
|
|
* Have we already run terminate threads. There is a race when it
|
|
|
|
|
* happens that we got one error while we are exiting.
|
|
|
|
@@ -403,7 +401,6 @@ static int multifd_send_pages(QEMUFile *f)
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qemu_sem_wait(&multifd_send_state->channels_ready);
|
|
|
|
|
/*
|
|
|
|
|
* next_channel can remain from a previous migration that was
|
|
|
|
|
* using more channels, so ensure it doesn't overflow if the
|
|
|
|
@@ -469,23 +466,11 @@ int multifd_queue_page(QEMUFile *f, RAMBlock *block, ram_addr_t offset)
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void multifd_send_terminate_threads(Error *err)
|
|
|
|
|
static void multifd_send_terminate_threads(void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
trace_multifd_send_terminate_threads(err != NULL);
|
|
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
|
MigrationState *s = migrate_get_current();
|
|
|
|
|
migrate_set_error(s, err);
|
|
|
|
|
if (s->state == MIGRATION_STATUS_SETUP ||
|
|
|
|
|
s->state == MIGRATION_STATUS_PRE_SWITCHOVER ||
|
|
|
|
|
s->state == MIGRATION_STATUS_DEVICE ||
|
|
|
|
|
s->state == MIGRATION_STATUS_ACTIVE) {
|
|
|
|
|
migrate_set_state(&s->state, s->state,
|
|
|
|
|
MIGRATION_STATUS_FAILED);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
trace_multifd_send_terminate_threads();
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We don't want to exit each threads twice. Depending on where
|
|
|
|
@@ -510,6 +495,11 @@ static void multifd_send_terminate_threads(Error *err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int multifd_send_channel_destroy(QIOChannel *send)
|
|
|
|
|
{
|
|
|
|
|
return socket_send_channel_destroy(send);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void multifd_save_cleanup(void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
@@ -517,7 +507,7 @@ void multifd_save_cleanup(void)
|
|
|
|
|
if (!migrate_multifd()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
multifd_send_terminate_threads(NULL);
|
|
|
|
|
multifd_send_terminate_threads();
|
|
|
|
|
for (i = 0; i < migrate_multifd_channels(); i++) {
|
|
|
|
|
MultiFDSendParams *p = &multifd_send_state->params[i];
|
|
|
|
|
|
|
|
|
@@ -532,11 +522,11 @@ void multifd_save_cleanup(void)
|
|
|
|
|
if (p->registered_yank) {
|
|
|
|
|
migration_ioc_unregister_yank(p->c);
|
|
|
|
|
}
|
|
|
|
|
socket_send_channel_destroy(p->c);
|
|
|
|
|
multifd_send_channel_destroy(p->c);
|
|
|
|
|
p->c = NULL;
|
|
|
|
|
qemu_mutex_destroy(&p->mutex);
|
|
|
|
|
qemu_sem_destroy(&p->sem);
|
|
|
|
|
qemu_sem_destroy(&p->sem_sync);
|
|
|
|
|
qemu_sem_destroy(&p->sem_done);
|
|
|
|
|
g_free(p->name);
|
|
|
|
|
p->name = NULL;
|
|
|
|
|
multifd_pages_clear(p->pages);
|
|
|
|
@@ -554,7 +544,6 @@ void multifd_save_cleanup(void)
|
|
|
|
|
error_free(local_err);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
qemu_sem_destroy(&multifd_send_state->channels_ready);
|
|
|
|
|
g_free(multifd_send_state->params);
|
|
|
|
|
multifd_send_state->params = NULL;
|
|
|
|
|
multifd_pages_clear(multifd_send_state->pages);
|
|
|
|
@@ -580,19 +569,15 @@ static int multifd_zero_copy_flush(QIOChannel *c)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int multifd_send_sync_main(QEMUFile *f)
|
|
|
|
|
static int multifd_send_wait(void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
bool flush_zero_copy;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!migrate_multifd()) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (multifd_send_state->pages->num) {
|
|
|
|
|
if (multifd_send_pages(f) < 0) {
|
|
|
|
|
error_report("%s: multifd_send_pages fail", __func__);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
/* wait for all channels to be idle */
|
|
|
|
|
for (i = 0; i < migrate_multifd_channels(); i++) {
|
|
|
|
|
trace_multifd_send_wait(migrate_multifd_channels() - i);
|
|
|
|
|
qemu_sem_wait(&multifd_send_state->channels_ready);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@@ -605,9 +590,46 @@ int multifd_send_sync_main(QEMUFile *f)
|
|
|
|
|
* to be less frequent, e.g. only after we finished one whole scanning of
|
|
|
|
|
* all the dirty bitmaps.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
flush_zero_copy = migrate_zero_copy_send();
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < migrate_multifd_channels(); i++) {
|
|
|
|
|
MultiFDSendParams *p = &multifd_send_state->params[i];
|
|
|
|
|
|
|
|
|
|
qemu_mutex_lock(&p->mutex);
|
|
|
|
|
assert(!p->pending_job);
|
|
|
|
|
qemu_mutex_unlock(&p->mutex);
|
|
|
|
|
|
|
|
|
|
qemu_sem_post(&p->sem);
|
|
|
|
|
qemu_sem_wait(&p->sem_done);
|
|
|
|
|
|
|
|
|
|
if (flush_zero_copy && p->c && (multifd_zero_copy_flush(p->c) < 0)) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* All channels went idle and have no more jobs. Unless we send
|
|
|
|
|
* them more work, we're good to allow any cleanup code to run at
|
|
|
|
|
* this point.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int multifd_send_sync_main(QEMUFile *f)
|
|
|
|
|
{
|
|
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
|
|
if (!migrate_multifd()) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (multifd_send_state->pages->num) {
|
|
|
|
|
if (multifd_send_pages(f) < 0) {
|
|
|
|
|
error_report("%s: multifd_send_pages fail", __func__);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < migrate_multifd_channels(); i++) {
|
|
|
|
|
MultiFDSendParams *p = &multifd_send_state->params[i];
|
|
|
|
|
|
|
|
|
@@ -627,20 +649,30 @@ int multifd_send_sync_main(QEMUFile *f)
|
|
|
|
|
qemu_mutex_unlock(&p->mutex);
|
|
|
|
|
qemu_sem_post(&p->sem);
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < migrate_multifd_channels(); i++) {
|
|
|
|
|
MultiFDSendParams *p = &multifd_send_state->params[i];
|
|
|
|
|
|
|
|
|
|
qemu_sem_wait(&multifd_send_state->channels_ready);
|
|
|
|
|
trace_multifd_send_sync_main_wait(p->id);
|
|
|
|
|
qemu_sem_wait(&p->sem_sync);
|
|
|
|
|
|
|
|
|
|
if (flush_zero_copy && p->c && (multifd_zero_copy_flush(p->c) < 0)) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ret = multifd_send_wait();
|
|
|
|
|
trace_multifd_send_sync_main(multifd_send_state->packet_num);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Mark that the thread has quit (including if it never even started)
|
|
|
|
|
* and release any waiters that might be stuck.
|
|
|
|
|
*/
|
|
|
|
|
static void multifd_send_thread_release(MultiFDSendParams *p)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Not all instances where this function is called happen with a
|
|
|
|
|
* live thread, but let's be conservative and always take the
|
|
|
|
|
* lock.
|
|
|
|
|
*/
|
|
|
|
|
qemu_mutex_lock(&p->mutex);
|
|
|
|
|
p->quit = true;
|
|
|
|
|
qemu_mutex_unlock(&p->mutex);
|
|
|
|
|
|
|
|
|
|
qemu_sem_post(&multifd_send_state->channels_ready);
|
|
|
|
|
qemu_sem_post(&p->sem_done);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *multifd_send_thread(void *opaque)
|
|
|
|
@@ -664,7 +696,6 @@ static void *multifd_send_thread(void *opaque)
|
|
|
|
|
p->num_packets = 1;
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
qemu_sem_post(&multifd_send_state->channels_ready);
|
|
|
|
|
qemu_sem_wait(&p->sem);
|
|
|
|
|
|
|
|
|
|
if (qatomic_read(&multifd_send_state->exiting)) {
|
|
|
|
@@ -734,32 +765,31 @@ static void *multifd_send_thread(void *opaque)
|
|
|
|
|
p->pending_job--;
|
|
|
|
|
qemu_mutex_unlock(&p->mutex);
|
|
|
|
|
|
|
|
|
|
if (flags & MULTIFD_FLAG_SYNC) {
|
|
|
|
|
qemu_sem_post(&p->sem_sync);
|
|
|
|
|
}
|
|
|
|
|
} else if (p->quit) {
|
|
|
|
|
qemu_mutex_unlock(&p->mutex);
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
qemu_sem_post(&p->sem_done);
|
|
|
|
|
qemu_mutex_unlock(&p->mutex);
|
|
|
|
|
/* sometimes there are spurious wakeups */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
if (local_err) {
|
|
|
|
|
if (ret) {
|
|
|
|
|
MigrationState *s = migrate_get_current();
|
|
|
|
|
|
|
|
|
|
trace_multifd_send_error(p->id);
|
|
|
|
|
multifd_send_terminate_threads(local_err);
|
|
|
|
|
error_free(local_err);
|
|
|
|
|
assert(local_err);
|
|
|
|
|
migrate_set_error(s, local_err);
|
|
|
|
|
|
|
|
|
|
if (s->state == MIGRATION_STATUS_SETUP ||
|
|
|
|
|
s->state == MIGRATION_STATUS_PRE_SWITCHOVER ||
|
|
|
|
|
s->state == MIGRATION_STATUS_DEVICE ||
|
|
|
|
|
s->state == MIGRATION_STATUS_ACTIVE) {
|
|
|
|
|
migrate_set_state(&s->state, s->state,
|
|
|
|
|
MIGRATION_STATUS_FAILED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Error happen, I will exit, but I can't just leave, tell
|
|
|
|
|
* who pay attention to me.
|
|
|
|
|
*/
|
|
|
|
|
if (ret != 0) {
|
|
|
|
|
qemu_sem_post(&p->sem_sync);
|
|
|
|
|
qemu_sem_post(&multifd_send_state->channels_ready);
|
|
|
|
|
multifd_send_terminate_threads();
|
|
|
|
|
multifd_send_thread_release(p);
|
|
|
|
|
error_free(local_err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qemu_mutex_lock(&p->mutex);
|
|
|
|
@@ -775,7 +805,7 @@ out:
|
|
|
|
|
|
|
|
|
|
static bool multifd_channel_connect(MultiFDSendParams *p,
|
|
|
|
|
QIOChannel *ioc,
|
|
|
|
|
Error *error);
|
|
|
|
|
Error **errp);
|
|
|
|
|
|
|
|
|
|
static void multifd_tls_outgoing_handshake(QIOTask *task,
|
|
|
|
|
gpointer opaque)
|
|
|
|
@@ -784,21 +814,15 @@ static void multifd_tls_outgoing_handshake(QIOTask *task,
|
|
|
|
|
QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task));
|
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
|
|
if (qio_task_propagate_error(task, &err)) {
|
|
|
|
|
trace_multifd_tls_outgoing_handshake_error(ioc, error_get_pretty(err));
|
|
|
|
|
} else {
|
|
|
|
|
if (!qio_task_propagate_error(task, &err)) {
|
|
|
|
|
trace_multifd_tls_outgoing_handshake_complete(ioc);
|
|
|
|
|
if (multifd_channel_connect(p, ioc, &err)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!multifd_channel_connect(p, ioc, err)) {
|
|
|
|
|
/*
|
|
|
|
|
* Error happen, mark multifd_send_thread status as 'quit' although it
|
|
|
|
|
* is not created, and then tell who pay attention to me.
|
|
|
|
|
*/
|
|
|
|
|
p->quit = true;
|
|
|
|
|
qemu_sem_post(&multifd_send_state->channels_ready);
|
|
|
|
|
qemu_sem_post(&p->sem_sync);
|
|
|
|
|
}
|
|
|
|
|
trace_multifd_tls_outgoing_handshake_error(ioc, error_get_pretty(err));
|
|
|
|
|
multifd_send_thread_release(p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *multifd_tls_handshake_thread(void *opaque)
|
|
|
|
@@ -814,7 +838,7 @@ static void *multifd_tls_handshake_thread(void *opaque)
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void multifd_tls_channel_connect(MultiFDSendParams *p,
|
|
|
|
|
static bool multifd_tls_channel_connect(MultiFDSendParams *p,
|
|
|
|
|
QIOChannel *ioc,
|
|
|
|
|
Error **errp)
|
|
|
|
|
{
|
|
|
|
@@ -824,7 +848,7 @@ static void multifd_tls_channel_connect(MultiFDSendParams *p,
|
|
|
|
|
|
|
|
|
|
tioc = migration_tls_client_create(ioc, hostname, errp);
|
|
|
|
|
if (!tioc) {
|
|
|
|
|
return;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object_unref(OBJECT(ioc));
|
|
|
|
@@ -834,31 +858,25 @@ static void multifd_tls_channel_connect(MultiFDSendParams *p,
|
|
|
|
|
qemu_thread_create(&p->thread, "multifd-tls-handshake-worker",
|
|
|
|
|
multifd_tls_handshake_thread, p,
|
|
|
|
|
QEMU_THREAD_JOINABLE);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool multifd_channel_connect(MultiFDSendParams *p,
|
|
|
|
|
QIOChannel *ioc,
|
|
|
|
|
Error *error)
|
|
|
|
|
Error **errp)
|
|
|
|
|
{
|
|
|
|
|
trace_multifd_set_outgoing_channel(
|
|
|
|
|
ioc, object_get_typename(OBJECT(ioc)),
|
|
|
|
|
migrate_get_current()->hostname, error);
|
|
|
|
|
migrate_get_current()->hostname);
|
|
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (migrate_channel_requires_tls_upgrade(ioc)) {
|
|
|
|
|
multifd_tls_channel_connect(p, ioc, &error);
|
|
|
|
|
if (!error) {
|
|
|
|
|
/*
|
|
|
|
|
* tls_channel_connect will call back to this
|
|
|
|
|
* function after the TLS handshake,
|
|
|
|
|
* so we mustn't call multifd_send_thread until then
|
|
|
|
|
*/
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return multifd_tls_channel_connect(p, ioc, errp);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
migration_ioc_register_yank(ioc);
|
|
|
|
|
p->registered_yank = true;
|
|
|
|
@@ -873,15 +891,7 @@ static void multifd_new_send_channel_cleanup(MultiFDSendParams *p,
|
|
|
|
|
QIOChannel *ioc, Error *err)
|
|
|
|
|
{
|
|
|
|
|
migrate_set_error(migrate_get_current(), err);
|
|
|
|
|
/* Error happen, we need to tell who pay attention to me */
|
|
|
|
|
qemu_sem_post(&multifd_send_state->channels_ready);
|
|
|
|
|
qemu_sem_post(&p->sem_sync);
|
|
|
|
|
/*
|
|
|
|
|
* Although multifd_send_thread is not created, but main migration
|
|
|
|
|
* thread need to judge whether it is running, so we need to mark
|
|
|
|
|
* its status.
|
|
|
|
|
*/
|
|
|
|
|
p->quit = true;
|
|
|
|
|
multifd_send_thread_release(p);
|
|
|
|
|
object_unref(OBJECT(ioc));
|
|
|
|
|
error_free(err);
|
|
|
|
|
}
|
|
|
|
@@ -889,20 +899,26 @@ static void multifd_new_send_channel_cleanup(MultiFDSendParams *p,
|
|
|
|
|
static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque)
|
|
|
|
|
{
|
|
|
|
|
MultiFDSendParams *p = opaque;
|
|
|
|
|
QIOChannel *sioc = QIO_CHANNEL(qio_task_get_source(task));
|
|
|
|
|
QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task));
|
|
|
|
|
Error *local_err = NULL;
|
|
|
|
|
|
|
|
|
|
trace_multifd_new_send_channel_async(p->id);
|
|
|
|
|
if (!qio_task_propagate_error(task, &local_err)) {
|
|
|
|
|
p->c = sioc;
|
|
|
|
|
p->c = ioc;
|
|
|
|
|
qio_channel_set_delay(p->c, false);
|
|
|
|
|
p->running = true;
|
|
|
|
|
if (multifd_channel_connect(p, sioc, local_err)) {
|
|
|
|
|
if (multifd_channel_connect(p, ioc, &local_err)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
multifd_new_send_channel_cleanup(p, sioc, local_err);
|
|
|
|
|
trace_multifd_new_send_channel_async_error(p->id, local_err);
|
|
|
|
|
multifd_new_send_channel_cleanup(p, ioc, local_err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void multifd_new_send_channel_create(gpointer opaque)
|
|
|
|
|
{
|
|
|
|
|
socket_send_channel_create(multifd_new_send_channel_async, opaque);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int multifd_save_setup(Error **errp)
|
|
|
|
@@ -919,7 +935,6 @@ int multifd_save_setup(Error **errp)
|
|
|
|
|
multifd_send_state = g_malloc0(sizeof(*multifd_send_state));
|
|
|
|
|
multifd_send_state->params = g_new0(MultiFDSendParams, thread_count);
|
|
|
|
|
multifd_send_state->pages = multifd_pages_init(page_count);
|
|
|
|
|
qemu_sem_init(&multifd_send_state->channels_ready, 0);
|
|
|
|
|
qatomic_set(&multifd_send_state->exiting, 0);
|
|
|
|
|
multifd_send_state->ops = multifd_ops[migrate_multifd_compression()];
|
|
|
|
|
|
|
|
|
@@ -928,7 +943,7 @@ int multifd_save_setup(Error **errp)
|
|
|
|
|
|
|
|
|
|
qemu_mutex_init(&p->mutex);
|
|
|
|
|
qemu_sem_init(&p->sem, 0);
|
|
|
|
|
qemu_sem_init(&p->sem_sync, 0);
|
|
|
|
|
qemu_sem_init(&p->sem_done, 0);
|
|
|
|
|
p->quit = false;
|
|
|
|
|
p->pending_job = 0;
|
|
|
|
|
p->id = i;
|
|
|
|
@@ -951,7 +966,7 @@ int multifd_save_setup(Error **errp)
|
|
|
|
|
p->write_flags = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
socket_send_channel_create(multifd_new_send_channel_async, p);
|
|
|
|
|
multifd_new_send_channel_create(p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < thread_count; i++) {
|
|
|
|
@@ -1037,7 +1052,7 @@ void multifd_load_cleanup(void)
|
|
|
|
|
* multifd_recv_thread may hung at MULTIFD_FLAG_SYNC handle code,
|
|
|
|
|
* however try to wakeup it without harm in cleanup phase.
|
|
|
|
|
*/
|
|
|
|
|
qemu_sem_post(&p->sem_sync);
|
|
|
|
|
qemu_sem_post(&p->sem_done);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qemu_thread_join(&p->thread);
|
|
|
|
@@ -1049,7 +1064,7 @@ void multifd_load_cleanup(void)
|
|
|
|
|
object_unref(OBJECT(p->c));
|
|
|
|
|
p->c = NULL;
|
|
|
|
|
qemu_mutex_destroy(&p->mutex);
|
|
|
|
|
qemu_sem_destroy(&p->sem_sync);
|
|
|
|
|
qemu_sem_destroy(&p->sem_done);
|
|
|
|
|
g_free(p->name);
|
|
|
|
|
p->name = NULL;
|
|
|
|
|
p->packet_len = 0;
|
|
|
|
@@ -1090,7 +1105,7 @@ void multifd_recv_sync_main(void)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
trace_multifd_recv_sync_main_signal(p->id);
|
|
|
|
|
qemu_sem_post(&p->sem_sync);
|
|
|
|
|
qemu_sem_post(&p->sem_done);
|
|
|
|
|
}
|
|
|
|
|
trace_multifd_recv_sync_main(multifd_recv_state->packet_num);
|
|
|
|
|
}
|
|
|
|
@@ -1142,7 +1157,7 @@ static void *multifd_recv_thread(void *opaque)
|
|
|
|
|
|
|
|
|
|
if (flags & MULTIFD_FLAG_SYNC) {
|
|
|
|
|
qemu_sem_post(&multifd_recv_state->sem_sync);
|
|
|
|
|
qemu_sem_wait(&p->sem_sync);
|
|
|
|
|
qemu_sem_wait(&p->sem_done);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1185,7 +1200,7 @@ int multifd_load_setup(Error **errp)
|
|
|
|
|
MultiFDRecvParams *p = &multifd_recv_state->params[i];
|
|
|
|
|
|
|
|
|
|
qemu_mutex_init(&p->mutex);
|
|
|
|
|
qemu_sem_init(&p->sem_sync, 0);
|
|
|
|
|
qemu_sem_init(&p->sem_done, 0);
|
|
|
|
|
p->quit = false;
|
|
|
|
|
p->id = i;
|
|
|
|
|
p->packet_len = sizeof(MultiFDPacket_t)
|
|
|
|
|