Skip to content

Commit 3bb586c

Browse files
reimplement plugin subsystem
1 parent c5532f9 commit 3bb586c

8 files changed

Lines changed: 190 additions & 128 deletions

File tree

include/machine.hh

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33

44
#include <memory>
55
#include <string>
6+
#include <utility>
67

78
#include "config.hh"
89
#include "cpu_state.hh"
910
#include "elf_loader.hh"
1011
#include "executors.hh"
12+
#include "machine_event.hh"
1113
#include "memory.hh"
12-
#include "plugin_manager.hh"
1314

1415
namespace hsim {
1516

@@ -34,15 +35,16 @@ class Machine final {
3435
}
3536
}
3637

37-
void loadPlugin(const std::string &pluginPath,
38-
const std::string &options = "") {
39-
m_plugins.loadPlugin(pluginPath, options);
38+
void addEventConsumer(IEventConsumerHandle consumer) {
39+
m_eventManager.attach(std::move(consumer));
4040
}
4141

42+
void notify() { m_eventManager.notify(); }
43+
4244
private:
4345
std::unique_ptr<CpuState> m_state;
4446
Memory m_mem{};
45-
PluginManager m_plugins;
47+
EventManager m_eventManager;
4648
};
4749

4850
} // namespace hsim

include/machine_event.hh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#ifndef HSIM_MACHINE_EVENT_INCLUDED
2+
#define HSIM_MACHINE_EVENT_INCLUDED
3+
4+
#include <list>
5+
#include <memory>
6+
#include <utility>
7+
8+
namespace hsim {
9+
10+
class IEventConsumer {
11+
public:
12+
virtual ~IEventConsumer() = default;
13+
virtual void update() = 0;
14+
};
15+
16+
using IEventConsumerHandle = std::unique_ptr<IEventConsumer>;
17+
class EventManager final {
18+
public:
19+
void notify() {
20+
for (auto &consumer : m_consumers) {
21+
consumer->update();
22+
}
23+
}
24+
void attach(IEventConsumerHandle consumer) {
25+
m_consumers.push_back(std::move(consumer));
26+
}
27+
void detach(IEventConsumerHandle consumer) { m_consumers.remove(consumer); }
28+
29+
private:
30+
std::list<IEventConsumerHandle> m_consumers; // unique?
31+
};
32+
33+
} // namespace hsim
34+
35+
#endif // HSIM_MACHINE_EVENT_INCLUDED

include/plugin.hh

Lines changed: 66 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,84 @@
11
#ifndef HSIM_PLUGIN_INCLUDED
22
#define HSIM_PLUGIN_INCLUDED
33

4-
#include <stdexcept>
4+
#include <filesystem>
5+
#include <memory>
56
#include <string>
7+
#include <utility>
68

79
#include <dlfcn.h>
810

9-
#include "plugin_api.hh"
11+
#include "machine_event.hh"
12+
#include "so_loader.hh"
1013

1114
namespace hsim {
1215

13-
class Plugin final {
16+
class IPlugin : public IEventConsumer {
1417
public:
15-
Plugin(const std::string &pluginPath, const std::string &options = "")
16-
: m_pluginName{pluginPath}, m_options{options} {
17-
m_dlhandle = dlopen(pluginPath.c_str(), RTLD_NOW);
18-
if (m_dlhandle == nullptr) {
19-
std::string dlErrorMsg = dlerror();
20-
std::string fullErrorMsg = "Unable to load plugin: " + pluginPath +
21-
". Error: " + dlErrorMsg;
22-
throw std::runtime_error(fullErrorMsg);
23-
}
24-
25-
auto loadFunc = reinterpret_cast<LoadFunc>(
26-
dlsym(m_dlhandle, kLoadFuncName.c_str()));
27-
if (loadFunc == nullptr) {
28-
std::string dlErrorMsg = dlerror();
29-
std::string fullErrorMsg =
30-
"Unable to load : " + pluginPath + ". Error: " + dlErrorMsg;
31-
throw std::runtime_error(fullErrorMsg);
32-
}
33-
34-
LoadablePlugin plugin = loadFunc(options.c_str());
35-
m_pluginMem = plugin.pluginMem;
36-
m_notify = plugin.notify;
37-
m_unload = plugin.unload;
38-
}
39-
40-
~Plugin() {
41-
m_unload(m_pluginMem);
42-
43-
dlclose(m_dlhandle);
44-
}
45-
46-
void notify() { m_notify(m_pluginMem); }
18+
IPlugin(SharedLib so_lib) : m_sharedLib(std::move(so_lib)) {}
19+
~IPlugin() override = default;
20+
SharedLib getSOLib() { return m_sharedLib; }
4721

4822
private:
49-
std::string m_pluginName;
50-
std::string m_options;
51-
52-
void *m_dlhandle;
53-
void *m_pluginMem;
54-
NotifyFunc m_notify;
55-
UnloadFunc m_unload;
23+
SharedLib m_sharedLib;
5624
};
5725

26+
using LoadPLuginFunc = hsim::IPlugin *(*)(const char *options,
27+
SharedLib so_lib);
28+
29+
// using IPluginHandler = std::unique_ptr<IPlugin, void (*)(IPlugin*)>;
30+
// auto loadPluginFromSO(const std::filesystem::path& path, const std::string&
31+
// options) {
32+
// SharedLib sharedLib{path, kLazy};
33+
// auto loadPluginFunc = sharedLib.get<LoadPLuginFunc>("loadPlugin");
34+
//
35+
// // NOTE reason for custom deleter:
36+
// // when ~IPlugin is called it first calls ~SharedLib and then
37+
// ~SimplePlugin(wich is already unloaded) auto pluginDeleter = [lib =
38+
// SharedLib{sharedLib}](IPlugin* plugin) mutable { delete plugin; };
39+
40+
// IPlugin* plugin = loadPluginFunc(options.c_str(), sharedLib);
41+
// return std::unique_ptr<IPlugin, decltype(pluginDeleter)>{plugin,
42+
// pluginDeleter};
43+
// }
44+
45+
// // NOTE reason for custom deleter:
46+
// // when ~IPlugin is called it first calls ~SharedLib and then
47+
// ~SimplePlugin(wich is already unloaded) void ipluginDeleter(IPlugin* plugin)
48+
// {
49+
// SharedLib soLib = plugin->getSOLib();
50+
// soLib.~SharedLib();
51+
// }
52+
53+
// using IPluginHandler = std::unique_ptr<IPlugin, void (*)(IPlugin*)>;
54+
// IPluginHandler loadPluginFromSO(const std::filesystem::path& path, const
55+
// std::string& options) {
56+
// SharedLib sharedLib{path, kLazy};
57+
// auto loadPluginFunc = sharedLib.get<LoadPLuginFunc>("loadPlugin");
58+
//
59+
// IPlugin* plugin = loadPluginFunc(options.c_str(), sharedLib);
60+
// return IPluginHandler{plugin, ipluginDeleter};
61+
// }
62+
63+
// using IPluginHandler = std::unique_ptr<IPlugin>;
64+
// IPluginHandler loadPluginFromSO(const std::filesystem::path& path, const
65+
// std::string& options) {
66+
// SharedLib sharedLib{path, kLazy};
67+
// auto loadPluginFunc = sharedLib.get<LoadPLuginFunc>("loadPlugin");
68+
//
69+
// IPlugin* plugin = loadPluginFunc(options.c_str(), sharedLib);
70+
// return IPluginHandler{plugin};
71+
// }
72+
73+
using IPluginHandler = std::unique_ptr<IPlugin>;
74+
IPluginHandler loadPluginFromSO(SharedLib sharedLib,
75+
const std::string &options) {
76+
auto loadPluginFunc = sharedLib.get<LoadPLuginFunc>("loadPlugin");
77+
78+
IPlugin *plugin = loadPluginFunc(options.c_str(), sharedLib);
79+
return IPluginHandler{plugin};
80+
}
81+
5882
} // namespace hsim
5983

6084
#endif // HSIM_PLUGIN_INCLUDED

include/plugin_api.hh

Lines changed: 0 additions & 30 deletions
This file was deleted.

include/plugin_manager.hh

Lines changed: 0 additions & 30 deletions
This file was deleted.

include/so_loader.hh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#ifndef HSIM_SO_LOADER_INCLUDED
2+
#define HSIM_SO_LOADER_INCLUDED
3+
4+
#include <cstdint>
5+
#include <filesystem>
6+
#include <memory>
7+
#include <stdexcept>
8+
#include <string>
9+
10+
#include <dlfcn.h>
11+
12+
namespace hsim {
13+
14+
enum SharedLibMode : std::uint16_t {
15+
kLazy = RTLD_LAZY,
16+
kNow = RTLD_NOW,
17+
kGlobal = RTLD_GLOBAL,
18+
kLocal = RTLD_LOCAL,
19+
};
20+
21+
class SharedLib {
22+
public:
23+
SharedLib(const std::filesystem::path &libPath, SharedLibMode mode)
24+
: m_handle{dlopen(libPath.c_str(), mode), [](void *handle) {
25+
if (handle != nullptr) {
26+
dlclose(handle);
27+
}
28+
}} {
29+
if (m_handle == nullptr) {
30+
throw std::runtime_error{dlerror()};
31+
}
32+
}
33+
template <typename T> T get(const std::string &symbol) {
34+
void *loadedSymbol = dlsym(m_handle.get(), symbol.c_str());
35+
if (loadedSymbol == nullptr) {
36+
throw std::runtime_error{dlerror()};
37+
}
38+
39+
return reinterpret_cast<T>(loadedSymbol);
40+
}
41+
42+
private:
43+
std::shared_ptr<void> m_handle;
44+
};
45+
46+
} // namespace hsim
47+
48+
#endif // HSIM_SO_LOADER_INCLUDED

plugins/simple_plugin.cc

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
1-
#include "plugin_api.hh"
2-
31
#include <iostream>
2+
#include <string>
3+
#include <utility>
44

5-
void notify(void* pluginMem);
6-
void unload(void* pluginMem);
5+
#include "plugin.hh"
6+
#include "so_loader.hh"
77

8-
HSIM_PLUGIN_API_ATTR hsim::LoadablePlugin loadPlugin([[maybe_unused]] const char* options) {
9-
hsim::LoadablePlugin plugin = {};
10-
plugin.pluginMem = nullptr;
11-
plugin.notify = notify;
12-
plugin.unload = unload;
8+
class SimplePlugin : public hsim::IPlugin {
9+
public:
10+
SimplePlugin(std::string name, hsim::SharedLib so_lib)
11+
: IPlugin{std::move(so_lib)}, m_name{std::move(name)} {
12+
std::cout << "SimplePlugin: " << m_name << std::endl;
13+
}
1314

14-
std::cout << "load plugin" << std::endl;
15+
~SimplePlugin() override {
16+
std::cout << "~SimplePlugin: " << m_name << std::endl;
17+
}
1518

16-
return plugin;
17-
}
19+
void update() override {
20+
std::cout << "SimplePlugin name is : " << m_name << std::endl;
21+
}
1822

19-
void notify([[maybe_unused]] void* pluginMem) {
20-
std::cout << "notify plugin" << std::endl;
21-
}
23+
private:
24+
std::string m_name;
25+
};
2226

23-
void unload([[maybe_unused]] void* pluginMem) {
24-
std::cout << "unload plugin" << std::endl;
25-
}
27+
extern "C" hsim::IPlugin *loadPlugin(const char *options,
28+
hsim::SharedLib so_lib) {
29+
return new SimplePlugin{options, std::move(so_lib)};
30+
}

src/main.cc

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
#include <exception>
12
#include <iostream>
2-
#include <stdexcept>
3+
#include <utility>
34
//
45
#include <CLI/CLI.hpp>
56

67
#include "config.hh"
78
#include "machine.hh"
9+
#include "plugin.hh"
10+
#include "so_loader.hh"
811

912
int main(int argc, char **argv) try {
1013
CLI::App app("hSim: high Performance CPU Simulator");
@@ -30,10 +33,15 @@ int main(int argc, char **argv) try {
3033
//
3134
hsim::Machine machine{config};
3235

33-
// machine.loadPlugin("./build/plugins/libsimple_plugin.so");
34-
3536
machine.run();
3637

38+
// hsim::SharedLib sharedLib{"./build/plugins/libsimple_plugin.so",
39+
// hsim::kLazy};
40+
41+
// auto plugin = hsim::loadPluginFromSO(sharedLib, "vova");
42+
// machine.addEventConsumer(std::move(plugin));
43+
// machine.notify();
44+
3745
return 0;
3846
} catch (const std::exception &e) {
3947
std::cout << e.what() << '\n';

0 commit comments

Comments
 (0)