-/* Copyright (c) 2007-2022. The SimGrid Team. All rights reserved. */
+/* Copyright (c) 2007-2023. The SimGrid Team. All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */
#include "src/mc/mc_replay.hpp"
#include <algorithm>
+#include <mutex> // std::scoped_lock
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_rma, smpi, "Logging specific to SMPI (RMA operations)");
return MPI_ERR_WIN; \
}
-namespace simgrid{
-namespace smpi{
+namespace simgrid::smpi {
std::unordered_map<int, smpi_key_elem> Win::keyvals_;
int Win::keyval_id_=0;
colls::bcast(&bar_ptr, sizeof(s4u::Barrier*), MPI_BYTE, 0, comm);
if (rank_ != 0)
bar_ = s4u::BarrierPtr(bar_ptr);
- bar_->wait();
- }else{
- colls::barrier(comm);
}
this->add_f();
}
-Win::~Win(){
+int Win::del(Win* win){
//As per the standard, perform a barrier to ensure every async comm is finished
if (MC_is_active() || MC_record_replay_is_active())
- bar_->wait();
+ win->bar_->wait();
else
- colls::barrier(comm_);
- flush_local_all();
+ colls::barrier(win->comm_);
+ win->flush_local_all();
- if (info_ != MPI_INFO_NULL)
- simgrid::smpi::Info::unref(info_);
- if (errhandler_ != MPI_ERRHANDLER_NULL)
- simgrid::smpi::Errhandler::unref(errhandler_);
+ if (win->info_ != MPI_INFO_NULL)
+ simgrid::smpi::Info::unref(win->info_);
+ if (win->errhandler_ != MPI_ERRHANDLER_NULL)
+ simgrid::smpi::Errhandler::unref(win->errhandler_);
- comm_->remove_rma_win(this);
+ win->comm_->remove_rma_win(win);
- colls::barrier(comm_);
- Comm::unref(comm_);
+ colls::barrier(win->comm_);
+ Comm::unref(win->comm_);
+ if (not win->lockers_.empty() || win->opened_ < 0) {
+ XBT_WARN("Freeing a locked or opened window");
+ return MPI_ERR_WIN;
+ }
+ if (win->allocated_)
+ xbt_free(win->base_);
+ if (win->mut_->get_owner() != nullptr)
+ win->mut_->unlock();
- if (allocated_)
- xbt_free(base_);
+ F2C::free_f(win->f2c_id());
+ win->cleanup_attr<Win>();
- F2C::free_f(this->f2c_id());
- cleanup_attr<Win>();
+ delete win;
+ return MPI_SUCCESS;
}
int Win::attach(void* /*base*/, MPI_Aint size)
if(request!=nullptr){
*request=sreq;
}else{
- mut_->lock();
+ const std::scoped_lock lock(*mut_);
requests_.push_back(sreq);
- mut_->unlock();
}
//push request to receiver's win
- recv_win->mut_->lock();
+ const std::scoped_lock recv_lock(*recv_win->mut_);
recv_win->requests_.push_back(rreq);
rreq->start();
- recv_win->mut_->unlock();
} else {
XBT_DEBUG("Entering MPI_Put from myself to myself, rank %d", target_rank);
Datatype::copy(origin_addr, origin_count, origin_datatype, recv_addr, target_count, target_datatype);
//start the send, with another process than us as sender.
sreq->start();
// push request to sender's win
- send_win->mut_->lock();
- send_win->requests_.push_back(sreq);
- send_win->mut_->unlock();
+ if (const std::scoped_lock send_lock(*send_win->mut_); true) {
+ send_win->requests_.push_back(sreq);
+ }
//start recv
rreq->start();
if(request!=nullptr){
*request=rreq;
}else{
- mut_->lock();
+ const std::scoped_lock lock(*mut_);
requests_.push_back(rreq);
- mut_->unlock();
}
} else {
Datatype::copy(send_addr, target_count, target_datatype, origin_addr, origin_count, origin_datatype);
// start send
sreq->start();
// push request to receiver's win
- recv_win->mut_->lock();
- recv_win->requests_.push_back(rreq);
- rreq->start();
- recv_win->mut_->unlock();
+ if (const std::scoped_lock recv_lock(*recv_win->mut_); true) {
+ recv_win->requests_.push_back(rreq);
+ rreq->start();
+ }
if (request != nullptr) {
*request = sreq;
} else {
- mut_->lock();
+ const std::scoped_lock lock(*mut_);
requests_.push_back(sreq);
- mut_->unlock();
}
// FIXME: The current implementation fails to ensure the correct ordering of the accumulate requests. The following
XBT_DEBUG("Entering MPI_Get_accumulate from %d", target_rank);
//need to be sure ops are correctly ordered, so finish request here ? slow.
MPI_Request req = MPI_REQUEST_NULL;
- send_win->atomic_mut_->lock();
+ const std::scoped_lock lock(*send_win->atomic_mut_);
get(result_addr, result_count, result_datatype, target_rank,
target_disp, target_count, target_datatype, &req);
if (req != MPI_REQUEST_NULL)
target_disp, target_count, target_datatype, op, &req);
if (req != MPI_REQUEST_NULL)
Request::wait(&req, MPI_STATUS_IGNORE);
- send_win->atomic_mut_->unlock();
return MPI_SUCCESS;
}
XBT_DEBUG("Entering MPI_Compare_and_swap with %d", target_rank);
MPI_Request req = MPI_REQUEST_NULL;
- send_win->atomic_mut_->lock();
+ const std::scoped_lock lock(*send_win->atomic_mut_);
get(result_addr, 1, datatype, target_rank,
target_disp, 1, datatype, &req);
if (req != MPI_REQUEST_NULL)
put(origin_addr, 1, datatype, target_rank,
target_disp, 1, datatype);
}
- send_win->atomic_mut_->unlock();
return MPI_SUCCESS;
}
group->ref();
dst_group_ = group;
- opened_++; // we're open for business !
+ opened_--; // we're open for business !
XBT_DEBUG("Leaving MPI_Win_Start");
return MPI_SUCCESS;
}
group->ref();
src_group_ = group;
- opened_++; // we're open for business !
+ opened_--; // we're open for business !
XBT_DEBUG("Leaving MPI_Win_Post");
return MPI_SUCCESS;
}
flush_local_all();
- opened_--; //we're closed for business !
+ opened_++; //we're closed for business !
Group::unref(dst_group_);
dst_group_ = MPI_GROUP_NULL;
return MPI_SUCCESS;
flush_local_all();
- opened_--; //we're closed for business !
+ opened_++; //we're closed for business !
Group::unref(src_group_);
src_group_ = MPI_GROUP_NULL;
return MPI_SUCCESS;
// Without this, the vector could get redimensioned when another process pushes.
// This would result in the array used by Request::waitall() to be invalidated.
// Another solution would be to copy the data and cleanup the vector *before* Request::waitall
- mut_->lock();
+ const std::scoped_lock lock(*mut_);
//Finish own requests
int size = static_cast<int>(requests_.size());
if (size > 0) {
Request::waitall(size, treqs, MPI_STATUSES_IGNORE);
requests_.clear();
}
- mut_->unlock();
return size;
}
int Win::finish_comms(int rank){
// See comment about the mutex in finish_comms() above
- mut_->lock();
+ const std::scoped_lock lock(*mut_);
// Finish own requests
// Let's see if we're either the destination or the sender of this request
// because we only wait for requests that we are responsible for.
Request::waitall(size, treqs, MPI_STATUSES_IGNORE);
myreqqs.clear();
}
- mut_->unlock();
return size;
}
if (errhandler_ != MPI_ERRHANDLER_NULL)
errhandler_->ref();
}
-} // namespace smpi
-} // namespace simgrid
+} // namespace simgrid::smpi