subroutine kswfn_emit_psi(Wfn, iter, psi_or_hpsi, iproc, nproc)
  use module_bigdft_profiling
  use module_bigdft_mpi
  use module_types
  implicit none
  type(DFT_wavefunction), intent(in) :: Wfn
  integer, intent(in) :: iter, iproc, nproc, psi_or_hpsi

  integer, parameter :: SIGNAL_DONE = -1
  integer, parameter :: SIGNAL_WAIT = -2
  integer :: message, ierr, data(2)
  integer :: status(MPI_STATUS_SIZE)

  call timing(iproc,'wf_signals    ','ON')
  if (iproc == 0) then
     ! Only iproc 0 emit the signal. This call is blocking.
     ! All other procs are blocked by the bcast to wait for
     ! possible transfer to proc 0.
     if (psi_or_hpsi == 0) then
        call wf_emit_psi(Wfn%c_obj, iter)
     else
        call wf_emit_hpsi(Wfn%c_obj, iter)
     end if
     if (nproc > 1) then
        ! After handling the signal, iproc 0 broadcasts to other
        ! proc to continue (jproc == -1).
        message = SIGNAL_DONE
        !call MPI_BCAST(message, 1, MPI_INTEGER, 0, bigdft_mpi%mpi_comm, ierr)
        call fmpi_bcast(message, 1,comm=bigdft_mpi%mpi_comm)
     end if
  else
     message = SIGNAL_WAIT
     do
        if (message == SIGNAL_DONE) then
           exit
        end if
        !call MPI_BCAST(message, 1, MPI_INTEGER, 0, bigdft_mpi%mpi_comm, ierr)
        call fmpi_bcast(message, 1,comm=bigdft_mpi%mpi_comm)

        if (message > 0 .and. iproc == message) then
           ! Will have to send to iproc 0 some of psi.
           call MPI_RECV(data, 2, MPI_INTEGER, 0, 123, bigdft_mpi%mpi_comm, status, ierr)
           if (psi_or_hpsi == 0) then
              call MPI_SEND(Wfn%psi(1 + data(1)), data(2), MPI_DOUBLE_PRECISION, &
                   & 0, 123, bigdft_mpi%mpi_comm, ierr)
           else
              call MPI_SEND(Wfn%hpsi(1 + data(1)), data(2), MPI_DOUBLE_PRECISION, &
                   & 0, 123, bigdft_mpi%mpi_comm, ierr)
           end if
        end if
     end do
  end if
  call timing(iproc,'wf_signals    ','OF')
END SUBROUTINE kswfn_emit_psi

subroutine kswfn_mpi_copy(psic, jproc, psiStart, psiSize)
  use module_bigdft_mpi
  use module_types
  implicit none
  integer, intent(in) :: psiSize, jproc, psiStart
  real(wp), intent(inout) :: psic(psiSize)

  integer :: ierr
  integer :: status(MPI_STATUS_SIZE)

  if (jproc == 0) return

  !call MPI_BCAST(jproc, 1, MPI_INTEGER, 0, bigdft_mpi%mpi_comm, ierr)
  call fmpi_bcast(jproc, 1,comm=bigdft_mpi%mpi_comm)

  call MPI_SEND((/ psiStart, psiSize /), 2, MPI_INTEGER, jproc, 123, bigdft_mpi%mpi_comm, ierr)
  call MPI_RECV(psic, psiSize, MPI_DOUBLE_PRECISION, jproc, 123, bigdft_mpi%mpi_comm, status, ierr)
END SUBROUTINE kswfn_mpi_copy

subroutine kswfn_emit_lzd(Wfn, iproc, nproc)
  use module_bigdft_profiling
  use module_types
  implicit none
  type(DFT_wavefunction), intent(in) :: Wfn
  integer, intent(in) :: iproc, nproc

  call timing(iproc,'wf_signals    ','ON')
  if (iproc == 0) then
     call wf_emit_lzd(Wfn%c_obj)
  end if
  call timing(iproc,'wf_signals    ','OF')
END SUBROUTINE kswfn_emit_lzd
