liblinux++

A hosted C++ runtime without any libc.
git clone git://henryandlizzy.uk/liblinux++
Log | Files | Refs

commit 9f14c4c1b95ad1cabd4d8c40fb85690740d44e90
parent 4e799093ad1f9b1bbc06edd48d5432d8f886d79b
Author: Henry Wilson <henry@henryandlizzy.uk>
Date:   Thu, 15 Jan 2026 01:17:51 +0000

coro: memory buffer based allocation

Diffstat:
Mcoro.cpp | 74+++++++++++++++++++++++++++++++++++++++++---------------------------------
1 file changed, 41 insertions(+), 33 deletions(-)

diff --git a/coro.cpp b/coro.cpp @@ -1,19 +1,9 @@ #include "linux.hpp" -void* operator new(size_t size) -{ - return *mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, {}, 0); -} - -void operator delete(void* p, size_t size) noexcept -{ - *munmap(p, size); -} - struct coroutine_frame { - void(*resume)(coroutine_frame*); - void(*destroy)(coroutine_frame*); + void(*resume)(coroutine_frame*) noexcept; + void(*destroy)(coroutine_frame*) noexcept; }; namespace std @@ -27,41 +17,47 @@ struct coroutine_traits template <typename T = void> struct coroutine_handle { - static coroutine_handle<T> from_address(void* ptr) + static coroutine_handle from_address(void* ptr) noexcept + { + return coroutine_handle{ptr}; + } + static coroutine_handle from_promise(T& promise) noexcept { - return {(coroutine_frame*)ptr}; + return coroutine_handle{((char*)&promise) - sizeof(coroutine_frame)}; } - void resume() const { + void resume() const noexcept { assert(frame); assert(frame->resume); frame->resume(frame); } - void destroy() const { + void destroy() const noexcept { assert(frame); assert(frame->destroy); frame->destroy(frame); } - operator coroutine_handle<void>() const { return {frame}; } - bool done() const + bool done() const noexcept { assert(frame); return not frame->resume; } -//private: +private: + coroutine_handle(void* ptr) noexcept : frame{reinterpret_cast<coroutine_frame*>(ptr)} {} coroutine_frame* frame = nullptr; }; struct suspend_always { bool await_ready() noexcept { return false; } - void await_suspend(coroutine_handle<>) noexcept { } + template <typename T> // easier to do this that provide a <void> specialisation for now + void await_suspend(coroutine_handle<T>) noexcept {} void await_resume() noexcept {} }; struct suspend_never { bool await_ready() noexcept { return true; } - void await_suspend(coroutine_handle<>) noexcept { __builtin_trap(); } + template <typename T> + void await_suspend(coroutine_handle<T>) noexcept { __builtin_trap(); } void await_resume() noexcept {} }; @@ -70,20 +66,30 @@ struct suspend_never struct task { struct promise_type { - std::suspend_never initial_suspend() { return {}; } + std::suspend_never initial_suspend() noexcept { return {}; } std::suspend_always final_suspend() noexcept { return {}; } - task get_return_object() { - void* p = reinterpret_cast<char*>(this) - sizeof(coroutine_frame); - return {std::coroutine_handle<promise_type>::from_address(p)}; + task get_return_object() noexcept { + return {std::coroutine_handle<promise_type>::from_promise(*this)}; } void unhandled_exception() noexcept {} - void return_void() {} + void return_void() noexcept {} + void* operator new(size_t s, span<char> storage) noexcept { + assert(s <= storage.size()); + return storage.begin(); + } + void operator delete(void*, size_t) noexcept {} }; + ~task() { h.destroy(); } + bool done() const noexcept { return h.done(); } + void resume() const noexcept { h.resume(); } +private: + friend struct promise_type; + task(std::coroutine_handle<promise_type> ch) : h{ch} {} std::coroutine_handle<promise_type> h; }; -task mytask() +task mytask(span<char> /*forwarded to new*/) noexcept { *write(stdout, "mytask: started\n"_sp); for (int i = 0; i < 3; ++i) @@ -97,13 +103,15 @@ task mytask() int main() { *write(stdout, "main\n"_sp); - [[maybe_unused]] task t = mytask(); - *write(stdout, "main: mytask created\n"_sp); - while (not t.h.done()) { - t.h.resume(); - *write(stdout, "main: back from resume\n"_sp); + char memory[56]; + task t = mytask(span{memory}); + *write(stdout, "main: mytask created\n"_sp); + while (not t.done()) + { + t.resume(); + *write(stdout, "main: back from resume\n"_sp); + } } - t.h.destroy(); *write(stdout, "main: mytask destroyed\n"_sp); }