Skip to content

Commit

Permalink
[onert] Introduce CodegenLoader class (#12536)
Browse files Browse the repository at this point in the history
This commit introduces CodegenLoader class.
This class loads the backend codegen library and provides a function
to get the concreate class of ICodegen class.

ONE-DCO-1.0-Signed-off-by: Jiyoung Yun <jy910.yun@samsung.com>
Co-authored-by: Sanggyu Lee <sg5.lee@samsung.com>
  • Loading branch information
jyoungyun and Sanggyu Lee committed Jan 30, 2024
1 parent 8185cb1 commit f03abf3
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 1 deletion.
2 changes: 1 addition & 1 deletion runtime/onert/core/include/odc/ICodegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class ICodegen
public:
virtual ~ICodegen() = default;

virtual int codegen(const char *in, const char *out) = 0;
virtual int codegen(const char *in, const char *out) const = 0;
};

} // namespace odc
Expand Down
87 changes: 87 additions & 0 deletions runtime/onert/core/src/odc/CodegenLoader.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "CodegenLoader.h"

#include <dlfcn.h>
#include <iostream>
#include <memory>

static const char *SHARED_LIB_EXT =
#if defined(__APPLE__) && defined(__MACH__)
".dylib";
#else
".so";
#endif

namespace onert
{
namespace odc
{

CodegenLoader &CodegenLoader::instance()
{
static CodegenLoader singleton;
return singleton;
}

void CodegenLoader::loadLibrary(const char *target)
{
if (get() != nullptr)
return;

const std::string codegen_so = "lib" + std::string{target} + SHARED_LIB_EXT;
void *handle = dlopen(codegen_so.c_str(), RTLD_LAZY | RTLD_LOCAL);
if (handle == nullptr)
{
throw std::runtime_error("CodegenLoader: " + std::string{dlerror()});
}

const auto factory = (factory_t)dlsym(handle, "create_codegen");
if (factory == nullptr)
{
const std::string dlerror_msg = dlerror();
dlclose(handle);
throw std::runtime_error("CodegenLoader: " + dlerror_msg);
}

const auto destroyer = (codegen_destory_t)dlsym(handle, "destroy_codegen");
_codegen = std::unique_ptr<ICodegen, codegen_destory_t>(factory(), destroyer);
if (_codegen == nullptr)
{
dlclose(handle);
throw std::runtime_error("CodegenLoader: unable to create codegen");
}

// Save backend handle (avoid warning by handle lost without dlclose())
_dlhandle = std::unique_ptr<void, dlhandle_destroy_t>{
handle, [filename = codegen_so](void *h) {
if (dlclose(h))
throw std::runtime_error("CodegenLoader: Failed to unload backend " + filename);
}};
}

void CodegenLoader::unloadLibrary()
{
if (get() == nullptr)
return;

_codegen.reset(nullptr);
_dlhandle.reset(nullptr);
}

} // namespace odc
} // namespace onert
96 changes: 96 additions & 0 deletions runtime/onert/core/src/odc/CodegenLoader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef __ONERT_ODC_CODEGEN_LOADER_H__
#define __ONERT_ODC_CODEGEN_LOADER_H__

#include "odc/ICodegen.h"

#include <functional>
#include <memory>

namespace onert
{
namespace odc
{

/**
* @brief Class to manage loading and unloading of dynamic library containing
* implementation of ICodegen interface.
*/
class CodegenLoader
{
public:
/**
* @brief Typedef for function pointer to destroy loaded library handle
*/
using dlhandle_destroy_t = std::function<void(void *)>;
/**
* @brief Typedef for function pointer to create instance of ICodegen
*/
using factory_t = ICodegen *(*)();
/**
* @brief Typedef for function pointer to destroy instance of ICodegen
*/
using codegen_destory_t = void (*)(ICodegen *);

/**
* @brief Get singleton instance of CodegenLoader
* @return Reference to singleton instance of CodegenLoader
*/
static CodegenLoader &instance();

// delete copy constructor and assignment operator
CodegenLoader(CodegenLoader const &) = delete;
CodegenLoader &operator=(CodegenLoader const &) = delete;

private:
// cannot create instance of CodegenLoader outside of this class
CodegenLoader() = default;
~CodegenLoader() = default;

public:
/**
* @brief Load dynamic library containing implementation of ICodegen
* @param[in] target Target backend name
* This target string will be used to find a backend library.
* The name of target backend library should follow the following rules:
* 'lib' + {backend extension} + '-gen' + {lib extension}
* And the target string should be a name except 'lib' and {lib extension}.
* For example, if the backend extension is 'aaa', the backend library name
* should be 'libaaa-gen.so', and the target string should be 'aaa-gen'.
*/
void loadLibrary(const char *target);
/**
* @brief Unload dynamic library containing implementation of ICodegen
*/
void unloadLibrary();
/**
* @brief Get instance of ICodegen created through factory method
* @return Pointer to instance of ICodegen
*/
const ICodegen *get() const { return _codegen.get(); }

private:
// Note: Keep handle to avoid svace warning of "handle lost without dlclose()"
std::unique_ptr<void, dlhandle_destroy_t> _dlhandle;
std::unique_ptr<ICodegen, codegen_destory_t> _codegen{nullptr, nullptr};
};

} // namespace odc
} // namespace onert

#endif // __ONERT_ODC_CODEGEN_LOADER_H__

0 comments on commit f03abf3

Please sign in to comment.