diff options
-rw-r--r-- | example/test.cc | 25 | ||||
-rw-r--r-- | lib/matcha.cc | 15 | ||||
-rw-r--r-- | lib/matcha.h | 38 | ||||
-rw-r--r-- | lib/thread_create.s | 6 |
4 files changed, 59 insertions, 25 deletions
diff --git a/example/test.cc b/example/test.cc index b436708..1a40958 100644 --- a/example/test.cc +++ b/example/test.cc @@ -1,21 +1,30 @@ #include "lib/matcha.h" -#include <cassert> #include <cstdio> +#include <memory> + +struct TestThread : public Thread { + TestThread(const char* name) : Thread(), mName(name) {} -struct Thread1 : public Thread { virtual void threadFn() override { - puts("start threadFn -> yield()"); + printf("[%s] starting up TestThread -> yield()\n", mName); yield(); - puts("return from yield() -> finish threadFn"); + printf("[%s] yield() -> finishing TestThreads\n", mName); } -} gThread1; + + private: + const char* mName; +}; int main() { - puts("start main thread"); + puts("[main] start main thread"); - gThread1.yield_to(); + Executor e; + e.spawn(std::make_unique<TestThread>("Thread1")); + e.spawn(std::make_unique<TestThread>("Thread2")); + e.spawn(std::make_unique<TestThread>("Thread3")); + e.run(); - puts("finish main thread"); + puts("[main] finish main thread"); return 0; } diff --git a/lib/matcha.cc b/lib/matcha.cc index 561a08f..6e73a5e 100644 --- a/lib/matcha.cc +++ b/lib/matcha.cc @@ -2,13 +2,12 @@ #include <cassert> #include <cstdint> -#include <cstdio> #include <sys/mman.h> #include <unistd.h> // sysconf // asm fns extern "C" void thread_create(); -extern "C" void yield(void* new_stack, void** old_stack); +extern "C" void yield(const void* new_stack, void* const* old_stack); long get_pagesize() { return sysconf(_SC_PAGESIZE); @@ -51,18 +50,14 @@ Thread::Thread() { void Thread::entry(void* obj) { Thread* t = static_cast<Thread*>(obj); - - puts("thread entry"); t->threadFn(); - puts("thread done"); } -void* gOriginalStack; - void Thread::yield() { - ::yield(gOriginalStack, &mStackPtr); + assert(mExecutor); + ::yield(mExecutor->getStackPtr(), &mStackPtr); } -void Thread::yield_to() const { - ::yield(mStackPtr, &gOriginalStack); +void Executor::yield_to(const Thread* t) const { + ::yield(t->mStackPtr, &mStackPtr); } diff --git a/lib/matcha.h b/lib/matcha.h index 1506081..9fed7c2 100644 --- a/lib/matcha.h +++ b/lib/matcha.h @@ -1,18 +1,48 @@ +#include <memory> +#include <vector> + +struct Executor; + struct Thread { Thread(const Thread&) = delete; Thread& operator=(const Thread&) = delete; Thread(); + virtual ~Thread() {} virtual void threadFn() = 0; - // use from executor - void yield_to() const; - protected: - // use in thread void yield(); private: static void entry(void* obj); void* mStackPtr; + + friend struct Executor; + const Executor* mExecutor; +}; + + +struct Executor { + Executor(const Executor&) = delete; + Executor& operator=(const Executor&) = delete; + Executor() = default; + + const void* getStackPtr() const { return mStackPtr; } + + void spawn(std::unique_ptr<Thread> t) { + mThreads.push_back(std::move(t)); + mThreads.back()->mExecutor = this; + } + void run() { + for (const std::unique_ptr<Thread>& t : mThreads) { + yield_to(t.get()); + } + } + + private: + void* mStackPtr; + std::vector<std::unique_ptr<Thread>> mThreads; + + void yield_to(const Thread* t) const; }; diff --git a/lib/thread_create.s b/lib/thread_create.s index 6ebcd86..d5dd092 100644 --- a/lib/thread_create.s +++ b/lib/thread_create.s @@ -23,9 +23,9 @@ thread_create: .size thread_create, .-thread_create - # extern "C" void yield(void* new_stack, void** old_stack); - # ^^^^^^^^^ ^^^^^^^^^ - # rdi rsi + # extern "C" void yield(const void* new_stack, void* const* old_stack); + # ^^^^^^^^^ ^^^^^^^^^ + # rdi rsi .global yield .type yield, @function yield: |