aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example/test.cc25
-rw-r--r--lib/matcha.cc15
-rw-r--r--lib/matcha.h38
-rw-r--r--lib/thread_create.s6
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: