diff --git a/compiler/compiler-settings.cpp b/compiler/compiler-settings.cpp index d096a120ac..2afde09710 100644 --- a/compiler/compiler-settings.cpp +++ b/compiler/compiler-settings.cpp @@ -340,6 +340,11 @@ void CompilerSettings::init() { if (!dynamic_incremental_linkage.get()) { ss << " -fvisibility=hidden"; } + if (vk::contains(cxx.get(), "clang")) { + // To avoid undefined behavior, the coroutine frame must be allocated using the aligned operator new overload (the one that takes a std::align_val_t) + // Details: https://github.com/llvm/llvm-project/commit/327141fb1d8ca35b323107a43d57886eb77e7384 + ss << " -fcoro-aligned-allocation"; + } // Temporary solution. Required for allocator functions replacement in timelib ss << " -DTIMELIB_ALLOC_FUNC_PREFIX=timelib_"; } else { diff --git a/runtime-light/coroutine/detail/await-set.h b/runtime-light/coroutine/detail/await-set.h index 2edbd086e4..2c05be0c6e 100644 --- a/runtime-light/coroutine/detail/await-set.h +++ b/runtime-light/coroutine/detail/await-set.h @@ -61,6 +61,11 @@ class await_broker { return kphp::memory::script::alloc(n); } + template + auto operator new(size_t n, std::align_val_t al, [[maybe_unused]] Args&&... args) noexcept -> void* { + return kphp::memory::script::alloc_aligned(n, al); + } + void operator delete(void* ptr, [[maybe_unused]] size_t n) noexcept { kphp::memory::script::free(ptr); } @@ -168,6 +173,11 @@ class await_set_task_promise_base : public kphp::coro::async_stack_element { return kphp::memory::script::alloc(n); } + template + auto operator new(size_t n, std::align_val_t al, [[maybe_unused]] Args&&... args) noexcept -> void* { + return kphp::memory::script::alloc_aligned(n, al); + } + void operator delete(void* ptr, [[maybe_unused]] size_t n) noexcept { kphp::memory::script::free(ptr); } diff --git a/runtime-light/coroutine/detail/task-self-deleting.h b/runtime-light/coroutine/detail/task-self-deleting.h index daa72cdd17..3ff19f1831 100644 --- a/runtime-light/coroutine/detail/task-self-deleting.h +++ b/runtime-light/coroutine/detail/task-self-deleting.h @@ -35,6 +35,11 @@ struct promise_self_deleting : kphp::coro::async_stack_element { return kphp::memory::script::alloc(n); } + template + auto operator new(size_t n, std::align_val_t al, [[maybe_unused]] Args&&... args) noexcept -> void* { + return kphp::memory::script::alloc_aligned(n, al); + } + auto operator delete(void* ptr, [[maybe_unused]] size_t n) noexcept -> void { kphp::memory::script::free(ptr); } diff --git a/runtime-light/coroutine/detail/when-all.h b/runtime-light/coroutine/detail/when-all.h index cc276f7996..2386e4fbb6 100644 --- a/runtime-light/coroutine/detail/when-all.h +++ b/runtime-light/coroutine/detail/when-all.h @@ -155,6 +155,11 @@ class when_all_task_promise_base : public kphp::coro::async_stack_element { return kphp::memory::script::alloc(n); } + template + auto operator new(size_t n, std::align_val_t al, [[maybe_unused]] Args&&... args) noexcept -> void* { + return kphp::memory::script::alloc_aligned(n, al); + } + auto operator delete(void* ptr, [[maybe_unused]] size_t n) noexcept -> void { kphp::memory::script::free(ptr); } diff --git a/runtime-light/coroutine/detail/when-any.h b/runtime-light/coroutine/detail/when-any.h index 2d7df28e37..f5ee01549e 100644 --- a/runtime-light/coroutine/detail/when-any.h +++ b/runtime-light/coroutine/detail/when-any.h @@ -165,6 +165,11 @@ class when_any_task_promise_base : public kphp::coro::async_stack_element { return kphp::memory::script::alloc(n); } + template + auto operator new(size_t n, std::align_val_t al, [[maybe_unused]] Args&&... args) noexcept -> void* { + return kphp::memory::script::alloc_aligned(n, al); + } + auto operator delete(void* ptr, [[maybe_unused]] size_t n) noexcept -> void { kphp::memory::script::free(ptr); } diff --git a/runtime-light/coroutine/shared-task.h b/runtime-light/coroutine/shared-task.h index c0a3c1cc29..ddec603c58 100644 --- a/runtime-light/coroutine/shared-task.h +++ b/runtime-light/coroutine/shared-task.h @@ -148,6 +148,11 @@ struct promise_base : kphp::coro::async_stack_element { return kphp::memory::script::alloc(n); } + template + auto operator new(size_t n, std::align_val_t al, [[maybe_unused]] Args&&... args) noexcept -> void* { + return kphp::memory::script::alloc_aligned(n, al); + } + auto operator delete(void* ptr, [[maybe_unused]] size_t n) noexcept -> void { kphp::memory::script::free(ptr); } diff --git a/runtime-light/coroutine/task.h b/runtime-light/coroutine/task.h index 7ba3fb2041..d5c064720b 100644 --- a/runtime-light/coroutine/task.h +++ b/runtime-light/coroutine/task.h @@ -69,6 +69,11 @@ struct promise_base : kphp::coro::async_stack_element { return kphp::memory::script::alloc(n); } + template + auto operator new(size_t n, std::align_val_t al, [[maybe_unused]] Args&&... args) noexcept -> void* { + return kphp::memory::script::alloc_aligned(n, al); + } + auto operator delete(void* ptr, [[maybe_unused]] size_t n) noexcept -> void { kphp::memory::script::free(ptr); } diff --git a/runtime-light/runtime-light.cmake b/runtime-light/runtime-light.cmake index 3b5494afd4..e5df2f323d 100644 --- a/runtime-light/runtime-light.cmake +++ b/runtime-light/runtime-light.cmake @@ -2,7 +2,7 @@ include(${THIRD_PARTY_DIR}/pcre2-cmake/pcre2.cmake) # ================================================================================================= -set(RUNTIME_LIGHT_COMPILE_FLAGS -stdlib=libc++ ${RUNTIME_LIGHT_VISIBILITY}) +set(RUNTIME_LIGHT_COMPILE_FLAGS -stdlib=libc++ -fcoro-aligned-allocation ${RUNTIME_LIGHT_VISIBILITY}) set(RUNTIME_LIGHT_PLATFORM_SPECIFIC_LINK_FLAGS) if(APPLE) diff --git a/tests/phpt/fork/043_sched_yield_in_callback.php b/tests/phpt/fork/043_sched_yield_in_callback.php new file mode 100644 index 0000000000..7a7f847bbf --- /dev/null +++ b/tests/phpt/fork/043_sched_yield_in_callback.php @@ -0,0 +1,21 @@ +@ok +