#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace smo { namespace stim_buff { namespace { void assertBodyThread() { auto self = sscl::ComponentThread::getSelf(); if (self->id != SmoThreadId::BODY) { throw std::runtime_error( std::string(__func__) + ": Must be executed on Body thread"); } } std::shared_ptr ComponentThread_getSelf() { return sscl::ComponentThread::getSelf(); } OptionParser& OptionParser_getOptions() { return OptionParser::getOptions(); } std::shared_ptr ComputeManager_createUseHostPtrBuffer( void* hostPtr, size_t size, cl_mem_flags flags) { return smo::compute::ComputeManager::getInstance().createUseHostPtrBuffer( hostPtr, size, flags); } void ComputeManager_releaseUseHostPtrBuffer( std::shared_ptr buffer) { smo::compute::ComputeManager::getInstance().releaseUseHostPtrBuffer( buffer); } std::shared_ptr ComputeManager_getDevice() { return smo::compute::ComputeManager::getInstance().getDevice(); } void ComputeManager_releaseDevice( std::shared_ptr device) { smo::compute::ComputeManager::getInstance().releaseDevice(device); } std::optional 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. */ SmoCallbacks smoCallbacks = { .searchForLibInSmoSearchPaths = searchForLibInSmoSearchPathsHook, .ComponentThread_getSelf = ComponentThread_getSelf, .OptionParser_getOptions = OptionParser_getOptions, .ComputeManager_createUseHostPtrBuffer = ComputeManager_createUseHostPtrBuffer, .ComputeManager_releaseUseHostPtrBuffer = ComputeManager_releaseUseHostPtrBuffer, .ComputeManager_getDevice = ComputeManager_getDevice, .ComputeManager_releaseDevice = ComputeManager_releaseDevice }; /* Static file-scope threading model object for senseApi libraries */ SmoThreadingModelDesc smoThreadingModelDesc = { .componentThread = nullptr }; } // namespace StimBuffApiLib& StimBuffApiManager::loadStimBuffApiLib( const std::string& libraryPath, const std::shared_ptr& componentThread) { loadable_lib::LoadableLibraryManager& llm = loadable_lib::LoadableLibraryManager::getInstance(); if (findStimBuffApiLibByLibraryPath(libraryPath)) { throw std::runtime_error( std::string(__func__) + ": StimBuffApiLib already loaded: " + libraryPath); } std::shared_ptr 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 = descFn( smoCallbacks, smoThreadingModelDesc); auto lib = std::make_shared(loadedLibrary, descFn); lib->setStimBuffApiDesc(libApiDesc); s.rsrc.libs.push_back(lib); return *lib; } std::optional> StimBuffApiManager::findStimBuffApiLibByLibraryPath( const std::string& libraryPath) { auto& libs = s.rsrc.libs; auto it = std::find_if( libs.begin(), libs.end(), [&libraryPath](const std::shared_ptr& lib) { return lib->loadedSharedLibrary->libraryPath == libraryPath; }); if (it != libs.end()) { return *it; } return std::nullopt; } std::optional> StimBuffApiManager::findStimBuffApiLibByApiName(const std::string& apiName) { auto& libs = s.rsrc.libs; auto it = std::find_if( libs.begin(), libs.end(), [&apiName](const std::shared_ptr& lib) { return lib->stimBuffApiDesc.name == apiName; }); if (it != libs.end()) { return *it; } return std::nullopt; } StimBuffApiLib& StimBuffApiManager::getStimBuffApiLibByApiName( const std::string& apiName) { auto libOpt = findStimBuffApiLibByApiName(apiName); if (!libOpt) { throw std::runtime_error( std::string(__func__) + ": No library for API '" + apiName + "'"); } return *libOpt.value(); } void StimBuffApiManager::unloadStimBuffApiLib(const std::string& libraryPath) { auto& libs = s.rsrc.libs; auto it = std::find_if( libs.begin(), libs.end(), [&libraryPath](const std::shared_ptr& lib) { return lib->loadedSharedLibrary->libraryPath == libraryPath; }); if (it == libs.end()) { std::cerr << std::string(__func__) + ": Library not found: " << libraryPath << '\n'; return; } std::shared_ptr loadedLibrary = (*it)->loadedSharedLibrary; libs.erase(it); loadable_lib::LoadableLibraryManager::getInstance() .unloadSharedLibrary(loadedLibrary); } void StimBuffApiManager::unloadAllStimBuffApiLibs(void) { 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& componentThread) { const auto& options = OptionParser::getOptions(); for (const auto& libPath : options.senseApiLibs) { loadStimBuffApiLib(libPath, componentThread); } } std::string StimBuffApiManager::stringifyLibs() const { std::string result; for (const auto& lib : s.rsrc.libs) { result += lib->stringify() + "\n"; } return result; } body::BodyViralPostingInvoker StimBuffApiManager::initializeStimBuffApiLibCReq( StimBuffApiLib& lib, bool acquireListLock) { assertBodyThread(); std::optional listGuard; if (acquireListLock) { 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.loadedSharedLibrary->libraryPath + "'"); } sscl::co::CoQutex::ReleaseHandle libGuard = co_await lib.s.lock.getAcquireInvocationAndSuspensionPolicy(); co_await lib.stimBuffApiDesc.sal_mgmt_libOps.initializeCInd(); co_return; } body::BodyViralPostingInvoker StimBuffApiManager::finalizeStimBuffApiLibCReq( StimBuffApiLib& lib, bool acquireListLock) { assertBodyThread(); std::optional listGuard; if (acquireListLock) { 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.loadedSharedLibrary->libraryPath + "'"); } sscl::co::CoQutex::ReleaseHandle libGuard = co_await lib.s.lock.getAcquireInvocationAndSuspensionPolicy(); lib.loadedSharedLibrary->isBeingDestroyed.store(true); co_await lib.stimBuffApiDesc.sal_mgmt_libOps.finalizeCInd(); co_return; } body::BodyViralPostingInvoker StimBuffApiManager::initializeAllStimBuffApiLibsCReq() { assertBodyThread(); sscl::co::CoQutex::ReleaseHandle listGuard = co_await s.lock.getAcquireInvocationAndSuspensionPolicy(); for (auto& lib : s.rsrc.libs) { co_await initializeStimBuffApiLibCReq(*lib, false); } co_return; } body::BodyViralPostingInvoker StimBuffApiManager::finalizeAllStimBuffApiLibsCReq() { assertBodyThread(); sscl::co::CoQutex::ReleaseHandle listGuard = co_await s.lock.getAcquireInvocationAndSuspensionPolicy(); for (auto& lib : s.rsrc.libs) { co_await finalizeStimBuffApiLibCReq(*lib, false); } co_return; } } // namespace stim_buff } // namespace smo