From 19eaed9e806484eae46ab4146093e384d67d76aa Mon Sep 17 00:00:00 2001 From: Johannes Stoelp Date: Sat, 14 Jan 2023 22:59:04 +0100 Subject: xpost: matcha-thread --- content/2023-01-14-xpost-matcha-threads.md | 73 ++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 content/2023-01-14-xpost-matcha-threads.md (limited to 'content') diff --git a/content/2023-01-14-xpost-matcha-threads.md b/content/2023-01-14-xpost-matcha-threads.md new file mode 100644 index 0000000..f627843 --- /dev/null +++ b/content/2023-01-14-xpost-matcha-threads.md @@ -0,0 +1,73 @@ ++++ +title = "xpost: Cooperative-multitasking studies (matcha-threads)" + +[taxonomies] +tags = ["threading", "linux", "x86", "arm", "riscv"] ++++ + +This is a cross post to a **cooperative-multitasking implementation** that I +did in the past and hosted on github [>> matcha-threads <<][matcha]. + +Cooperative-multitasking allows to perform the thread scheduling in user space. +Executing threads need to give the control back to the `scheduler` such that +other threads can run. Since control is returned explicitly to the scheduler, +threads need to **"cooperate"**. + +The following code snippet shows an example of two such threads: +```cpp +#include "lib/executor.h" +#include "lib/thread.h" +#include + +void like_tea(nMatcha::Yielder& y) { + std::puts("like"); + y.yield(); + std::puts("tea"); +} + +int main() { + nMatcha::Executor e; + e.spawn(nMatcha::FnThread::make(like_tea)); + e.spawn(nMatcha::FnThread::make([](nMatcha::Yielder& y) { + std::puts("I"); + y.yield(); + std::puts("green"); + })); + e.run(); + return 0; +} +``` + +Which gives the following output when being run: +```text +I +like +green +tea +``` + +The main focus of that project was to understand the fundamental mechanism +underlying cooperative-multitasking and implement such a `yield()` function as +shown in the example above. + +Looking at the final implementation, the yield function does the following: +```text +yield: + 1. function prologue + 2. push callee-saved regs to current stack + 3. swap stack pointers (current - new) + 4. pop callee-saved regs from new stack + 5. function epilogue & return +``` + +Implementations for different ISAs are available here: +- [x86_64][yield-x86] +- [arm64][yield-arm64] +- [armv7a][yield-arm] +- [riscv64][yield-rv64] + +[matcha]: https://github.com/johannst/matcha-threads +[yield-x86]: https://github.com/johannst/matcha-threads/blob/master/lib/arch/x86_64/yield.s +[yield-arm]: https://github.com/johannst/matcha-threads/blob/master/lib/arch/arm/yield.s +[yield-arm64]: https://github.com/johannst/matcha-threads/blob/master/lib/arch/arm64/yield.s +[yield-rv64]: https://github.com/johannst/matcha-threads/blob/master/lib/arch/riscv64/yield.s -- cgit v1.2.3