}
void serialize(std::stringstream& stream) const override;
std::string to_string() const override;
- bool is_visible() const override { return true; }
};
void ObjectAccessObserver::serialize(std::stringstream& stream) const
{
simgrid::kernel::actor::ActorImpl* owner = nullptr;
const char* file = nullptr;
int line = -1;
- ObjectOwner(simgrid::kernel::actor::ActorImpl* o) : owner(o) {}
+ int recursive_depth = 0;
+ explicit ObjectOwner(simgrid::kernel::actor::ActorImpl* o) : owner(o) {}
};
std::unordered_map<void*, ObjectOwner*> owners;
{
if (owners.empty())
std::atexit(clean_owners);
- auto it = owners.find(object);
- if (it != owners.end())
+ if (auto it = owners.find(object); it != owners.end())
return it->second;
auto* o = new ObjectOwner(nullptr);
owners.emplace(object, o);
return o;
}
-int sthread_access_begin(void* objaddr, const char* objname, const char* file, int line)
+int sthread_access_begin(void* objaddr, const char* objname, const char* file, int line, const char* func)
{
sthread_disable();
auto* self = simgrid::kernel::actor::ActorImpl::self();
[self, objaddr, objname, file, line]() -> bool {
XBT_INFO("%s takes %s", self->get_cname(), objname);
auto* ownership = get_owner(objaddr);
- if (ownership->owner != nullptr) {
+ if (ownership->owner == self) {
+ ownership->recursive_depth++;
+ return true;
+ } else if (ownership->owner != nullptr) {
auto msg = std::string("Unprotected concurent access to ") + objname + ": " + ownership->owner->get_name();
- if (not xbt_log_no_loc)
+ if (not xbt_log_no_loc) {
msg += simgrid::xbt::string_printf(" at %s:%d", ownership->file, ownership->line);
+ if (ownership->recursive_depth > 1) {
+ msg += simgrid::xbt::string_printf(" (and %d other locations)", ownership->recursive_depth - 1);
+ if (ownership->recursive_depth != 2)
+ msg += "s";
+ }
+ } else {
+ msg += simgrid::xbt::string_printf(" from %d location", ownership->recursive_depth);
+ if (ownership->recursive_depth != 1)
+ msg += "s";
+ }
msg += " vs " + self->get_name();
if (xbt_log_no_loc)
msg += std::string(" (locations hidden because of --log=no_loc).");
ownership->owner = self;
ownership->file = file;
ownership->line = line;
+ ownership->recursive_depth = 1;
return true;
},
&observer);
sthread_enable();
return true;
}
-void sthread_access_end(void* objaddr, const char* objname, const char* file, int line)
+void sthread_access_end(void* objaddr, const char* objname, const char* file, int line, const char* func)
{
sthread_disable();
auto* self = simgrid::kernel::actor::ActorImpl::self();
[self, objaddr, objname]() -> void {
XBT_INFO("%s releases %s", self->get_cname(), objname);
auto* ownership = get_owner(objaddr);
- xbt_assert(ownership->owner == self, "safety check failed: I'm not owner of the object I'm releasing.");
- ownership->owner = nullptr;
+ xbt_assert(ownership->owner == self,
+ "safety check failed: %s is not owner of the object it's releasing. That object owned by %s.",
+ self->get_cname(), (ownership->owner == nullptr ? "nobody" : ownership->owner->get_cname()));
+ ownership->recursive_depth--;
+ if (ownership->recursive_depth == 0)
+ ownership->owner = nullptr;
},
&observer);
sthread_enable();