summaryrefslogtreecommitdiff
path: root/coroutine/ppc64le/Context.h
diff options
context:
space:
mode:
authorodaira <odaira@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-12-10 23:22:56 +0000
committerodaira <odaira@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-12-10 23:22:56 +0000
commit3a5cc345f8bab6d179f79265ba20234e41494a68 (patch)
tree4a1344ced170115c98519b3b3df165c24fc3ae1c /coroutine/ppc64le/Context.h
parentdff1e89bfb77e5d57bc56312364ac2036f3f7a99 (diff)
Native coroutine implementation for ppc64le Linux
* configure.ac: enable fiber coroutine for powerpc64le-linux * coroutine/ppc64le/Context.S: coroutine_transfer implementation * coroutine/ppc64le/Context.h: coroutine implementation git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66315 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'coroutine/ppc64le/Context.h')
-rw-r--r--coroutine/ppc64le/Context.h54
1 files changed, 54 insertions, 0 deletions
diff --git a/coroutine/ppc64le/Context.h b/coroutine/ppc64le/Context.h
new file mode 100644
index 0000000000..de592f5a46
--- /dev/null
+++ b/coroutine/ppc64le/Context.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <assert.h>
+#include <string.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#define COROUTINE __attribute__((noreturn)) void
+
+const size_t COROUTINE_REGISTERS =
+ 19 /* 18 general purpose registers (r14-r31) and 1 return address */
+ + 4; /* space for fiber_entry() to store the link register */
+
+typedef struct
+{
+ void **stack_pointer;
+} coroutine_context;
+
+typedef COROUTINE(* coroutine_start)(coroutine_context *from, coroutine_context *self);
+
+static inline void coroutine_initialize(
+ coroutine_context *context,
+ coroutine_start start,
+ void *stack_pointer,
+ size_t stack_size
+) {
+ /* Force 16-byte alignment */
+ context->stack_pointer = (void**)((uintptr_t)stack_pointer & ~0xF);
+
+ if (!start) {
+ assert(!context->stack_pointer);
+ /* We are main coroutine for this thread */
+ return;
+ }
+
+ context->stack_pointer -= COROUTINE_REGISTERS;
+ memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
+
+ /* Skip a global prologue that sets the TOC register */
+ context->stack_pointer[18] = ((char*)start) + 8;
+}
+
+coroutine_context * coroutine_transfer(coroutine_context * current, coroutine_context * target);
+
+static inline void coroutine_destroy(coroutine_context * context)
+{
+ context->stack_pointer = NULL;
+}
+
+#if __cplusplus
+}
+#endif