diff --git a/CMakeLists.txt b/CMakeLists.txt index 59a083b..ab75262 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,7 +204,7 @@ if((NOT TILE_HAVE_GETIFADDRS) OR (NOT TILE_HAVE_FREEIFADDRS)) list(APPEND TILE_SRCS "tile/base/net/detail/android/ifaddrs.c") endif() -add_library(tile OBJECT ${TILE_SRCS} ${ASM_SRCS}) +add_library(tile OBJECT ${TILE_SRCS}) set_target_properties(tile PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION "${tile_VERSION_MAJRO}") # target_sources(tile PRIVATE ${TILE_SRCS}) diff --git a/third_party/context/CMakeLists.txt b/third_party/context/CMakeLists.txt index 5174108..cf8db97 100644 --- a/third_party/context/CMakeLists.txt +++ b/third_party/context/CMakeLists.txt @@ -10,7 +10,7 @@ cmake_minimum_required(VERSION 3.5...3.16) project( nova_context VERSION 0.1.0 - LANGUAGES C) + LANGUAGES C ASM) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) @@ -197,6 +197,7 @@ set(ASM_SRC unset(_asm_suffix) +set_source_files_properties(${ASM_SRC} PROPERTIES LINKER_LANGUAGE C) # POWERPC_32/SYSV Special case: https://github.com/boostorg/context/issues/120 if((NOVA_CONTEXT_ARCHITECTURE STREQUAL ppc32) AND (NOVA_CONTEXT_ABI STREQUAL sysv)) @@ -210,8 +211,8 @@ if(NOVA_CONTEXT_ASSEMBLER STREQUAL masm AND NOVA_CONTEXT_ARCHITECTURE STREQUAL endif() if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) - set_source_files_properties(${ASM_SRC} PROPERTIES COMPILE_OPTIONS - "-x assembler-with-cpp") + # set_source_files_properties(${ASM_SRC} PROPERTIES COMPILE_OPTIONS + # "-x assembler-with-cpp") endif() # Boost specific definitions diff --git a/tile/base/internal/format.h b/tile/base/internal/format.h index 70027e4..80a5e6d 100644 --- a/tile/base/internal/format.h +++ b/tile/base/internal/format.h @@ -57,6 +57,13 @@ auto format_as(const T &val) return val.ToString(); } +template +auto format_as(T *ptr) + -> tile::enable_if_t>::value, + void *> { + return reinterpret_cast(ptr); +} + #define TILE_INSTANCE_CHRONO_FORMAT_AS(type, suffix) \ inline std::string format_as(const type &val) { \ return tile::detail::format_as_impl(val, suffix); \ @@ -80,4 +87,17 @@ TILE_INSTANCE_CHRONO_FORMAT_AS(std::chrono::years, "y") #include "fmt/format.h" #include "fmt/ostream.h" +inline std::ostream &operator<<(std::ostream &os, std::nullptr_t) { + return os << "nullptr"; +} + +// template ::value && +// !std::is_same, +// std::nullptr_t>::value>> +// std::ostream &operator<<(std::ostream &os, T *ptr) { +// return os << fmt::format("{}", fmt::ptr(ptr)); +// } + #endif // TILE_BASE_INTERNAL_FORMAT_H diff --git a/tile/fiber/detail/fiber.cc b/tile/fiber/detail/fiber.cc index 7fa89b2..3aa3a06 100644 --- a/tile/fiber/detail/fiber.cc +++ b/tile/fiber/detail/fiber.cc @@ -16,32 +16,38 @@ namespace detail { static thread_local Fiber *tls_current_fiber = nullptr; static thread_local Fiber *tls_master_fiber = nullptr; -constexpr auto kStackSize = 8192; -constexpr auto kAlignSize = 16; +constexpr std::size_t kStackSize = 8192; +constexpr std::size_t kAlignSize = 16; -void RunProc(void *arg) { - auto proc = static_cast *>(arg); - if (proc) { - (*proc)(); +void FiberEntry(fcontext_transfer_t t) { + // TILE_LOG_INFO("FiberEntry creater {}, proc {}", t.fctx, t.data); + std::function *fn = static_cast *>(t.data); + TILE_CHECK_NE(t.data, nullptr); + TILE_CHECK_NE(t.fctx, nullptr); + try { + t = jump_fcontext(t.fctx, nullptr); + (*fn)(); + } catch (const std::exception &e) { + // TILE_LOG_ERROR("Exception caught in fiber: {}", e.what()); } - Fiber::MasterFiber()->Resume(); + TILE_CHECK_NE(t.fctx, nullptr); + // TILE_LOG_INFO("FiberEntry End. Resume to {}", t.fctx); + jump_fcontext(t.fctx, nullptr); } -void RunProc1(fcontext_transfer_t ft) { - auto t = jump_fcontext(ft.fctx, nullptr); +fcontext_t CreateFiber(void *stack, std::size_t stack_size, + std::function *fn) { + void *stack_top = static_cast(stack) + stack_size; + const fcontext_t fctx = make_fcontext(stack_top, stack_size, FiberEntry); + TILE_CHECK_NE(fctx, nullptr); - auto proc = static_cast *>(ft.data); - TILE_LOG_INFO("proc: {}", fmt::ptr(proc)); - if (proc) { - (*proc)(); - } - Fiber::MasterFiber()->Resume(); + return jump_fcontext(fctx, fn).fctx; } struct alignas(hardware_destructive_interference_size) Fiber::FiberContext { fcontext_t fctx; - // tile_ucontext_t uctx; std::aligned_storage::type stack; + std::function proc; }; Fiber *Fiber::Current() noexcept { return tls_current_fiber; } @@ -56,12 +62,13 @@ std::unique_ptr Fiber::Create(std::function proc) noexcept { } Fiber::Fiber(std::function proc) - : ctx_(object_pool::Get().Leak()), proc_(std::move(proc)) { + : ctx_(object_pool::Get().Leak()) { - // memset(&ctx_->uctx, 0, sizeof(tile_ucontext_t)); - // memset(&ctx_->stack, 0, kStackSize); - if (proc_) { - make_fcontext(&ctx_->stack, kStackSize, RunProc1); + ctx_->proc = std::move(proc); + if (ctx_->proc) { + ctx_->fctx = CreateFiber(&ctx_->stack, kStackSize, &ctx_->proc); + } else { + ctx_->fctx = nullptr; } } @@ -75,12 +82,14 @@ void Fiber::Resume() { auto caller = Current(); TILE_CHECK_NE(caller, this, "Can't `Resume()` self"); SetCurrent(this); - // tile_ucontext_swap(&caller->ctx_->uctx, &ctx_->uctx); - TILE_LOG_INFO("proc: {}", fmt::ptr(&proc_)); - jump_fcontext(ctx_->fctx, nullptr); + // TILE_LOG_INFO("Resume before proc: {}", fmt::ptr(&proc_)); + ctx_->fctx = jump_fcontext(ctx_->fctx, nullptr).fctx; + // TILE_LOG_INFO("Resume after proc: {}", fmt::ptr(&proc_)); SetCurrent(caller); } +void Fiber::Yield() {} + } // namespace detail } // namespace fiber diff --git a/tile/fiber/detail/fiber.h b/tile/fiber/detail/fiber.h index 6c903f7..8d83756 100644 --- a/tile/fiber/detail/fiber.h +++ b/tile/fiber/detail/fiber.h @@ -43,21 +43,20 @@ public: Fiber(Fiber &&other) noexcept = default; Fiber &operator=(Fiber &&other) noexcept = default; + // for `Scheduler` + void Resume(); + void Yield(); + private: TILE_FRIEND_TEST(Fiber, Base); - friend void RunProc(void *); - friend void RunProc1(struct fcontext_transfer); friend Scheduler; struct FiberContext; friend class ::tile::PoolTraits; Fiber(std::function proc = nullptr); - void Resume(); - private: std::unique_ptr ctx_; - std::function proc_; FiberState state_{Ready}; }; diff --git a/tile/fiber/detail/fiber_test.cc b/tile/fiber/detail/fiber_test.cc index 497b3c1..d431a9e 100644 --- a/tile/fiber/detail/fiber_test.cc +++ b/tile/fiber/detail/fiber_test.cc @@ -13,27 +13,19 @@ TEST(Fiber, Base) { // 0 -> master fiber // [1, 9] -> worker fibers - std::vector> fibers; - fibers.emplace_back(Fiber::Create()); - Fiber::SetMasterFiber(fibers[0].get()); - Fiber::SetCurrent(fibers[0].get()); - - for (int i = 1; i != 10; ++i) { - fibers.emplace_back(Fiber::Create([&, i] { - while (cnt < kMaxCnt) { - ASSERT_EQ(Fiber::Current(), fibers[i].get()); - ++cnt; - Fiber::MasterFiber()->Resume(); - } - })); - } + auto master_fiber = Fiber::Create(); + Fiber::SetMasterFiber(master_fiber.get()); + Fiber::SetCurrent(master_fiber.get()); while (cnt < kMaxCnt) { - int old = cnt; - auto next_fiber = fibers[Random(1, 9)].get(); + std::unique_ptr worker_fiber = Fiber::Create([&] { + ASSERT_EQ(Fiber::Current(), worker_fiber.get()); + ++cnt; + }); - next_fiber->Resume(); + int old = cnt; + worker_fiber->Resume(); ++resume_cnt; ASSERT_EQ(old + 1, cnt); ASSERT_EQ(Fiber::Current(), Fiber::MasterFiber());