Bin Guo <[email protected]> writes:

> multifd_recv_cleanup() iterates over all receive channels twice:
> one loop to join threads and another to clean up each channel.

ok

> Unlike the send side where all threads must be signalled before any is
> joined (to avoid deadlock),

Not super relevant what the send side does. It's just a similar piece of
code, that's all.

> on the receive side the threads are already
> terminated by multifd_recv_terminate_threads().  Each join simply
> waits for an already-terminated thread, so the join and cleanup for
> channel i are independent of channel j, and the two loops can safely
> be merged into one.
>

We do really need to join all threads before proceeding. There's no
guarantee on the the order in which they'll terminate.

> This cuts the iteration count in half and improves locality: the
> thread's resources are freed immediately after its join.
>
> Signed-off-by: Bin Guo <[email protected]>
> ---
>  migration/multifd.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/migration/multifd.c b/migration/multifd.c
> index b3eef875cc..67ee9bdf5e 100644
> --- a/migration/multifd.c
> +++ b/migration/multifd.c
> @@ -1153,15 +1153,14 @@ void multifd_recv_cleanup(void)
>          return;
>      }
>      multifd_recv_terminate_threads(NULL);
> +
>      for (i = 0; i < migrate_multifd_channels(); i++) {
>          MultiFDRecvParams *p = &multifd_recv_state->params[i];
>  
>          if (p->thread_created) {
>              qemu_thread_join(&p->thread);
>          }
> -    }
> -    for (i = 0; i < migrate_multifd_channels(); i++) {
> -        multifd_recv_cleanup_channel(&multifd_recv_state->params[i]);
> +        multifd_recv_cleanup_channel(p);
>      }
>      multifd_recv_cleanup_state();
>  }

Reply via email to