23 "main stack size is too small for ucontext!");
25 thread_local std::array<uintptr_t, UContext::kMainStackSize> UContext::gMainStack;
27 std::unordered_map<int, std::unique_ptr<UContext::Context>> UContext::gContextInfo;
28 std::mutex UContext::gContextInfoLock;
29 int UContext::gContextNextId{0};
45 allocSize +=
sizeof(ucontext_t);
57 throw std::runtime_error(
"posix_memalign() failed");
61 throw std::runtime_error(
"failed to allocate stack");
65 this->
stack = {
reinterpret_cast<uintptr_t *
>(buf), allocSize /
sizeof(uintptr_t)};
66 this->ownsStack =
true;
84 _aligned_free(this->
stack.data());
86 free(this->
stack.data());
94 #pragma clang diagnostic push
95 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
107 auto info = std::make_unique<Context>(entry);
108 if(!info)
throw std::runtime_error(
"Failed to allocate context");
111 auto uctx = ContextFor(thread);
112 memset(uctx, 0,
sizeof(*uctx));
114 if(getcontext(uctx)) {
115 throw std::runtime_error(
"getcontext() failed");
119 auto offset =
sizeof(ucontext_t);
124 uctx->uc_stack.ss_sp =
reinterpret_cast<std::byte *
>(thread->
stack.data()) + offset;
125 uctx->uc_stack.ss_size = (thread->
stack.size() *
sizeof(uintptr_t)) - offset;
130 std::lock_guard<std::mutex> lg(gContextInfoLock);
132 id = ++gContextNextId;
134 gContextInfo.emplace(
id, std::move(info));
139 makecontext(uctx,
reinterpret_cast<void(*)()
>(&EntryStub), 1,
id);
148 void UContext::InvokeCothreadDidReturnHandler(
Cothread *from) {
158 void UContext::EntryStub(
int id) {
160 std::unique_ptr<Context> info;
162 std::lock_guard<std::mutex> lg(gContextInfoLock);
163 info = std::move(gContextInfo.at(
id));
164 gContextInfo.erase(
id);
181 swapcontext(UContext::ContextFor(from), UContext::ContextFor(
this));
184 #pragma clang diagnostic pop
193 return new UContext(UContext::gMainStack);
Instance of a single cooperative thread.
static Cothread * Current()
Implementation of context switching that uses the C library's setcontext() methods.
UContext(const Entry &entry, const size_t stackSize=0)
static constexpr const size_t kStackAlignment
void switchTo(CothreadImpl *from) override
static constexpr const size_t kDefaultStackSize
static constexpr const size_t kMainStackSize
Implementation details (including architecture/platform specific code) for the library.
std::function< void(libcommunism::Cothread *)> gReturnHandler
Main namespace for the libcommunism library.
CothreadImpl * AllocKernelThreadWrapper()
Abstract interface for a platform implementation of cothreads.
std::span< uintptr_t > stack
Stack used by this cothread, if any.