diff --git a/CMakeLists.txt b/CMakeLists.txt index 089592f0..e0448b1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ unset(_default_abi) ## Arch-and-model -set(_all_archs arm arm64 loongarch64 mips32 mips64 ppc32 ppc64 riscv64 s390x i386 x86_64 combined) +set(_all_archs arm arm64 e2k loongarch64 mips32 mips64 ppc32 ppc64 riscv64 s390x i386 x86_64 combined) # Try at start to auto determine arch from CMake. if(CMAKE_SYSTEM_PROCESSOR IN_LIST _all_archs) @@ -69,6 +69,8 @@ else() if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "^[Aa][Rr][Mm]") # armv8 set(_default_arch arm64) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^[Ee]2[Kk]") + set(_default_arch e2k) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") set(_default_arch mips64) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc64)") @@ -78,7 +80,7 @@ else() endif() endif() -set(BOOST_CONTEXT_ARCHITECTURE "${_default_arch}" CACHE STRING "Boost.Context architecture (arm, arm64, loongarch64, mips32, mips64, ppc32, ppc64, riscv64, s390x, i386, x86_64, combined)") +set(BOOST_CONTEXT_ARCHITECTURE "${_default_arch}" CACHE STRING "Boost.Context architecture (arm, arm64, e2k, loongarch64, mips32, mips64, ppc32, ppc64, riscv64, s390x, i386, x86_64, combined)") set_property(CACHE BOOST_CONTEXT_ARCHITECTURE PROPERTY STRINGS ${_all_archs}) unset(_all_archs) @@ -123,7 +125,11 @@ unset(_default_ext) ## Implementation -set(_default_impl fcontext) +if(BOOST_CONTEXT_ARCHITECTURE STREQUAL e2k) + set(_default_impl ucontext) +else() + set(_default_impl fcontext) +endif() set(BOOST_CONTEXT_IMPLEMENTATION "${_default_impl}" CACHE STRING "Boost.Context implementation (fcontext, ucontext, winfib)") set_property(CACHE BOOST_CONTEXT_IMPLEMENTATION PROPERTY STRINGS fcontext ucontext winfib) diff --git a/include/boost/context/continuation_ucontext.hpp b/include/boost/context/continuation_ucontext.hpp index 5b632dc9..3e3ef0f3 100644 --- a/include/boost/context/continuation_ucontext.hpp +++ b/include/boost/context/continuation_ucontext.hpp @@ -108,6 +108,11 @@ struct BOOST_CONTEXT_DECL activation_record { } virtual ~activation_record() { +#ifdef __e2k__ + // On the e2k arch makecontext() is a real syscall that allocates memory + // so ucontext_t objects should be freed + ::freecontext_e2k( & uctx); +#endif } activation_record( activation_record const&) = delete; @@ -312,8 +317,21 @@ static activation_record * create_context1( StackAlloc && salloc, Fn && fn) { std::uint32_t((integer >> 32) & 0xFFFFFFFF), std::uint32_t(integer)); #else +#ifndef __e2k__ ::makecontext(&record->uctx, (void (*)()) & entry_func, 1, record); +#else + // On the e2k arch makecontext() allocates memory and thus may fail due to OOM + // We have to check for the returning value + int mc_ret = ::makecontext_e2k(&record->uctx, (void (*)()) & entry_func, + 1, record); + if (BOOST_UNLIKELY(mc_ret < 0)) { + record->~capture_t(); + salloc.deallocate( sctx); + throw std::system_error(std::error_code(errno, std::system_category()), + "makecontext_e2k() failed"); + } +#endif // __e2k__ #endif #if defined(BOOST_USE_ASAN) record->stack_bottom = record->uctx.uc_stack.ss_sp; @@ -355,8 +373,21 @@ static activation_record * create_context2( preallocated palloc, StackAlloc && s std::uint32_t((integer >> 32) & 0xFFFFFFFF), std::uint32_t(integer)); #else +#ifndef __e2k__ ::makecontext(&record->uctx, (void (*)()) & entry_func, 1, record); +#else + // On the e2k arch makecontext() allocates memory and thus may fail due to OOM + // We have to check for the returning value + int mc_ret = ::makecontext_e2k(&record->uctx, (void (*)()) & entry_func, + 1, record); + if (BOOST_UNLIKELY(mc_ret < 0)) { + record->~capture_t(); + salloc.deallocate( palloc.sctx); + throw std::system_error(std::error_code(errno, std::system_category()), + "makecontext_e2k() failed"); + } +#endif // __e2k__ #endif #if defined(BOOST_USE_ASAN) record->stack_bottom = record->uctx.uc_stack.ss_sp; diff --git a/include/boost/context/fiber_ucontext.hpp b/include/boost/context/fiber_ucontext.hpp index 687e1c29..1859c5ac 100644 --- a/include/boost/context/fiber_ucontext.hpp +++ b/include/boost/context/fiber_ucontext.hpp @@ -123,6 +123,11 @@ struct BOOST_CONTEXT_DECL fiber_activation_record { } virtual ~fiber_activation_record() { +#ifdef __e2k__ + // On the e2k arch makecontext() is a real syscall that allocates memory + // so ucontext_t objects should be freed + ::freecontext_e2k( & uctx); +#endif #if defined(BOOST_USE_TSAN) if (destroy_tsan_fiber) __tsan_destroy_fiber(tsan_fiber); @@ -342,8 +347,21 @@ static fiber_activation_record * create_fiber1( StackAlloc && salloc, Fn && fn) std::uint32_t((integer >> 32) & 0xFFFFFFFF), std::uint32_t(integer)); #else +#ifndef __e2k__ ::makecontext(&record->uctx, (void (*)()) & fiber_entry_func, 1, record); +#else + // On the e2k arch makecontext() allocates memory and thus may fail due to OOM + // We have to check for the returning value + int mc_ret = ::makecontext_e2k(&record->uctx, (void (*)()) & fiber_entry_func, + 1, record); + if (BOOST_UNLIKELY(mc_ret < 0)) { + record->~capture_t(); + salloc.deallocate( sctx); + throw std::system_error(std::error_code(errno, std::system_category()), + "makecontext_e2k() failed"); + } +#endif // __e2k__ #endif #if defined(BOOST_USE_ASAN) record->stack_bottom = record->uctx.uc_stack.ss_sp; @@ -393,8 +411,21 @@ static fiber_activation_record * create_fiber2( preallocated palloc, StackAlloc std::uint32_t((integer >> 32) & 0xFFFFFFFF), std::uint32_t(integer)); #else +#ifndef __e2k__ ::makecontext(&record->uctx, (void (*)()) & fiber_entry_func, 1, record); +#else + // On the e2k arch makecontext() allocates memory and thus may fail due to OOM + // We have to check for the returning value + int mc_ret = ::makecontext_e2k(&record->uctx, (void (*)()) & fiber_entry_func, + 1, record); + if (BOOST_UNLIKELY(mc_ret < 0)) { + record->~capture_t(); + salloc.deallocate( palloc.sctx); + throw std::system_error(std::error_code(errno, std::system_category()), + "makecontext_e2k() failed"); + } +#endif // __e2k__ #endif #if defined(BOOST_USE_ASAN) record->stack_bottom = record->uctx.uc_stack.ss_sp;