Add LoadableLibraryManager and refactor StimBuffApiManager to use it.
Centralize dlopen/search in LoadableLibraryManager so typed library managers can share one loaded-shlib registry without duplicating load/unload logic. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -36,6 +36,9 @@ add_library(smocore STATIC
|
||||
# SenseApis
|
||||
stimBuffApis/stimBuffApiManager.cpp
|
||||
|
||||
# Loadable shared libraries
|
||||
loadableLib/loadableLibraryManager.cpp
|
||||
|
||||
# ComputeManager
|
||||
computeManager/computeManager.cpp
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <deviceManager/deviceManager.h>
|
||||
#include <deviceManager/deviceReattacher.h>
|
||||
#include <stimBuffApis/stimBuffApiManager.h>
|
||||
#include <loadableLib/loadableLibraryManager.h>
|
||||
#include <marionette/marionette.h>
|
||||
#include <marionette/marionetteThread.h>
|
||||
#include <mind.h>
|
||||
@@ -92,7 +93,7 @@ DeviceManager::attachStimBuffDeviceCReq(
|
||||
auto &sbam = stim_buff::StimBuffApiManager::getInstance();
|
||||
auto &lib = sbam.getStimBuffApiLibByApiName(spec->stimBuffApi);
|
||||
|
||||
if (lib.isBeingDestroyed.load())
|
||||
if (lib.loadedSharedLibrary->isBeingDestroyed.load())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Library is being destroyed"
|
||||
@@ -103,12 +104,13 @@ DeviceManager::attachStimBuffDeviceCReq(
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": attachDeviceCReq() is NULL "
|
||||
"for library '" + lib.libraryPath + "'");
|
||||
"for library '" + lib.loadedSharedLibrary->libraryPath + "'");
|
||||
}
|
||||
|
||||
/* FIXME Locking here makes no sense. */
|
||||
sscl::co::CoQutex::ReleaseHandle sbamGuard =
|
||||
co_await sbam.s.lock.getAcquireInvocationAndSuspensionPolicy();
|
||||
co_await sbam.s.lock
|
||||
.getAcquireInvocationAndSuspensionPolicy();
|
||||
sscl::co::CoQutex::ReleaseHandle libGuard =
|
||||
co_await lib.s.lock.getAcquireInvocationAndSuspensionPolicy();
|
||||
sbamGuard.release();
|
||||
@@ -151,7 +153,7 @@ DeviceManager::detachStimBuffDeviceCReq(
|
||||
auto &sbam = stim_buff::StimBuffApiManager::getInstance();
|
||||
auto &lib = sbam.getStimBuffApiLibByApiName(spec->stimBuffApi);
|
||||
|
||||
if (lib.isBeingDestroyed.load())
|
||||
if (lib.loadedSharedLibrary->isBeingDestroyed.load())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Library is being destroyed"
|
||||
@@ -162,12 +164,13 @@ DeviceManager::detachStimBuffDeviceCReq(
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": detachDeviceCReq() is NULL "
|
||||
"for library '" + lib.libraryPath + "'");
|
||||
"for library '" + lib.loadedSharedLibrary->libraryPath + "'");
|
||||
}
|
||||
|
||||
/* FIXME Locking here makes no sense. */
|
||||
sscl::co::CoQutex::ReleaseHandle sbamGuard =
|
||||
co_await sbam.s.lock.getAcquireInvocationAndSuspensionPolicy();
|
||||
co_await sbam.s.lock
|
||||
.getAcquireInvocationAndSuspensionPolicy();
|
||||
sscl::co::CoQutex::ReleaseHandle libGuard =
|
||||
co_await lib.s.lock.getAcquireInvocationAndSuspensionPolicy();
|
||||
sbamGuard.release();
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
#ifndef LOADABLE_LIBRARY_MANAGER_H
|
||||
#define LOADABLE_LIBRARY_MANAGER_H
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <spinscale/co/coQutex.h>
|
||||
#include <spinscale/sharedResourceGroup.h>
|
||||
|
||||
namespace smo {
|
||||
namespace loadable_lib {
|
||||
|
||||
class LoadableLibraryManager
|
||||
{
|
||||
public:
|
||||
struct SharedLibraryDeleter
|
||||
{
|
||||
void operator()(void* handle) const;
|
||||
};
|
||||
|
||||
struct LoadedSharedLibrary
|
||||
{
|
||||
LoadedSharedLibrary(
|
||||
std::string libraryPathIn,
|
||||
std::string resolvedPathIn,
|
||||
std::unique_ptr<void, SharedLibraryDeleter> dlopenHandleIn)
|
||||
: libraryPath(std::move(libraryPathIn)),
|
||||
resolvedPath(std::move(resolvedPathIn)),
|
||||
dlopenHandle(std::move(dlopenHandleIn))
|
||||
{}
|
||||
|
||||
std::string libraryPath;
|
||||
std::string resolvedPath;
|
||||
std::unique_ptr<void, SharedLibraryDeleter> dlopenHandle;
|
||||
std::atomic<bool> isBeingDestroyed{false};
|
||||
|
||||
void* getDlopenHandle() const
|
||||
{
|
||||
return dlopenHandle.get();
|
||||
}
|
||||
};
|
||||
|
||||
struct Resources
|
||||
{
|
||||
std::vector<std::shared_ptr<LoadedSharedLibrary>> loadedSharedLibraries;
|
||||
};
|
||||
|
||||
static LoadableLibraryManager& getInstance()
|
||||
{
|
||||
static LoadableLibraryManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::optional<std::string> searchForLibInSmoSearchPaths(
|
||||
const std::string& libraryPath) const;
|
||||
|
||||
std::shared_ptr<LoadedSharedLibrary> loadSharedLibrary(
|
||||
const std::string& libraryPath);
|
||||
|
||||
void unloadSharedLibrary(
|
||||
const std::shared_ptr<LoadedSharedLibrary>& loadedLibrary);
|
||||
|
||||
template<typename FnPtr>
|
||||
static FnPtr resolveSymbol(void* handle, const char* symbolName)
|
||||
{
|
||||
dlerror();
|
||||
auto symbol = reinterpret_cast<FnPtr>(dlsym(handle, symbolName));
|
||||
const char* dlerr = dlerror();
|
||||
if (dlerr != nullptr)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("dlsym('") + symbolName + "') failed: " + dlerr);
|
||||
}
|
||||
|
||||
if (symbol == nullptr)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("dlsym('") + symbolName + "') returned null");
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public:
|
||||
sscl::SharedResourceGroup<sscl::co::CoQutex, Resources> s;
|
||||
|
||||
private:
|
||||
LoadableLibraryManager()
|
||||
: s("LoadableLibraryManager")
|
||||
{}
|
||||
|
||||
~LoadableLibraryManager();
|
||||
|
||||
LoadableLibraryManager(const LoadableLibraryManager&) = delete;
|
||||
LoadableLibraryManager& operator=(const LoadableLibraryManager&) = delete;
|
||||
|
||||
void appendLoadedSharedLibrary(
|
||||
const std::shared_ptr<LoadedSharedLibrary>& loadedLibrary);
|
||||
|
||||
void removeLoadedSharedLibrary(
|
||||
const std::shared_ptr<LoadedSharedLibrary>& loadedLibrary);
|
||||
};
|
||||
|
||||
} // namespace loadable_lib
|
||||
} // namespace smo
|
||||
|
||||
#endif // LOADABLE_LIBRARY_MANAGER_H
|
||||
@@ -3,11 +3,10 @@
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <dlfcn.h>
|
||||
#include <functional>
|
||||
#include <user/senseApiDesc.h>
|
||||
#include <loadableLib/loadableLibraryManager.h>
|
||||
#include <spinscale/co/coQutex.h>
|
||||
#include <spinscale/sharedResourceGroup.h>
|
||||
|
||||
@@ -18,25 +17,15 @@ class StimBuffApiLib
|
||||
{
|
||||
private:
|
||||
friend class StimBuffApiManager;
|
||||
struct DlCloser
|
||||
{
|
||||
void operator()(void* handle) const
|
||||
{
|
||||
if (handle) {
|
||||
dlclose(handle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
StimBuffApiLib(
|
||||
const std::string& path, void *_dlopen_handle,
|
||||
std::shared_ptr<loadable_lib::LoadableLibraryManager::LoadedSharedLibrary>
|
||||
_loadedSharedLibrary,
|
||||
SMO_GET_STIM_BUFF_API_DESC_FN_TYPEDEF *descFn)
|
||||
: libraryPath(path),
|
||||
isBeingDestroyed(false),
|
||||
dlopen_handle(_dlopen_handle, DlCloser()),
|
||||
: loadedSharedLibrary(std::move(_loadedSharedLibrary)),
|
||||
SMO_GET_STIM_BUFF_API_DESC_FN_NAME(descFn),
|
||||
s("StimBuffApiLib-" + path)
|
||||
s("StimBuffApiLib-" + loadedSharedLibrary->libraryPath)
|
||||
{}
|
||||
|
||||
void setStimBuffApiDesc(const StimBuffApiDesc &desc)
|
||||
@@ -45,16 +34,16 @@ public:
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Sanity check failed for stim buff API "
|
||||
"descriptor in library '" + libraryPath + "'");
|
||||
"descriptor in library '"
|
||||
+ loadedSharedLibrary->libraryPath + "'");
|
||||
}
|
||||
|
||||
stimBuffApiDesc = desc;
|
||||
}
|
||||
|
||||
public:
|
||||
std::string libraryPath;
|
||||
std::atomic<bool> isBeingDestroyed;
|
||||
std::unique_ptr<void, DlCloser> dlopen_handle;
|
||||
std::shared_ptr<loadable_lib::LoadableLibraryManager::LoadedSharedLibrary>
|
||||
loadedSharedLibrary;
|
||||
/* UNIMPLEMENTED: API-specific cmdline options. These affect this specific
|
||||
* stim buff api lib's behaviour globally.
|
||||
*/
|
||||
@@ -83,8 +72,10 @@ public:
|
||||
|
||||
sscl::SharedResourceGroup<sscl::co::CoQutex, StimBuffApiLibResources> s;
|
||||
|
||||
std::string stringify() const {
|
||||
std::string result = "Library Path: " + libraryPath + "\n";
|
||||
std::string stringify() const
|
||||
{
|
||||
std::string result = "Library Path: "
|
||||
+ loadedSharedLibrary->libraryPath + "\n";
|
||||
result += "Stim Buff API Descriptor: " + stimBuffApiDesc.stringify() + "\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ class StimBuffApiManager
|
||||
public:
|
||||
struct Resources
|
||||
{
|
||||
std::vector<std::shared_ptr<StimBuffApiLib>> stimBuffApiLibs;
|
||||
std::vector<std::shared_ptr<StimBuffApiLib>> libs;
|
||||
};
|
||||
|
||||
static StimBuffApiManager& getInstance()
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
const std::string& libraryPath,
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread);
|
||||
|
||||
std::optional<std::shared_ptr<StimBuffApiLib>> getStimBuffApiLib(
|
||||
std::optional<std::shared_ptr<StimBuffApiLib>> findStimBuffApiLibByLibraryPath(
|
||||
const std::string& libraryPath);
|
||||
std::optional<std::shared_ptr<StimBuffApiLib>> findStimBuffApiLibByApiName(
|
||||
const std::string& apiName);
|
||||
@@ -48,19 +48,21 @@ public:
|
||||
|
||||
void loadAllStimBuffApiLibsFromOptions(
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread);
|
||||
|
||||
void unloadAllStimBuffApiLibs(void);
|
||||
|
||||
body::BodyViralPostingInvoker<void> initializeStimBuffApiLibCReq(
|
||||
StimBuffApiLib &lib, bool acquireSbamLock=true);
|
||||
StimBuffApiLib &lib, bool acquireListLock=true);
|
||||
body::BodyViralPostingInvoker<void> finalizeStimBuffApiLibCReq(
|
||||
StimBuffApiLib &lib, bool acquireSbamLock=true);
|
||||
StimBuffApiLib &lib, bool acquireListLock=true);
|
||||
|
||||
body::BodyViralPostingInvoker<void> initializeAllStimBuffApiLibsCReq();
|
||||
body::BodyViralPostingInvoker<void> finalizeAllStimBuffApiLibsCReq();
|
||||
|
||||
std::string stringifyLibs() const;
|
||||
|
||||
public:
|
||||
sscl::SharedResourceGroup<sscl::co::CoQutex, Resources> s;
|
||||
|
||||
private:
|
||||
StimBuffApiManager()
|
||||
: s("StimBuffApiManager")
|
||||
@@ -70,13 +72,6 @@ private:
|
||||
|
||||
StimBuffApiManager(const StimBuffApiManager&) = delete;
|
||||
StimBuffApiManager& operator=(const StimBuffApiManager&) = delete;
|
||||
|
||||
public:
|
||||
sscl::SharedResourceGroup<sscl::co::CoQutex, Resources> s;
|
||||
|
||||
public:
|
||||
static std::optional<std::string> searchForLibInSmoSearchPaths(
|
||||
const std::string& libraryPath);
|
||||
};
|
||||
|
||||
} // namespace stim_buff
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <loadableLib/loadableLibraryManager.h>
|
||||
#include <opts.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace smo {
|
||||
namespace loadable_lib {
|
||||
|
||||
namespace {
|
||||
|
||||
std::vector<std::string> buildSmoLibrarySearchPaths()
|
||||
{
|
||||
std::vector<std::string> searchPaths = {
|
||||
fs::current_path().string(),
|
||||
fs::path("/proc/self/exe").parent_path().string()
|
||||
};
|
||||
|
||||
const auto& options = OptionParser::getOptions();
|
||||
if (!options.senseApiLibPath.empty())
|
||||
{
|
||||
searchPaths.insert(
|
||||
searchPaths.begin(),
|
||||
options.senseApiLibPath.begin(),
|
||||
options.senseApiLibPath.end());
|
||||
}
|
||||
|
||||
return searchPaths;
|
||||
}
|
||||
|
||||
void logLibraryNotInSearchPaths(
|
||||
const std::string& libraryPath,
|
||||
const std::vector<std::string>& searchPaths)
|
||||
{
|
||||
std::cerr << "searchForLibInSmoSearchPaths: library '"
|
||||
<< libraryPath << "' isn't in search bespoke search paths: ";
|
||||
|
||||
for (const auto& path : searchPaths) {
|
||||
std::cerr << path << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Trying to load " << libraryPath
|
||||
<< " from system default search paths\n";
|
||||
}
|
||||
|
||||
std::unique_ptr<void, LoadableLibraryManager::SharedLibraryDeleter>
|
||||
tryDlopenPath(const std::string& path)
|
||||
{
|
||||
dlerror();
|
||||
void* handle = dlopen(path.c_str(), RTLD_LAZY);
|
||||
if (!handle) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return std::unique_ptr<
|
||||
void, LoadableLibraryManager::SharedLibraryDeleter>(handle);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
LoadableLibraryManager::~LoadableLibraryManager() = default;
|
||||
|
||||
void LoadableLibraryManager::SharedLibraryDeleter::operator()(void* handle) const
|
||||
{
|
||||
if (handle) {
|
||||
dlclose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadableLibraryManager::appendLoadedSharedLibrary(
|
||||
const std::shared_ptr<LoadedSharedLibrary>& loadedLibrary)
|
||||
{
|
||||
s.rsrc.loadedSharedLibraries.push_back(loadedLibrary);
|
||||
}
|
||||
|
||||
void LoadableLibraryManager::removeLoadedSharedLibrary(
|
||||
const std::shared_ptr<LoadedSharedLibrary>& loadedLibrary)
|
||||
{
|
||||
auto& loadedLibs = s.rsrc.loadedSharedLibraries;
|
||||
auto it = std::find(loadedLibs.begin(), loadedLibs.end(), loadedLibrary);
|
||||
if (it != loadedLibs.end()) {
|
||||
loadedLibs.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::string> LoadableLibraryManager::searchForLibInSmoSearchPaths(
|
||||
const std::string& libraryPath) const
|
||||
{
|
||||
const std::vector<std::string> searchPaths = buildSmoLibrarySearchPaths();
|
||||
|
||||
for (const auto& path : searchPaths)
|
||||
{
|
||||
fs::path fullPath = fs::path(path) / libraryPath;
|
||||
if (fs::exists(fullPath)) {
|
||||
return fullPath.string();
|
||||
}
|
||||
}
|
||||
|
||||
logLibraryNotInSearchPaths(libraryPath, searchPaths);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::shared_ptr<LoadableLibraryManager::LoadedSharedLibrary>
|
||||
LoadableLibraryManager::loadSharedLibrary(const std::string& libraryPath)
|
||||
{
|
||||
const std::optional<std::string> fullPath =
|
||||
searchForLibInSmoSearchPaths(libraryPath);
|
||||
const std::string resolvedPath = fullPath.value_or(libraryPath);
|
||||
|
||||
auto dlopenHandle = tryDlopenPath(resolvedPath);
|
||||
if (!dlopenHandle && fullPath.has_value()) {
|
||||
dlopenHandle = tryDlopenPath(libraryPath);
|
||||
}
|
||||
|
||||
if (!dlopenHandle)
|
||||
{
|
||||
const char* dlerr = dlerror();
|
||||
const std::string error = (dlerr
|
||||
? dlerr
|
||||
: "Unknown error while opening shlib");
|
||||
throw std::runtime_error(
|
||||
std::string("loadSharedLibrary: Cannot load library '")
|
||||
+ libraryPath + "': " + error);
|
||||
}
|
||||
|
||||
auto loadedLibrary = std::make_shared<LoadedSharedLibrary>(
|
||||
libraryPath,
|
||||
resolvedPath,
|
||||
std::move(dlopenHandle));
|
||||
|
||||
appendLoadedSharedLibrary(loadedLibrary);
|
||||
return loadedLibrary;
|
||||
}
|
||||
|
||||
void LoadableLibraryManager::unloadSharedLibrary(
|
||||
const std::shared_ptr<LoadedSharedLibrary>& loadedLibrary)
|
||||
{
|
||||
if (!loadedLibrary) {
|
||||
return;
|
||||
}
|
||||
|
||||
removeLoadedSharedLibrary(loadedLibrary);
|
||||
loadedLibrary->dlopenHandle.reset();
|
||||
}
|
||||
|
||||
} // namespace loadable_lib
|
||||
} // namespace smo
|
||||
@@ -1,9 +1,10 @@
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <optional>
|
||||
#include <filesystem>
|
||||
#include <algorithm>
|
||||
#include <stimBuffApis/stimBuffApiManager.h>
|
||||
#include <stimBuffApis/stimBuffApiLib.h>
|
||||
#include <loadableLib/loadableLibraryManager.h>
|
||||
#include <body/bodyThread.h>
|
||||
#include <componentThread.h>
|
||||
#include <opts.h>
|
||||
@@ -13,9 +14,6 @@
|
||||
#include <marionette/marionette.h>
|
||||
#include <computeManager/computeManager.h>
|
||||
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace smo {
|
||||
namespace stim_buff {
|
||||
|
||||
@@ -32,109 +30,55 @@ void assertBodyThread()
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* @brief Searches for a library in predefined locations
|
||||
* @param libraryPath The name or path of the library to find
|
||||
* @return Optional containing the full path if found in search paths, nullopt
|
||||
* if not
|
||||
*
|
||||
* Searches for the library in the following locations in order:
|
||||
* 1. Custom path specified by --sense-api-lib-path option (if provided)
|
||||
* 2. Current working directory
|
||||
* 3. Directory containing the executable
|
||||
*
|
||||
* If the library is not found in any of these locations, returns nullopt and
|
||||
* falls back to system default library search paths (LD_LIBRARY_PATH, etc.)
|
||||
*/
|
||||
static std::optional<std::string> searchForLibInSmoSearchPaths(
|
||||
const std::string& libraryPath)
|
||||
{
|
||||
std::vector<std::string> searchPaths = {
|
||||
fs::current_path().string(),
|
||||
fs::path("/proc/self/exe").parent_path().string()
|
||||
};
|
||||
|
||||
const auto& options = OptionParser::getOptions();
|
||||
if (!options.senseApiLibPath.empty())
|
||||
{
|
||||
// Insert all stim buff API library paths at the beginning of search paths
|
||||
searchPaths.insert(
|
||||
searchPaths.begin(),
|
||||
options.senseApiLibPath.begin(),
|
||||
options.senseApiLibPath.end());
|
||||
}
|
||||
|
||||
for (const auto& path : searchPaths)
|
||||
{
|
||||
fs::path fullPath = fs::path(path) / libraryPath;
|
||||
if (fs::exists(fullPath))
|
||||
{
|
||||
return fullPath.string();
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << std::string(__func__) + ": library '"
|
||||
+ libraryPath + "' isn't in search bespoke search paths: ";
|
||||
for (const auto& path : searchPaths) {
|
||||
std::cerr << path << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Trying to load " + libraryPath + " from system default "
|
||||
"search paths\n";
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/* Local static function to wrap sscl::ComponentThread::getSelf for SmoCallbacks */
|
||||
static std::shared_ptr<sscl::ComponentThread> ComponentThread_getSelf()
|
||||
std::shared_ptr<sscl::ComponentThread> ComponentThread_getSelf()
|
||||
{
|
||||
return sscl::ComponentThread::getSelf();
|
||||
}
|
||||
|
||||
/* Local static function to wrap OptionParser::getOptions for SmoCallbacks */
|
||||
static OptionParser& OptionParser_getOptions()
|
||||
OptionParser& OptionParser_getOptions()
|
||||
{
|
||||
return OptionParser::getOptions();
|
||||
}
|
||||
|
||||
/* Local static functions to wrap ComputeManager methods for SmoCallbacks */
|
||||
static std::shared_ptr<smo::compute::ClBuffer>
|
||||
std::shared_ptr<smo::compute::ClBuffer>
|
||||
ComputeManager_createUseHostPtrBuffer(
|
||||
void* hostPtr, size_t size, cl_mem_flags flags
|
||||
)
|
||||
void* hostPtr, size_t size, cl_mem_flags flags)
|
||||
{
|
||||
return smo::compute::ComputeManager::getInstance().createUseHostPtrBuffer(
|
||||
hostPtr, size, flags);
|
||||
}
|
||||
|
||||
static void ComputeManager_releaseUseHostPtrBuffer(
|
||||
std::shared_ptr<smo::compute::ClBuffer> buffer
|
||||
)
|
||||
void ComputeManager_releaseUseHostPtrBuffer(
|
||||
std::shared_ptr<smo::compute::ClBuffer> buffer)
|
||||
{
|
||||
smo::compute::ComputeManager::getInstance().releaseUseHostPtrBuffer(
|
||||
buffer);
|
||||
}
|
||||
|
||||
static std::shared_ptr<smo::compute::ComputeDevice> ComputeManager_getDevice()
|
||||
std::shared_ptr<smo::compute::ComputeDevice> ComputeManager_getDevice()
|
||||
{
|
||||
return smo::compute::ComputeManager::getInstance().getDevice();
|
||||
}
|
||||
|
||||
static void ComputeManager_releaseDevice(
|
||||
std::shared_ptr<smo::compute::ComputeDevice> device
|
||||
)
|
||||
void ComputeManager_releaseDevice(
|
||||
std::shared_ptr<smo::compute::ComputeDevice> device)
|
||||
{
|
||||
smo::compute::ComputeManager::getInstance().releaseDevice(device);
|
||||
}
|
||||
|
||||
std::optional<std::string> searchForLibInSmoSearchPathsHook(
|
||||
const std::string& libraryPath)
|
||||
{
|
||||
return loadable_lib::LoadableLibraryManager::getInstance()
|
||||
.searchForLibInSmoSearchPaths(libraryPath);
|
||||
}
|
||||
|
||||
/* Hooks to be provided to stimBuffApiLibs, enabling them to call into Salmanoff
|
||||
* code.
|
||||
*/
|
||||
static SmoCallbacks smoCallbacks =
|
||||
SmoCallbacks smoCallbacks =
|
||||
{
|
||||
.searchForLibInSmoSearchPaths = searchForLibInSmoSearchPaths,
|
||||
.searchForLibInSmoSearchPaths = searchForLibInSmoSearchPathsHook,
|
||||
.ComponentThread_getSelf = ComponentThread_getSelf,
|
||||
.OptionParser_getOptions = OptionParser_getOptions,
|
||||
.ComputeManager_createUseHostPtrBuffer =
|
||||
@@ -146,84 +90,58 @@ static SmoCallbacks smoCallbacks =
|
||||
};
|
||||
|
||||
/* Static file-scope threading model object for senseApi libraries */
|
||||
static SmoThreadingModelDesc smoThreadingModelDesc = {
|
||||
SmoThreadingModelDesc smoThreadingModelDesc = {
|
||||
.componentThread = nullptr
|
||||
};
|
||||
|
||||
std::optional<std::string> StimBuffApiManager::searchForLibInSmoSearchPaths(
|
||||
const std::string& libraryPath)
|
||||
{
|
||||
return ::smo::stim_buff::searchForLibInSmoSearchPaths(libraryPath);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
StimBuffApiLib& StimBuffApiManager::loadStimBuffApiLib(
|
||||
const std::string& libraryPath,
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread
|
||||
)
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread)
|
||||
{
|
||||
std::optional<std::string> fullPath = searchForLibInSmoSearchPaths(
|
||||
libraryPath);
|
||||
std::string resolvedPath = fullPath.value_or(libraryPath);
|
||||
loadable_lib::LoadableLibraryManager& llm =
|
||||
loadable_lib::LoadableLibraryManager::getInstance();
|
||||
|
||||
// Clear any existing error
|
||||
dlerror();
|
||||
auto dlopen_handle = std::unique_ptr<void, StimBuffApiLib::DlCloser>(
|
||||
dlopen(resolvedPath.c_str(), RTLD_LAZY));
|
||||
if (!dlopen_handle && fullPath.has_value())
|
||||
{
|
||||
// Fallback to using the supplied libraryPath
|
||||
dlerror();
|
||||
dlopen_handle.reset(dlopen(libraryPath.c_str(), RTLD_LAZY));
|
||||
}
|
||||
|
||||
if (!dlopen_handle)
|
||||
{
|
||||
const char *dlerr = dlerror();
|
||||
|
||||
std::string error = (dlerr
|
||||
? dlerr
|
||||
: "Unknown error while opening shlib");
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Cannot load library '"
|
||||
+ libraryPath + "': "
|
||||
+ error);
|
||||
}
|
||||
|
||||
// Initialize getSenseApiDescriptor
|
||||
auto func = reinterpret_cast<SMO_GET_STIM_BUFF_API_DESC_FN_TYPEDEF *>(
|
||||
dlsym(dlopen_handle.get(), SMO_GET_STIM_BUFF_API_DESC_FN_NAME_STR));
|
||||
if (!func)
|
||||
if (findStimBuffApiLibByLibraryPath(libraryPath))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": dlsym('"
|
||||
SMO_GET_STIM_BUFF_API_DESC_FN_NAME_STR "') failed for library '"
|
||||
+ libraryPath + "'");
|
||||
std::string(__func__) + ": StimBuffApiLib already loaded: "
|
||||
+ libraryPath);
|
||||
}
|
||||
|
||||
// Check if the static threading model obj is null and initialize if needed
|
||||
std::shared_ptr<loadable_lib::LoadableLibraryManager::LoadedSharedLibrary>
|
||||
loadedLibrary = llm.loadSharedLibrary(libraryPath);
|
||||
|
||||
auto descFn = loadable_lib::LoadableLibraryManager::resolveSymbol<
|
||||
SMO_GET_STIM_BUFF_API_DESC_FN_TYPEDEF *>(
|
||||
loadedLibrary->getDlopenHandle(),
|
||||
SMO_GET_STIM_BUFF_API_DESC_FN_NAME_STR);
|
||||
|
||||
if (!smoThreadingModelDesc.componentThread) {
|
||||
smoThreadingModelDesc.componentThread = componentThread;
|
||||
}
|
||||
|
||||
const StimBuffApiDesc &libApiDesc = func(
|
||||
const StimBuffApiDesc& libApiDesc = descFn(
|
||||
smoCallbacks, smoThreadingModelDesc);
|
||||
|
||||
auto lib = std::make_shared<StimBuffApiLib>(
|
||||
libraryPath, dlopen_handle.release(), func);
|
||||
auto lib = std::make_shared<StimBuffApiLib>(loadedLibrary, descFn);
|
||||
lib->setStimBuffApiDesc(libApiDesc);
|
||||
getInstance().s.rsrc.stimBuffApiLibs.push_back(lib);
|
||||
return *getInstance().s.rsrc.stimBuffApiLibs.back();
|
||||
s.rsrc.libs.push_back(lib);
|
||||
|
||||
return *lib;
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<StimBuffApiLib>>
|
||||
StimBuffApiManager::getStimBuffApiLib(const std::string& libraryPath)
|
||||
StimBuffApiManager::findStimBuffApiLibByLibraryPath(
|
||||
const std::string& libraryPath)
|
||||
{
|
||||
auto &libs = getInstance().s.rsrc.stimBuffApiLibs;
|
||||
auto it = std::find_if(libs.begin(), libs.end(),
|
||||
[&libPath = libraryPath](const std::shared_ptr<StimBuffApiLib>& lib) {
|
||||
return lib->libraryPath == libPath;
|
||||
}
|
||||
);
|
||||
auto& libs = s.rsrc.libs;
|
||||
auto it = std::find_if(
|
||||
libs.begin(), libs.end(),
|
||||
[&libraryPath](const std::shared_ptr<StimBuffApiLib>& lib) {
|
||||
return lib->loadedSharedLibrary->libraryPath == libraryPath;
|
||||
});
|
||||
|
||||
if (it != libs.end()) { return *it; }
|
||||
return std::nullopt;
|
||||
@@ -232,12 +150,12 @@ StimBuffApiManager::getStimBuffApiLib(const std::string& libraryPath)
|
||||
std::optional<std::shared_ptr<StimBuffApiLib>>
|
||||
StimBuffApiManager::findStimBuffApiLibByApiName(const std::string& apiName)
|
||||
{
|
||||
auto &libs = getInstance().s.rsrc.stimBuffApiLibs;
|
||||
auto it = std::find_if(libs.begin(), libs.end(),
|
||||
auto& libs = s.rsrc.libs;
|
||||
auto it = std::find_if(
|
||||
libs.begin(), libs.end(),
|
||||
[&apiName](const std::shared_ptr<StimBuffApiLib>& lib) {
|
||||
return lib->stimBuffApiDesc.name == apiName;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
if (it != libs.end()) { return *it; }
|
||||
return std::nullopt;
|
||||
@@ -258,31 +176,42 @@ StimBuffApiLib &StimBuffApiManager::getStimBuffApiLibByApiName(
|
||||
|
||||
void StimBuffApiManager::unloadStimBuffApiLib(const std::string& libraryPath)
|
||||
{
|
||||
auto &libs = getInstance().s.rsrc.stimBuffApiLibs;
|
||||
auto it = std::find_if(libs.begin(), libs.end(),
|
||||
[&lpath = libraryPath](const std::shared_ptr<StimBuffApiLib>& lib) {
|
||||
return lib->libraryPath == lpath;
|
||||
}
|
||||
);
|
||||
auto& libs = s.rsrc.libs;
|
||||
auto it = std::find_if(
|
||||
libs.begin(), libs.end(),
|
||||
[&libraryPath](const std::shared_ptr<StimBuffApiLib>& lib) {
|
||||
return lib->loadedSharedLibrary->libraryPath == libraryPath;
|
||||
});
|
||||
|
||||
if (it != libs.end())
|
||||
if (it == libs.end())
|
||||
{
|
||||
libs.erase(it);
|
||||
std::cerr << std::string(__func__) + ": Library not found: "
|
||||
<< libraryPath << '\n';
|
||||
return;
|
||||
}
|
||||
|
||||
std::cerr << std::string(__func__) + ": Library not found: "
|
||||
<< libraryPath << '\n';
|
||||
std::shared_ptr<loadable_lib::LoadableLibraryManager::LoadedSharedLibrary>
|
||||
loadedLibrary = (*it)->loadedSharedLibrary;
|
||||
libs.erase(it);
|
||||
|
||||
loadable_lib::LoadableLibraryManager::getInstance()
|
||||
.unloadSharedLibrary(loadedLibrary);
|
||||
}
|
||||
|
||||
void StimBuffApiManager::unloadAllStimBuffApiLibs(void)
|
||||
{
|
||||
getInstance().s.rsrc.stimBuffApiLibs.clear();
|
||||
auto libs = s.rsrc.libs;
|
||||
s.rsrc.libs.clear();
|
||||
|
||||
for (const auto& lib : libs)
|
||||
{
|
||||
loadable_lib::LoadableLibraryManager::getInstance()
|
||||
.unloadSharedLibrary(lib->loadedSharedLibrary);
|
||||
}
|
||||
}
|
||||
|
||||
void StimBuffApiManager::loadAllStimBuffApiLibsFromOptions(
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread
|
||||
)
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread)
|
||||
{
|
||||
const auto& options = OptionParser::getOptions();
|
||||
for (const auto& libPath : options.senseApiLibs) {
|
||||
@@ -293,7 +222,7 @@ void StimBuffApiManager::loadAllStimBuffApiLibsFromOptions(
|
||||
std::string StimBuffApiManager::stringifyLibs() const
|
||||
{
|
||||
std::string result;
|
||||
for (const auto& lib : getInstance().s.rsrc.stimBuffApiLibs) {
|
||||
for (const auto& lib : s.rsrc.libs) {
|
||||
result += lib->stringify() + "\n";
|
||||
}
|
||||
return result;
|
||||
@@ -301,23 +230,22 @@ std::string StimBuffApiManager::stringifyLibs() const
|
||||
|
||||
body::BodyViralPostingInvoker<void>
|
||||
StimBuffApiManager::initializeStimBuffApiLibCReq(
|
||||
StimBuffApiLib &lib, bool acquireSbamLock)
|
||||
StimBuffApiLib& lib, bool acquireListLock)
|
||||
{
|
||||
assertBodyThread();
|
||||
|
||||
StimBuffApiManager &sbam = getInstance();
|
||||
std::optional<sscl::co::CoQutex::ReleaseHandle> sbamGuard;
|
||||
if (acquireSbamLock)
|
||||
std::optional<sscl::co::CoQutex::ReleaseHandle> listGuard;
|
||||
if (acquireListLock)
|
||||
{
|
||||
sbamGuard.emplace(
|
||||
co_await sbam.s.lock.getAcquireInvocationAndSuspensionPolicy());
|
||||
listGuard.emplace(
|
||||
co_await s.lock.getAcquireInvocationAndSuspensionPolicy());
|
||||
}
|
||||
|
||||
if (!lib.stimBuffApiDesc.sal_mgmt_libOps.initializeCInd)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": initializeCInd() is NULL for library '"
|
||||
+ lib.libraryPath + "'");
|
||||
+ lib.loadedSharedLibrary->libraryPath + "'");
|
||||
}
|
||||
|
||||
sscl::co::CoQutex::ReleaseHandle libGuard =
|
||||
@@ -330,29 +258,28 @@ StimBuffApiManager::initializeStimBuffApiLibCReq(
|
||||
|
||||
body::BodyViralPostingInvoker<void>
|
||||
StimBuffApiManager::finalizeStimBuffApiLibCReq(
|
||||
StimBuffApiLib &lib, bool acquireSbamLock)
|
||||
StimBuffApiLib& lib, bool acquireListLock)
|
||||
{
|
||||
assertBodyThread();
|
||||
|
||||
StimBuffApiManager &sbam = getInstance();
|
||||
std::optional<sscl::co::CoQutex::ReleaseHandle> sbamGuard;
|
||||
if (acquireSbamLock)
|
||||
std::optional<sscl::co::CoQutex::ReleaseHandle> listGuard;
|
||||
if (acquireListLock)
|
||||
{
|
||||
sbamGuard.emplace(
|
||||
co_await sbam.s.lock.getAcquireInvocationAndSuspensionPolicy());
|
||||
listGuard.emplace(
|
||||
co_await s.lock.getAcquireInvocationAndSuspensionPolicy());
|
||||
}
|
||||
|
||||
if (!lib.stimBuffApiDesc.sal_mgmt_libOps.finalizeCInd)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": finalizeCInd() is NULL for library '"
|
||||
+ lib.libraryPath + "'");
|
||||
+ lib.loadedSharedLibrary->libraryPath + "'");
|
||||
}
|
||||
|
||||
sscl::co::CoQutex::ReleaseHandle libGuard =
|
||||
co_await lib.s.lock.getAcquireInvocationAndSuspensionPolicy();
|
||||
|
||||
lib.isBeingDestroyed.store(true);
|
||||
lib.loadedSharedLibrary->isBeingDestroyed.store(true);
|
||||
co_await lib.stimBuffApiDesc.sal_mgmt_libOps.finalizeCInd();
|
||||
|
||||
co_return;
|
||||
@@ -363,11 +290,10 @@ StimBuffApiManager::initializeAllStimBuffApiLibsCReq()
|
||||
{
|
||||
assertBodyThread();
|
||||
|
||||
StimBuffApiManager &sbam = getInstance();
|
||||
sscl::co::CoQutex::ReleaseHandle sbamGuard =
|
||||
co_await sbam.s.lock.getAcquireInvocationAndSuspensionPolicy();
|
||||
sscl::co::CoQutex::ReleaseHandle listGuard =
|
||||
co_await s.lock.getAcquireInvocationAndSuspensionPolicy();
|
||||
|
||||
for (auto &lib : sbam.s.rsrc.stimBuffApiLibs) {
|
||||
for (auto& lib : s.rsrc.libs) {
|
||||
co_await initializeStimBuffApiLibCReq(*lib, false);
|
||||
}
|
||||
|
||||
@@ -379,17 +305,15 @@ StimBuffApiManager::finalizeAllStimBuffApiLibsCReq()
|
||||
{
|
||||
assertBodyThread();
|
||||
|
||||
StimBuffApiManager &sbam = getInstance();
|
||||
sscl::co::CoQutex::ReleaseHandle sbamGuard =
|
||||
co_await sbam.s.lock.getAcquireInvocationAndSuspensionPolicy();
|
||||
sscl::co::CoQutex::ReleaseHandle listGuard =
|
||||
co_await s.lock.getAcquireInvocationAndSuspensionPolicy();
|
||||
|
||||
for (auto &lib : sbam.s.rsrc.stimBuffApiLibs) {
|
||||
for (auto& lib : s.rsrc.libs) {
|
||||
co_await finalizeStimBuffApiLibCReq(*lib, false);
|
||||
}
|
||||
|
||||
co_return;
|
||||
}
|
||||
|
||||
|
||||
} // namespace stim_buff
|
||||
} // namespace smo
|
||||
|
||||
Reference in New Issue
Block a user