migration: Add postcopy_thread_create()
Postcopy create threads. A common manner is we init a sem and use it to sync with the thread. Namely, we have fault_thread_sem and listen_thread_sem and they're only used for this. Make it a shared infrastructure so it's easier to create yet another thread. Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Signed-off-by: Peter Xu <peterx@redhat.com> Message-Id: <20220301083925.33483-7-peterx@redhat.com> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
This commit is contained in:
parent
cfc7dc8abf
commit
095c12a4a2
@ -70,7 +70,11 @@ struct MigrationIncomingState {
|
|||||||
/* A hook to allow cleanup at the end of incoming migration */
|
/* A hook to allow cleanup at the end of incoming migration */
|
||||||
void *transport_data;
|
void *transport_data;
|
||||||
void (*transport_cleanup)(void *data);
|
void (*transport_cleanup)(void *data);
|
||||||
|
/*
|
||||||
|
* Used to sync thread creations. Note that we can't create threads in
|
||||||
|
* parallel with this sem.
|
||||||
|
*/
|
||||||
|
QemuSemaphore thread_sync_sem;
|
||||||
/*
|
/*
|
||||||
* Free at the start of the main state load, set as the main thread finishes
|
* Free at the start of the main state load, set as the main thread finishes
|
||||||
* loading state.
|
* loading state.
|
||||||
@ -83,13 +87,11 @@ struct MigrationIncomingState {
|
|||||||
size_t largest_page_size;
|
size_t largest_page_size;
|
||||||
bool have_fault_thread;
|
bool have_fault_thread;
|
||||||
QemuThread fault_thread;
|
QemuThread fault_thread;
|
||||||
QemuSemaphore fault_thread_sem;
|
|
||||||
/* Set this when we want the fault thread to quit */
|
/* Set this when we want the fault thread to quit */
|
||||||
bool fault_thread_quit;
|
bool fault_thread_quit;
|
||||||
|
|
||||||
bool have_listen_thread;
|
bool have_listen_thread;
|
||||||
QemuThread listen_thread;
|
QemuThread listen_thread;
|
||||||
QemuSemaphore listen_thread_sem;
|
|
||||||
|
|
||||||
/* For the kernel to send us notifications */
|
/* For the kernel to send us notifications */
|
||||||
int userfault_fd;
|
int userfault_fd;
|
||||||
|
@ -78,6 +78,20 @@ int postcopy_notify(enum PostcopyNotifyReason reason, Error **errp)
|
|||||||
&pnd);
|
&pnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: this routine is not thread safe, we can't call it concurrently. But it
|
||||||
|
* should be good enough for migration's purposes.
|
||||||
|
*/
|
||||||
|
void postcopy_thread_create(MigrationIncomingState *mis,
|
||||||
|
QemuThread *thread, const char *name,
|
||||||
|
void *(*fn)(void *), int joinable)
|
||||||
|
{
|
||||||
|
qemu_sem_init(&mis->thread_sync_sem, 0);
|
||||||
|
qemu_thread_create(thread, name, fn, mis, joinable);
|
||||||
|
qemu_sem_wait(&mis->thread_sync_sem);
|
||||||
|
qemu_sem_destroy(&mis->thread_sync_sem);
|
||||||
|
}
|
||||||
|
|
||||||
/* Postcopy needs to detect accesses to pages that haven't yet been copied
|
/* Postcopy needs to detect accesses to pages that haven't yet been copied
|
||||||
* across, and efficiently map new pages in, the techniques for doing this
|
* across, and efficiently map new pages in, the techniques for doing this
|
||||||
* are target OS specific.
|
* are target OS specific.
|
||||||
@ -902,7 +916,7 @@ static void *postcopy_ram_fault_thread(void *opaque)
|
|||||||
trace_postcopy_ram_fault_thread_entry();
|
trace_postcopy_ram_fault_thread_entry();
|
||||||
rcu_register_thread();
|
rcu_register_thread();
|
||||||
mis->last_rb = NULL; /* last RAMBlock we sent part of */
|
mis->last_rb = NULL; /* last RAMBlock we sent part of */
|
||||||
qemu_sem_post(&mis->fault_thread_sem);
|
qemu_sem_post(&mis->thread_sync_sem);
|
||||||
|
|
||||||
struct pollfd *pfd;
|
struct pollfd *pfd;
|
||||||
size_t pfd_len = 2 + mis->postcopy_remote_fds->len;
|
size_t pfd_len = 2 + mis->postcopy_remote_fds->len;
|
||||||
@ -1173,11 +1187,8 @@ int postcopy_ram_incoming_setup(MigrationIncomingState *mis)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_sem_init(&mis->fault_thread_sem, 0);
|
postcopy_thread_create(mis, &mis->fault_thread, "postcopy/fault",
|
||||||
qemu_thread_create(&mis->fault_thread, "postcopy/fault",
|
postcopy_ram_fault_thread, QEMU_THREAD_JOINABLE);
|
||||||
postcopy_ram_fault_thread, mis, QEMU_THREAD_JOINABLE);
|
|
||||||
qemu_sem_wait(&mis->fault_thread_sem);
|
|
||||||
qemu_sem_destroy(&mis->fault_thread_sem);
|
|
||||||
mis->have_fault_thread = true;
|
mis->have_fault_thread = true;
|
||||||
|
|
||||||
/* Mark so that we get notified of accesses to unwritten areas */
|
/* Mark so that we get notified of accesses to unwritten areas */
|
||||||
|
@ -135,6 +135,10 @@ void postcopy_remove_notifier(NotifierWithReturn *n);
|
|||||||
/* Call the notifier list set by postcopy_add_start_notifier */
|
/* Call the notifier list set by postcopy_add_start_notifier */
|
||||||
int postcopy_notify(enum PostcopyNotifyReason reason, Error **errp);
|
int postcopy_notify(enum PostcopyNotifyReason reason, Error **errp);
|
||||||
|
|
||||||
|
void postcopy_thread_create(MigrationIncomingState *mis,
|
||||||
|
QemuThread *thread, const char *name,
|
||||||
|
void *(*fn)(void *), int joinable);
|
||||||
|
|
||||||
struct PostCopyFD;
|
struct PostCopyFD;
|
||||||
|
|
||||||
/* ufd is a pointer to the struct uffd_msg *TODO: more Portable! */
|
/* ufd is a pointer to the struct uffd_msg *TODO: more Portable! */
|
||||||
|
@ -1863,7 +1863,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
|
|||||||
|
|
||||||
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
|
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
|
||||||
MIGRATION_STATUS_POSTCOPY_ACTIVE);
|
MIGRATION_STATUS_POSTCOPY_ACTIVE);
|
||||||
qemu_sem_post(&mis->listen_thread_sem);
|
qemu_sem_post(&mis->thread_sync_sem);
|
||||||
trace_postcopy_ram_listen_thread_start();
|
trace_postcopy_ram_listen_thread_start();
|
||||||
|
|
||||||
rcu_register_thread();
|
rcu_register_thread();
|
||||||
@ -1988,14 +1988,8 @@ static int loadvm_postcopy_handle_listen(MigrationIncomingState *mis)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mis->have_listen_thread = true;
|
mis->have_listen_thread = true;
|
||||||
/* Start up the listening thread and wait for it to signal ready */
|
postcopy_thread_create(mis, &mis->listen_thread, "postcopy/listen",
|
||||||
qemu_sem_init(&mis->listen_thread_sem, 0);
|
postcopy_ram_listen_thread, QEMU_THREAD_DETACHED);
|
||||||
qemu_thread_create(&mis->listen_thread, "postcopy/listen",
|
|
||||||
postcopy_ram_listen_thread, NULL,
|
|
||||||
QEMU_THREAD_DETACHED);
|
|
||||||
qemu_sem_wait(&mis->listen_thread_sem);
|
|
||||||
qemu_sem_destroy(&mis->listen_thread_sem);
|
|
||||||
|
|
||||||
trace_loadvm_postcopy_handle_listen("return");
|
trace_loadvm_postcopy_handle_listen("return");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user