29#include <EASTL/functional.h>
30#include <EASTL/utility.h>
54template <
typename T =
void>
57 typedef typename std::conditional<std::is_void<T>::value,
Empty, T>::type
SafeT;
62 if (m_handle) m_handle.destroy();
64 m_handle = other.m_handle;
65 m_value = eastl::move(other.m_value);
66 m_suspended = other.m_suspended;
67 m_earlyResume = other.m_earlyResume;
69 other.m_handle =
nullptr;
70 other.m_value =
SafeT{};
71 other.m_suspended =
true;
72 other.m_earlyResume =
false;
77 if (m_handle) m_handle.destroy();
79 m_handle = other.m_handle;
80 m_value = eastl::move(other.m_value);
81 m_suspended = other.m_suspended;
82 m_earlyResume = other.m_earlyResume;
84 other.m_handle =
nullptr;
85 other.m_value =
SafeT{};
86 other.m_suspended =
true;
87 other.m_earlyResume =
false;
95 if (m_handle) m_handle.destroy();
113 bool ret = m_coroutine->m_earlyResume;
114 m_coroutine->m_earlyResume =
false;
117 constexpr void await_suspend(std::coroutine_handle<> h) { m_coroutine->m_suspended =
true; }
144 if (!m_handle)
return;
146 m_earlyResume =
true;
163 if (!m_handle)
return true;
164 bool isDone = m_handle.done();
166 if constexpr (!std::is_void<T>::value) {
167 m_value = eastl::move(m_handle.promise().m_value);
191 return Coroutine<>{eastl::move(std::coroutine_handle<Promise>::from_promise(*
this))};
193 std::suspend_always initial_suspend() {
return {}; }
194 std::suspend_always final_suspend() noexcept {
return {}; }
195 void unhandled_exception() {}
197 if (m_awaitingCoroutine) {
199 m_awaitingCoroutine =
nullptr;
202 [[no_unique_address]] Empty m_value;
203 std::coroutine_handle<> m_awaitingCoroutine;
206 struct PromiseValue {
207 Coroutine<T> get_return_object() {
208 return Coroutine{eastl::move(std::coroutine_handle<Promise>::from_promise(*
this))};
210 std::suspend_always initial_suspend() {
return {}; }
211 std::suspend_always final_suspend() noexcept {
return {}; }
212 void unhandled_exception() {}
213 void return_value(T &&
value) {
214 m_value = eastl::move(
value);
215 if (m_awaitingCoroutine) {
217 m_awaitingCoroutine =
nullptr;
221 std::coroutine_handle<> m_awaitingCoroutine;
224 typedef typename std::conditional<std::is_void<T>::value, PromiseVoid, PromiseValue>::type Promise;
226 Coroutine(std::coroutine_handle<Promise> &&handle) : m_handle(eastl::
move(handle)) {}
228 std::coroutine_handle<Promise> m_handle;
229 [[no_unique_address]]
SafeT m_value;
230 bool m_suspended =
true;
231 bool m_earlyResume =
false;
260 handle.promise().m_awaitingCoroutine = h;
265 if constexpr (std::is_void<T>::value) {
270 auto val = eastl::move(
handle.promise().m_value);
287 void initializeInternal(eastl::function<
void()> &&func,
void *ss_sp,
unsigned ss_size);
290 [[nodiscard]]
bool isAlive()
const {
return m_isAlive; }
297 static void trampoline(
void *arg) {
304 eastl::function<void()> m_func;
305 bool m_isAlive =
false;
306#ifdef PSYQO_SHADOW_STACK
325template <
unsigned StackSize = 0x10000>
376 struct alignas(8) Stack {
416template <
unsigned StackSize = 1024>
418 static_assert(StackSize <= 1024,
"The scratchpad is 1024 bytes");
419 static_assert(StackSize > 16,
"makecontext reserves 16 bytes at the top of the stack");
420 static_assert((StackSize & 7) == 0,
"The stack size needs to be a multiple of 8");
437 "ScratchpadStackful: the .scratchpad section overlaps the stack");
Stackful coroutine whose stack is the scratchpad.
Definition coroutine.hh:417
ScratchpadStackful()=default
ScratchpadStackful(const ScratchpadStackful &)=delete
static constexpr uintptr_t c_stackBase
Definition coroutine.hh:423
void initialize(eastl::function< void()> &&func)
Initialize the coroutine with a function.
Definition coroutine.hh:435
ScratchpadStackful & operator=(const ScratchpadStackful &)=delete
static constexpr unsigned c_freeBytes
Definition coroutine.hh:425
void yield()
Yield the coroutine. See Stackful::yield.
Definition coroutine.hh:449
bool isAlive() const
Check if the coroutine is currently alive. See Stackful::isAlive.
Definition coroutine.hh:454
void resume()
Resume the coroutine. See Stackful::resume.
Definition coroutine.hh:444
static constexpr unsigned c_stackSize
Definition coroutine.hh:424
Definition coroutine.hh:285
void yield()
Definition coroutine.cpp:60
bool isAlive() const
Definition coroutine.hh:290
StackfulBase & operator=(const StackfulBase &)=delete
void resume()
Definition coroutine.cpp:47
StackfulBase(const StackfulBase &)=delete
void initializeInternal(eastl::function< void()> &&func, void *ss_sp, unsigned ss_size)
Definition coroutine.cpp:29
Stackful coroutine class.
Definition coroutine.hh:326
Stackful(const Stackful &)=delete
bool isAlive() const
Check if the coroutine is currently alive.
Definition coroutine.hh:373
void yield()
Yield the coroutine.
Definition coroutine.hh:363
void resume()
Resume the coroutine.
Definition coroutine.hh:353
void initialize(eastl::function< void()> &&func)
Initialize the coroutine with a function and an argument.
Definition coroutine.hh:340
static constexpr unsigned c_stackSize
Definition coroutine.hh:328
Stackful & operator=(const Stackful &)=delete
constexpr uint32_t move(Reg tgt, Reg src)
Definition encoder.hh:243
void assert(bool condition, const char *message, std::source_location location=std::source_location::current())
A simple assert macro.
Definition kernel.hh:366
void queueCallback(eastl::function< void()> &&lambda)
Queues a callback to be called from the main thead.
Definition kernel.cpp:410
char __scratchpad_end[]
Definition coroutine.hh:383
The awaiter type.
Definition coroutine.hh:107
Awaiter(Awaiter &&other)=default
Awaiter(Awaiter const &)=default
constexpr void await_suspend(std::coroutine_handle<> h)
Definition coroutine.hh:117
Awaiter & operator=(Awaiter const &)=default
constexpr void await_resume() const noexcept
Definition coroutine.hh:118
constexpr bool await_ready() const noexcept
Definition coroutine.hh:112
Awaiter & operator=(Awaiter &&other)=default
The awaiter type for coroutine-to-coroutine chaining via co_await.
Definition coroutine.hh:244
constexpr T await_resume()
Definition coroutine.hh:264
constexpr bool await_ready()
Definition coroutine.hh:257
void await_suspend(std::coroutine_handle<> h)
Definition coroutine.hh:259
std::coroutine_handle< Promise > handle
Definition coroutine.hh:245
ChainAwaiter & operator=(const ChainAwaiter &)=delete
ChainAwaiter & operator=(ChainAwaiter &&)=delete
~ChainAwaiter()
Definition coroutine.hh:248
ChainAwaiter(ChainAwaiter &&other)
Definition coroutine.hh:252
ChainAwaiter(const ChainAwaiter &)=delete
ChainAwaiter(std::coroutine_handle< Promise > h)
Definition coroutine.hh:247
Definition coroutine.hh:56
A suitable type to hold and return a C++20 coroutine.
Definition coroutine.hh:55
Coroutine(Coroutine const &)=delete
~Coroutine()
Definition coroutine.hh:94
Coroutine & operator=(Coroutine const &)=delete
Promise promise_type
Definition coroutine.hh:234
const SafeT & value() const
Returns the value returned by the coroutine.
Definition coroutine.hh:186
Coroutine(Coroutine &&other)
Definition coroutine.hh:61
std::conditional< std::is_void< T >::value, Empty, T >::type SafeT
Definition coroutine.hh:57
Coroutine & operator=(Coroutine &&other)
Definition coroutine.hh:75
void resume()
Resumes the coroutine.
Definition coroutine.hh:143
Awaiter awaiter() &
Creates an Awaiter object.
Definition coroutine.hh:132
bool done()
Returns the status of the coroutine.
Definition coroutine.hh:162
One shadow stack, for one machine stack.
Definition shadow-stack.hh:76
static int ret
Definition syscalls.h:125
uint16_t val
Definition timers.c:319