[前][次][番号順一覧][スレッド一覧]

ruby-changes:65016

From: Yusuke <ko1@a...>
Date: Sat, 23 Jan 2021 18:56:34 +0900 (JST)
Subject: [ruby-changes:65016] 62283f7a7a (master): coroutine/emscripten/: Experimentally support emscripten fiber API

https://git.ruby-lang.org/ruby.git/commit/?id=62283f7a7a

From 62283f7a7a87fa2f353814a3ef6a3b1cab2a32b8 Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@r...>
Date: Sat, 23 Jan 2021 18:54:50 +0900
Subject: coroutine/emscripten/: Experimentally support emscripten fiber API

---
 configure.ac                   |  6 +++-
 coroutine/emscripten/Context.c |  8 +++++
 coroutine/emscripten/Context.h | 76 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 89 insertions(+), 1 deletion(-)
 create mode 100644 coroutine/emscripten/Context.c
 create mode 100644 coroutine/emscripten/Context.h

diff --git a/configure.ac b/configure.ac
index 05d3e99..285a2f9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1138,7 +1138,8 @@ main() https://github.com/ruby/ruby/blob/trunk/configure.ac#L1138
 		])
 		],
 [emscripten*], [LIBS="-lm -lc $LIBS"
-		RUBY_APPEND_OPTIONS(LDFLAGS, -s ALLOW_MEMORY_GROWTH=1)
+		RUBY_APPEND_OPTIONS(LDFLAGS, "-s ALLOW_MEMORY_GROWTH=1")
+		RUBY_APPEND_OPTIONS(LDFLAGS, "-s ASYNCIFY")
 		],
 [	LIBS="-lm $LIBS"])
 : ${ORIG_LIBS=$LIBS}
@@ -2461,6 +2462,9 @@ AS_CASE([$rb_cv_coroutine], [yes|''], [ https://github.com/ruby/ruby/blob/trunk/configure.ac#L2462
         [*-haiku*], [
             rb_cv_coroutine=copy
         ],
+        [*-emscripten*], [
+            rb_cv_coroutine=emscripten
+        ],
         [
             rb_cv_coroutine=ucontext
         ]
diff --git a/coroutine/emscripten/Context.c b/coroutine/emscripten/Context.c
new file mode 100644
index 0000000..75c088d
--- /dev/null
+++ b/coroutine/emscripten/Context.c
@@ -0,0 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/coroutine/emscripten/Context.c#L1
+#include "Context.h"
+
+void coroutine_trampoline(void * _context)
+{
+    struct coroutine_context * context = _context;
+
+    context->entry_func(context->from, context);
+}
diff --git a/coroutine/emscripten/Context.h b/coroutine/emscripten/Context.h
new file mode 100644
index 0000000..aefbb92
--- /dev/null
+++ b/coroutine/emscripten/Context.h
@@ -0,0 +1,76 @@ https://github.com/ruby/ruby/blob/trunk/coroutine/emscripten/Context.h#L1
+#ifndef COROUTINE_EMSCRIPTEN_CONTEXT_H
+#define COROUTINE_EMSCRIPTEN_CONTEXT_H 1
+
+/* An experimental coroutine wrapper for emscripten
+ * Contact on Yusuke Endoh if you encounter any problem about this
+ */
+
+#pragma once
+
+#include <assert.h>
+#include <stddef.h>
+#include <emscripten/fiber.h>
+
+#define COROUTINE __attribute__((noreturn)) void
+
+#if INTPTR_MAX <= INT32_MAX
+#define COROUTINE_LIMITED_ADDRESS_SPACE
+#endif
+
+struct coroutine_context;
+
+typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
+
+struct coroutine_context
+{
+    emscripten_fiber_t state;
+    coroutine_start entry_func;
+    struct coroutine_context * from;
+};
+
+COROUTINE coroutine_trampoline(void * _context);
+
+#define MAIN_ASYNCIFY_STACK_SIZE 65536
+static inline void coroutine_initialize_main(struct coroutine_context * context) {
+    static char asyncify_stack[MAIN_ASYNCIFY_STACK_SIZE];
+    emscripten_fiber_init_from_current_context(&context->state, asyncify_stack, MAIN_ASYNCIFY_STACK_SIZE);
+}
+#undef MAIN_ASYNCIFY_STACK_SIZE
+
+static inline void coroutine_initialize(
+    struct coroutine_context *context,
+    coroutine_start start,
+    void *stack,
+    size_t size
+) {
+    assert(start && stack && size >= 1024);
+
+    uintptr_t addr = (uintptr_t)stack;
+    size_t offset = addr & 0xF;
+    void *c_stack = (void*)((addr + 0xF) & ~0xF);
+    size -= offset;
+    size_t c_stack_size = (size / 2) & ~0xF;
+    void *asyncify_stack = (void*)((uintptr_t)c_stack + c_stack_size);
+    size_t asyncify_stack_size = size - c_stack_size;
+    context->entry_func = start;
+
+    emscripten_fiber_init(&context->state, coroutine_trampoline, context, c_stack, c_stack_size, asyncify_stack, asyncify_stack_size);
+}
+
+static inline struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target)
+{
+    struct coroutine_context * previous = target->from;
+
+    target->from = current;
+    emscripten_fiber_swap(&current->state, &target->state);
+    target->from = previous;
+
+    return target;
+}
+
+static inline void coroutine_destroy(struct coroutine_context * context)
+{
+    context->from = NULL;
+}
+
+#endif /* COROUTINE_EMSCRIPTEN_CONTEXT_H */
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]