Commit 52d75e0b authored by Brian Pickrell's avatar Brian Pickrell
Browse files

reorganized mutexes and locks; passes test

parent efb502bf
/* /*
* The MIT License (MIT) * The MIT License (MIT)
* *
* Copyright (c) 2015-2022 Advanced Micro Devices, Inc. All rights reserved. * Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
...@@ -34,59 +34,88 @@ inline namespace MIGRAPHX_INLINE_NS { ...@@ -34,59 +34,88 @@ inline namespace MIGRAPHX_INLINE_NS {
void store_target_lib(const dynamic_loader& lib) void store_target_lib(const dynamic_loader& lib)
{ {
static std::vector<dynamic_loader> target_loader; static std::vector<dynamic_loader> target_loader;
std::mutex mutex; static std::mutex mutex;
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
target_loader.emplace_back(lib); target_loader.emplace_back(lib);
} }
/**
* Returns a singleton map of targets and names.
*/
std::unordered_map<std::string, target>& target_map() std::unordered_map<std::string, target>& target_map()
{ {
static std::unordered_map<std::string, target> m; // NOLINT static std::unordered_map<std::string, target> m; // NOLINT
return m; return m;
} }
/**
* Returns a singleton mutex used by the various register_target methods.
*/
std::mutex& target_mutex()
{
static std::mutex m; // NOLINT
return m;
}
void register_target_init() { (void)target_map(); } void register_target_init() { (void)target_map(); }
void unregister_target(const std::string& name) void unregister_target(const std::string& name)
{ {
std::mutex mutex; std::unique_lock<std::mutex> lock(target_mutex());
std::unique_lock<std::mutex> lock(mutex);
assert(target_map().count(name)); assert(target_map().count(name));
target_map().erase(name); target_map().erase(name);
} }
/**
* Insert a target name in the target_map; thread safe.
*/
void register_target(const target& t) void register_target(const target& t)
{ {
std::mutex mutex; std::unique_lock<std::mutex> lock(target_mutex());
std::unique_lock<std::mutex> lock(mutex);
target_map()[t.name()] = t; target_map()[t.name()] = t;
} }
target make_target(const std::string& name) /**
* Search for a target by name in the target_map; thread-safe.
*/
migraphx::optional<target> find_target(const std::string& name)
{ {
// debug // search for match or return none
for(auto pp : target_map()) std::unique_lock<std::mutex> lock(target_mutex());
std::cout << pp.first << "\n"; const auto it = target_map().find(name);
std::mutex mutex; if(it == target_map().end())
std::unique_lock<std::mutex> lock(mutex); return nullopt;
if(not contains(target_map(), name)) return it->second;
}
/**
* Get a target by name. Load target library and register target if needed.
* Thread safe.
*/
target make_target(const std::string& name)
{
// no lock required here
auto t = find_target(name);
if(t == nullopt)
{ {
std::string target_name = "libmigraphx_" + name + ".so"; std::string target_name = "libmigraphx_" + name + ".so";
// register_target is called by this
store_target_lib(dynamic_loader(target_name)); store_target_lib(dynamic_loader(target_name));
t = find_target(name);
} }
const auto it = target_map().find(name); // at this point we should always have a target
if(it == target_map().end())
{ return *t;
MIGRAPHX_THROW("Requested target '" + name + "' is not loaded or not supported");
}
return it->second;
} }
/**
* Get list of names of registered targets.
*/
std::vector<std::string> get_targets() std::vector<std::string> get_targets()
{ {
std::unique_lock<std::mutex> lock(target_mutex());
std::vector<std::string> result; std::vector<std::string> result;
std::transform(target_map().begin(), std::transform(target_map().begin(),
target_map().end(), target_map().end(),
......
...@@ -57,7 +57,7 @@ TEST_CASE(concurrent_targets) ...@@ -57,7 +57,7 @@ TEST_CASE(concurrent_targets)
{ {
std::vector<std::thread> threads; std::vector<std::thread> threads;
for(auto i = 0u; i < 10000; i++) for(auto i = 0u; i < 1000; i++)
{ {
auto thread_body = []() { auto thread_body = []() {
auto ref_target = migraphx::make_target("gpu"); auto ref_target = migraphx::make_target("gpu");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment