Skip to content

Commit

Permalink
[WASI Threads] Add pulgin
Browse files Browse the repository at this point in the history
Signed-off-by: Sylveon <sylveon@secondstate.io>
  • Loading branch information
LFsWang committed May 17, 2023
1 parent 44a487a commit 1453884
Show file tree
Hide file tree
Showing 12 changed files with 341 additions and 0 deletions.
27 changes: 27 additions & 0 deletions include/host/mock/wasi_threads_func.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

#pragma once

#include "common/errcode.h"
#include "host/mock/log.h"
#include "runtime/callingframe.h"
#include "runtime/hostfunc.h"

namespace WasmEdge {
namespace Host {
namespace WasiThreadsMock {

using namespace std::literals;

class ThreadSpawn : public Runtime::HostFunction<ThreadSpawn> {
public:
Expect<void> body(const Runtime::CallingFrame &, uint32_t) {
printPluginMock("Wasi-Threads"sv);
return Unexpect(ErrCode::Value::HostFuncError);
}
};

} // namespace WasiThreadsMock
} // namespace Host
} // namespace WasmEdge
22 changes: 22 additions & 0 deletions include/host/mock/wasi_threads_module.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

#pragma once

#include "host/mock/wasi_threads_func.h"
#include "runtime/instance/module.h"

namespace WasmEdge {
namespace Host {

class WasiThreadsModuleMock : public Runtime::Instance::ModuleInstance {
public:
WasiThreadsModuleMock()
: Runtime::Instance::ModuleInstance("wasi") {
addHostFunc("wasi_thread_spawn",
std::make_unique<WasiThreadsMock::ThreadSpawn>());
}
};

} // namespace Host
} // namespace WasmEdge
4 changes: 4 additions & 0 deletions lib/vm/vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "host/mock/wasi_nn_module.h"
#include "host/mock/wasmedge_httpsreq_module.h"
#include "host/mock/wasmedge_process_module.h"
#include "host/mock/wasi_threads_module.h"

namespace WasmEdge {
namespace VM {
Expand Down Expand Up @@ -89,6 +90,8 @@ void VM::unsafeLoadPlugInHosts() {
"wasi_crypto"sv, "wasi_crypto_symmetric"sv));
PlugInModInsts.push_back(createPluginModule<Host::WasmEdgeProcessModuleMock>(
"wasmedge_process"sv, "wasmedge_process"sv));
PlugInModInsts.push_back(createPluginModule<Host::WasiThreadsModuleMock>(
"wasi_threads"sv, "wasi_threads"sv));
PlugInModInsts.push_back(createPluginModule<Host::WasmEdgeHttpsReqModuleMock>(
"wasmedge_httpsreq"sv, "wasmedge_httpsreq"sv));

Expand All @@ -99,6 +102,7 @@ void VM::unsafeLoadPlugInHosts() {
}
// Skip WasmEdge_Process, WasmEdge_HttpsReq, wasi_nn, and wasi_crypto.
if (Plugin.name() == "wasmedge_process"sv ||
Plugin.name() == "wasi_threads"sv ||
Plugin.name() == "wasmedge_httpsreq"sv ||
Plugin.name() == "wasi_nn"sv || Plugin.name() == "wasi_crypto"sv) {
continue;
Expand Down
1 change: 1 addition & 0 deletions plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ if(WASMEDGE_PLUGIN_PROCESS)
# Only Linux systems support wasmedge_process now.
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
add_subdirectory(wasmedge_process)
add_subdirectory(wasi_threads)
else()
message(WARNING "Only Linux platforms support WasmEdge_Process plug-in now.")
endif()
Expand Down
60 changes: 60 additions & 0 deletions plugins/wasi_threads/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: 2019-2022 Second State INC

wasmedge_add_library(wasmedgePluginWasiThreads
SHARED
threadfunc.cpp
threadmodule.cpp
)

target_compile_options(wasmedgePluginWasiThreads
PUBLIC
-DWASMEDGE_PLUGIN
)

if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
target_link_options(wasmedgePluginWasiThreads
PUBLIC
-Wl,-U,__ZN8WasmEdge6Plugin14PluginRegisterC1EPKNS0_6Plugin16PluginDescriptorE
-Wl,-U,__ZN8WasmEdge6Plugin14PluginRegisterD1Ev
)
endif()

target_include_directories(wasmedgePluginWasiThreads
PUBLIC
$<TARGET_PROPERTY:wasmedgePlugin,INCLUDE_DIRECTORIES>
)

target_link_libraries(wasmedgePluginWasiThreads
PUBLIC
wasmedgeExecutor
wasmedgeCommon
wasmedgeSystem
)

install(TARGETS wasmedgePluginWasiThreads DESTINATION ${CMAKE_INSTALL_LIBDIR}/wasmedge)

target_include_directories(wasmedgePluginWasiThreads
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)

target_link_libraries(wasmedgePluginWasiThreads
PUBLIC
wasmedgeExecutor
wasmedgeCommon
wasmedgeSystem
wasmedgePlugin
)

if(CMAKE_SYSTEM_NAME MATCHES "Linux")
target_link_options(wasmedgePluginWasiThreads
PUBLIC
-u_ZN8WasmEdge4Host6WasmEdgeThread17WasmEdgeThreadEnvironment8RegisterE
)
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
target_link_options(wasmedgePluginWasiThreads
PUBLIC
-u__ZN8WasmEdge4Host6WasmEdgeThread17WasmEdgeThreadEnvironment8RegisterE
)
endif()
23 changes: 23 additions & 0 deletions plugins/wasi_threads/base.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

#pragma once

#include "common/errcode.h"
#include "runtime/hostfunc.h"
#include "threadenv.h"

namespace WasmEdge {
namespace Host {

template <typename T> class WasiThreads : public Runtime::HostFunction<T> {
public:
WasiThreads(WasiThreadsEnvironment &HostEnv)
: Runtime::HostFunction<T>(0), Env(HostEnv) {}

protected:
WasiThreadsEnvironment &Env;
};

} // namespace Host
} // namespace WasmEdge
36 changes: 36 additions & 0 deletions plugins/wasi_threads/threadenv.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

#include "threadenv.h"
#include "threadmodule.h"

#include <thread>

namespace WasmEdge {
namespace Host {

Runtime::Instance::ModuleInstance *create(void) noexcept {
return new WasiThreadsModule;
}

Plugin::Plugin::PluginDescriptor Descriptor{
.Name = "wasi_threads",
.Description = "",
.APIVersion = Plugin::Plugin::CurrentAPIVersion,
.Version = {0, 10, 1, 0},
.ModuleCount = 1,
.ModuleDescriptions =
(Plugin::PluginModule::ModuleDescriptor[]){
{
.Name = "wasi_threads",
.Description = "",
.Create = wasi_threads,
},
},
.AddOptions = nullptr,
};

Plugin::PluginRegister WasiThreadsEnvironment::Register(&Descriptor);

} // namespace Host
} // namespace WasmEdge
87 changes: 87 additions & 0 deletions plugins/wasi_threads/threadenv.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

#pragma once

#include "plugin/plugin.h"
#include "vm/vm.h"
#include "common/log.h"

#include <cstdint>
#include <mutex>
#include <random>
#include <shared_mutex>
#include <unordered_map>
#include <vector>

namespace WasmEdge {
namespace Host {

using wasmedge_tid_t = uint32_t;
class TidManager {
public:
/// @brief Tid is in [1, 2**29], 0 is reserved
const static wasmedge_tid_t MinTid = 1;
const static wasmedge_tid_t MaxTid = 1 << 29;

TidManager() : Mutex(), Distribution(MinTid, MaxTid), Engine(), TidMap() {
std::random_device Device;

if (Device.entropy() == 0) {
spdlog::warn("Quality of random device is bad");
}

Engine.seed(Device());
}

wasmedge_tid_t allocate(std::shared_ptr<std::thread> Thread) {
std::unique_lock Lock(Mutex);

wasmedge_tid_t NewTid;
bool Success = false;

while (!Success) {
NewTid = Distribution(Engine);
Success = TidMap.find(NewTid) == TidMap.end();
}

TidMap.emplace(NewTid, Thread);
return NewTid;
}

Expect<void> free(wasmedge_tid_t Tid) noexcept {
std::unique_lock Lock(Mutex);

if (auto It = TidMap.find(Tid); It == TidMap.end()) {
return Unexpect(ErrCode::Value::HostFuncError);
} else {
TidMap.erase(It);
return {};
}
}

private:
mutable std::shared_mutex Mutex;

std::uniform_int_distribution<wasmedge_tid_t> Distribution;
std::default_random_engine Engine;
std::unordered_map<wasmedge_tid_t, std::shared_ptr<std::thread>> TidMap;
};

class WasiThreadsEnvironment {
public:
WasiThreadsEnvironment() noexcept {}
~WasiThreadsEnvironment() noexcept {}

Expect<wasmedge_tid_t> threadCreate(Executor::Executor *Exec,
uint32_t ThreadFunc, uint32_t Arg);
Expect<void> threadJoin(wasmedge_tid_t Tid, void **WasiRetval);

static Plugin::PluginRegister Register;

private:
TidManager Manager;
};

} // namespace Host
} // namespace WasmEdge
17 changes: 17 additions & 0 deletions plugins/wasi_threads/threadfunc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

#include "threadfunc.h"
#include "common/log.h"

namespace WasmEdge {
namespace Host {

Expect<uint32_t> WasiThreadSpawn::body( [[maybe_unused]] const Runtime::CallingFrame &Frame,
[[maybe_unused]] uint32_t ThreadStartArg) {

return {0};
}

} // namespace Host
} // namespace WasmEdge
23 changes: 23 additions & 0 deletions plugins/wasi_threads/threadfunc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

#pragma once

#include "runtime/instance/memory.h"
#include "base.h"

#include <cstdint>

namespace WasmEdge {
namespace Host {

class WasiThreadSpawn : public WasiThreads<WasiThreadSpawn> {
public:
WasiThreadSpawn(WasiThreadsEnvironment &HostEnv)
: WasiThreads(HostEnv) {}

Expect<uint32_t> body(const Runtime::CallingFrame &Frame, uint32_t ThreadStartArg);
};

} // namespace Host
} // namespace WasmEdge
16 changes: 16 additions & 0 deletions plugins/wasi_threads/threadmodule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

#include "threadmodule.h"
#include "threadfunc.h"

namespace WasmEdge {
namespace Host {

WasiThreadsModule::WasiThreadsModule()
: ModuleInstance("wasi") {
addHostFunc("thread_spawn", std::make_unique<WasiThreadSpawn>(Env));
}

} // namespace Host
} // namespace WasmEdge
25 changes: 25 additions & 0 deletions plugins/wasi_threads/threadmodule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2022 Second State INC

#pragma once

#include "runtime/instance/module.h"
#include "threadenv.h"
#include "base.h"

namespace WasmEdge {
namespace Host {

class WasiThreadsModule : public Runtime::Instance::ModuleInstance {
public:
WasiThreadsModule();

WasiThreadsEnvironment &getEnv() noexcept { return Env; }
const WasiThreadsEnvironment &getEnv() const noexcept { return Env; }

private:
WasiThreadsEnvironment Env;
};

} // namespace Host
} // namespace WasmEdge

0 comments on commit 1453884

Please sign in to comment.