int MPID_Win_free(MPIR_Win ** win_ptr) { int mpi_errno = MPI_SUCCESS; int in_use; MPIR_Comm *comm_ptr; MPIR_Errflag_t errflag = MPIR_ERR_NONE; MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_WIN_FREE); MPIR_FUNC_VERBOSE_RMA_ENTER(MPID_STATE_MPID_WIN_FREE); MPIR_ERR_CHKANDJUMP(((*win_ptr)->states.access_state != MPIDI_RMA_NONE && (*win_ptr)->states.access_state != MPIDI_RMA_FENCE_ISSUED && (*win_ptr)->states.access_state != MPIDI_RMA_FENCE_GRANTED) || ((*win_ptr)->states.exposure_state != MPIDI_RMA_NONE), mpi_errno, MPI_ERR_RMA_SYNC, "**rmasync"); /* 1. Here we must wait until all passive locks are released on this target, * because for some UNLOCK messages, we do not send ACK back to origin, * we must wait until lock is released so that we can free window. * 2. We also need to wait until AT completion counter being zero, because * this counter is increment everytime we meet a GET-like operation, it is * possible that when target entering Win_free, passive epoch is not finished * yet and there are still GETs doing on this target. * 3. We also need to wait until lock queue becomes empty. It is possible * that some lock requests is still waiting in the queue when target is * entering Win_free. */ while ((*win_ptr)->current_lock_type != MPID_LOCK_NONE || (*win_ptr)->at_completion_counter != 0 || (*win_ptr)->target_lock_queue_head != NULL || (*win_ptr)->current_target_lock_data_bytes != 0 || (*win_ptr)->sync_request_cnt != 0) { mpi_errno = wait_progress_engine(); if (mpi_errno != MPI_SUCCESS) MPIR_ERR_POP(mpi_errno); } mpi_errno = MPID_Barrier((*win_ptr)->comm_ptr, &errflag); if (mpi_errno) MPIR_ERR_POP(mpi_errno); /* Free window resources in lower layer. */ if (MPIDI_CH3U_Win_hooks.win_free != NULL) { mpi_errno = MPIDI_CH3U_Win_hooks.win_free(win_ptr); if (mpi_errno != MPI_SUCCESS) MPIR_ERR_POP(mpi_errno); } /* dequeue window from the global list */ MPIR_Assert((*win_ptr)->active == FALSE); DL_DELETE(MPIDI_RMA_Win_inactive_list_head, (*win_ptr)); if (MPIDI_RMA_Win_inactive_list_head == NULL && MPIDI_RMA_Win_active_list_head == NULL) { /* this is the last window, de-register RMA progress hook */ mpi_errno = MPID_Progress_deregister_hook(MPIDI_CH3I_RMA_Progress_hook_id); if (mpi_errno != MPI_SUCCESS) { MPIR_ERR_POP(mpi_errno); } } comm_ptr = (*win_ptr)->comm_ptr; mpi_errno = MPIR_Comm_free_impl(comm_ptr); if (mpi_errno) MPIR_ERR_POP(mpi_errno); if ((*win_ptr)->basic_info_table != NULL) MPL_free((*win_ptr)->basic_info_table); MPL_free((*win_ptr)->op_pool_start); MPL_free((*win_ptr)->target_pool_start); MPL_free((*win_ptr)->slots); MPL_free((*win_ptr)->target_lock_entry_pool_start); MPIR_Assert((*win_ptr)->current_target_lock_data_bytes == 0); /* Free the attached buffer for windows created with MPI_Win_allocate() */ if ((*win_ptr)->create_flavor == MPI_WIN_FLAVOR_ALLOCATE || (*win_ptr)->create_flavor == MPI_WIN_FLAVOR_SHARED) { if ((*win_ptr)->shm_allocated == FALSE && (*win_ptr)->size > 0) { MPL_free((*win_ptr)->base); } } MPIR_Object_release_ref(*win_ptr, &in_use); /* MPI windows don't have reference count semantics, so this should always be true */ MPIR_Assert(!in_use); MPIR_Handle_obj_free(&MPIR_Win_mem, *win_ptr); fn_exit: MPIR_FUNC_VERBOSE_RMA_EXIT(MPID_STATE_MPID_WIN_FREE); return mpi_errno; fn_fail: goto fn_exit; }
/* Now the functions */ static int intra_Barrier(struct MPIR_COMMUNICATOR *comm) { int rank, size, N2_prev, surfeit; int d, dst, src; MPI_Status status; /* Intialize communicator size */ (void) MPIR_Comm_size(comm, &size); #ifdef MPID_Barrier if (comm->ADIBarrier) { MPID_Barrier(comm->ADIctx, comm); return MPI_SUCCESS; } #endif /* If there's only one member, this is trivial */ if (size > 1) { /* Initialize collective communicator */ comm = comm->comm_coll; (void) MPIR_Comm_rank(comm, &rank); (void) MPIR_Comm_N2_prev(comm, &N2_prev); surfeit = size - N2_prev; /* Lock for collective operation */ MPID_THREAD_LOCK(comm->ADIctx, comm); /* Perform a combine-like operation */ if (rank < N2_prev) { if (rank < surfeit) { /* get the fanin letter from the upper "half" process: */ dst = N2_prev + rank; MPI_Recv((void *) 0, 0, MPI_INT, dst, MPIR_BARRIER_TAG, comm->self, &status); } /* combine on embedded N2_prev power-of-two processes */ for (d = 1; d < N2_prev; d <<= 1) { dst = (rank ^ d); MPI_Sendrecv((void *) 0, 0, MPI_INT, dst, MPIR_BARRIER_TAG, (void *) 0, 0, MPI_INT, dst, MPIR_BARRIER_TAG, comm->self, &status); } /* fanout data to nodes above N2_prev... */ if (rank < surfeit) { dst = N2_prev + rank; MPI_Send((void *) 0, 0, MPI_INT, dst, MPIR_BARRIER_TAG, comm->self); } } else { /* fanin data to power of 2 subset */ src = rank - N2_prev; MPI_Sendrecv((void *) 0, 0, MPI_INT, src, MPIR_BARRIER_TAG, (void *) 0, 0, MPI_INT, src, MPIR_BARRIER_TAG, comm->self, &status); } /* Unlock for collective operation */ MPID_THREAD_UNLOCK(comm->ADIctx, comm); } return (MPI_SUCCESS); }