about summary refs log tree commit diff
path: root/src/rt/rust_task.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rt/rust_task.cpp')
-rw-r--r--src/rt/rust_task.cpp26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index 17faeec1a1c..5043f9ec4b0 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -8,6 +8,8 @@
 #ifndef __WIN32__
 #include <execinfo.h>
 #endif
+#include <cassert>
+#include <cstring>
 
 #include "globals.h"
 
@@ -36,22 +38,46 @@ new_stk(rust_scheduler *sched, rust_task *task, size_t minsz)
     stk_seg *stk = (stk_seg *)task->malloc(sz, "stack");
     LOGPTR(task->sched, "new stk", (uintptr_t)stk);
     memset(stk, 0, sizeof(stk_seg));
+    stk->next = task->stk;
     stk->limit = (uintptr_t) &stk->data[minsz];
     LOGPTR(task->sched, "stk limit", stk->limit);
     stk->valgrind_id =
         VALGRIND_STACK_REGISTER(&stk->data[0],
                                 &stk->data[minsz]);
+    task->stk = stk;
     return stk;
 }
 
 static void
 del_stk(rust_task *task, stk_seg *stk)
 {
+    assert(stk == task->stk && "Freeing stack segments out of order!");
+
+    task->stk = stk->next;
+
     VALGRIND_STACK_DEREGISTER(stk->valgrind_id);
     LOGPTR(task->sched, "freeing stk segment", (uintptr_t)stk);
     task->free(stk);
 }
 
+// Entry points for `__morestack` (see arch/*/morestack.S).
+extern "C" void *
+rust_new_stack(size_t stk_sz, void *args_addr, size_t args_sz) {
+    rust_task *task = rust_scheduler::get_task();
+    stk_seg *stk_seg = new_stk(task->sched, task, stk_sz);
+    memcpy(stk_seg->data, args_addr, args_sz);
+    return stk_seg->data;
+}
+
+extern "C" void *
+rust_del_stack() {
+    rust_task *task = rust_scheduler::get_task();
+    stk_seg *next_seg = task->stk->next;
+    del_stk(task, task->stk);
+    return next_seg->data;
+}
+
+
 // Tasks
 rust_task::rust_task(rust_scheduler *sched, rust_task_list *state,
                      rust_task *spawner, const char *name) :