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

ruby-changes:66656

From: Samuel <ko1@a...>
Date: Thu, 1 Jul 2021 08:23:49 +0900 (JST)
Subject: [ruby-changes:66656] 42130a64f0 (master): Replace copy coroutine with pthread implementation.

https://git.ruby-lang.org/ruby.git/commit/?id=42130a64f0

From 42130a64f02294dc8025af3a51bda518c67ab33d Mon Sep 17 00:00:00 2001
From: Samuel Williams <samuel.williams@o...>
Date: Sat, 26 Jun 2021 10:17:26 +1200
Subject: Replace copy coroutine with pthread implementation.

---
 .github/workflows/compilers.yml |   2 +-
 NEWS.md                         |   3 +
 bootstraptest/test_fiber.rb     |   4 +-
 configure.ac                    |   8 +-
 cont.c                          | 141 ++++++++++-----------
 coroutine/Stack.h               |  21 ----
 coroutine/amd64/Context.h       |   1 +
 coroutine/arm32/Context.h       |   1 +
 coroutine/arm64/Context.h       |   1 +
 coroutine/copy/Context.c        | 162 ------------------------
 coroutine/copy/Context.h        |  98 ---------------
 coroutine/emscripten/Context.h  |   1 +
 coroutine/ppc64le/Context.h     |   1 +
 coroutine/pthread/Context.c     | 268 ++++++++++++++++++++++++++++++++++++++++
 coroutine/pthread/Context.h     |  63 ++++++++++
 coroutine/riscv64/Context.h     |   1 +
 coroutine/ucontext/Context.c    |   1 +
 coroutine/ucontext/Context.h    |   1 +
 coroutine/win32/Context.h       |   1 +
 coroutine/win64/Context.h       |   1 +
 coroutine/x86/Context.h         |   1 +
 eval.c                          |   5 -
 eval_intern.h                   |   4 +-
 process.c                       |  24 ++--
 test/ruby/test_fiber.rb         |   5 +-
 thread.c                        |  22 ++--
 thread_pthread.c                |   4 +-
 thread_sync.c                   |  85 ++++++-------
 thread_win32.c                  |   4 +-
 vm_core.h                       |   7 +-
 30 files changed, 492 insertions(+), 449 deletions(-)
 delete mode 100644 coroutine/Stack.h
 delete mode 100644 coroutine/copy/Context.c
 delete mode 100644 coroutine/copy/Context.h
 create mode 100644 coroutine/pthread/Context.c
 create mode 100644 coroutine/pthread/Context.h

diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml
index 3bd7bab..ea19c01 100644
--- a/.github/workflows/compilers.yml
+++ b/.github/workflows/compilers.yml
@@ -93,7 +93,7 @@ jobs: https://github.com/ruby/ruby/blob/trunk/.github/workflows/compilers.yml#L93
           - { key: append_configure, name: jemalloc,             value: '--with-jemalloc' }
           - { key: append_configure, name: valgrind,             value: '--with-valgrind' }
           - { key: append_configure, name: 'coroutine=ucontext', value: '--with-coroutine=ucontext' }
-          - { key: append_configure, name: 'coroutine=copy',     value: '--with-coroutine=copy' }
+          - { key: append_configure, name: 'coroutine=pthread',  value: '--with-coroutine=pthread' }
           - { key: append_configure, name: disable-jit-support,  value: '--disable-jit-support' }
           - { key: append_configure, name: disable-dln,          value: '--disable-dln' }
           - { key: append_configure, name: disable-rubygems,     value: '--disable-rubygems' }
diff --git a/NEWS.md b/NEWS.md
index 68ae707..00102ff 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -128,6 +128,8 @@ Outstanding ones only. https://github.com/ruby/ruby/blob/trunk/NEWS.md#L128
 
     * Make `Monitor` fiber-safe. [[Bug #17827]]
 
+    * Replace copy coroutine with pthread implementation. [[Feature #18015]]
+
 ## Stdlib updates
 
 Outstanding ones only.
@@ -193,3 +195,4 @@ Excluding feature bug fixes. https://github.com/ruby/ruby/blob/trunk/NEWS.md#L195
 [Feature #17470]: https://bugs.ruby-lang.org/issues/17470
 [Feature #17853]: https://bugs.ruby-lang.org/issues/17853
 [Bug #17827]: https://bugs.ruby-lang.org/issues/17827
+[Feature #18015]: https://bugs.ruby-lang.org/issues/18015
diff --git a/bootstraptest/test_fiber.rb b/bootstraptest/test_fiber.rb
index 35e1bf6..2614dd1 100644
--- a/bootstraptest/test_fiber.rb
+++ b/bootstraptest/test_fiber.rb
@@ -19,12 +19,12 @@ assert_equal %q{ok}, %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_fiber.rb#L19
 }
 
 assert_equal %q{ok}, %q{
-  10_000.times.collect{Fiber.new{}}
+  100.times.collect{Fiber.new{}}
   :ok
 }
 
 assert_equal %q{ok}, %q{
-  fibers = 100.times.collect{Fiber.new{Fiber.yield}}
+  fibers = 1000.times.collect{Fiber.new{Fiber.yield}}
   fibers.each(&:resume)
   fibers.each(&:resume)
   :ok
diff --git a/configure.ac b/configure.ac
index 90b5a75..f74dbdc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2533,10 +2533,10 @@ AS_CASE([$coroutine_type], [yes|''], [ https://github.com/ruby/ruby/blob/trunk/configure.ac#L2533
             coroutine_type=x86
         ],
         [*-openbsd*], [
-            coroutine_type=copy
+            coroutine_type=pthread
         ],
         [*-haiku*], [
-            coroutine_type=copy
+            coroutine_type=pthread
         ],
         [*-emscripten*], [
             coroutine_type=emscripten
@@ -2544,7 +2544,7 @@ AS_CASE([$coroutine_type], [yes|''], [ https://github.com/ruby/ruby/blob/trunk/configure.ac#L2544
         [
             AC_CHECK_FUNCS([getcontext swapcontext makecontext],
                 [coroutine_type=ucontext],
-                [coroutine_type=copy; break]
+                [coroutine_type=pthread; break]
             )
         ]
     )
@@ -2554,7 +2554,7 @@ COROUTINE_H=coroutine/$coroutine_type/Context.h https://github.com/ruby/ruby/blob/trunk/configure.ac#L2554
 AS_IF([test ! -f "$srcdir/$COROUTINE_H"],
       [AC_MSG_ERROR('$coroutine_type' is not supported as coroutine)])
 AS_CASE([$coroutine_type],
-    [copy|ucontext], [
+    [ucontext|pthread], [
         COROUTINE_SRC=coroutine/$coroutine_type/Context.c
     ],
     [
diff --git a/cont.c b/cont.c
index 00ab1e9..d72d29e 100644
--- a/cont.c
+++ b/cont.c
@@ -711,10 +711,51 @@ fiber_pool_stack_release(struct fiber_pool_stack * stack) https://github.com/ruby/ruby/blob/trunk/cont.c#L711
 #endif
 }
 
+void rb_fiber_start(rb_fiber_t*);
+
+static inline void
+ec_switch(rb_thread_t *th, rb_fiber_t *fiber)
+{
+    rb_execution_context_t *ec = &fiber->cont.saved_ec;
+    rb_ractor_set_current_ec(th->ractor, th->ec = ec);
+    // ruby_current_execution_context_ptr = th->ec = ec;
+
+    /*
+     * timer-thread may set trap interrupt on previous th->ec at any time;
+     * ensure we do not delay (or lose) the trap interrupt handling.
+     */
+    if (th->vm->ractor.main_thread == th &&
+        rb_signal_buff_size() > 0) {
+        RUBY_VM_SET_TRAP_INTERRUPT(ec);
+    }
+
+    VM_ASSERT(ec->fiber_ptr->cont.self == 0 || ec->vm_stack != NULL);
+}
+
+static inline void
+fiber_restore_thread(rb_thread_t *th, rb_fiber_t *fiber)
+{
+    ec_switch(th, fiber);
+    VM_ASSERT(th->ec->fiber_ptr == fiber);
+}
+
 static COROUTINE
 fiber_entry(struct coroutine_context * from, struct coroutine_context * to)
 {
-    rb_fiber_start();
+    rb_fiber_t *fiber = to->argument;
+    rb_thread_t *thread = fiber->cont.saved_ec.thread_ptr;
+
+#ifdef COROUTINE_PTHREAD_CONTEXT
+    ruby_thread_set_native(thread);
+#endif
+
+    fiber_restore_thread(thread, fiber);
+
+    rb_fiber_start(fiber);
+
+#ifndef COROUTINE_PTHREAD_CONTEXT
+    VM_UNREACHABLE(fiber_entry);
+#endif
 }
 
 // Initialize a fiber's coroutine's machine stack and vm stack.
@@ -731,22 +772,13 @@ fiber_initialize_coroutine(rb_fiber_t *fiber, size_t * vm_stack_size) https://github.com/ruby/ruby/blob/trunk/cont.c#L772
     vm_stack = fiber_pool_stack_alloca(&fiber->stack, fiber_pool->vm_stack_size);
     *vm_stack_size = fiber_pool->vm_stack_size;
 
-#ifdef COROUTINE_PRIVATE_STACK
-    coroutine_initialize(&fiber->context, fiber_entry, fiber_pool_stack_base(&fiber->stack), fiber->stack.available, sec->machine.stack_start);
-    // The stack for this execution context is still the main machine stack, so don't adjust it.
-    // If this is not managed correctly, you will fail in `rb_ec_stack_check`.
-
-    // We limit the machine stack usage to the fiber stack size.
-    if (sec->machine.stack_maxsize > fiber->stack.available) {
-        sec->machine.stack_maxsize = fiber->stack.available;
-    }
-#else
     coroutine_initialize(&fiber->context, fiber_entry, fiber_pool_stack_base(&fiber->stack), fiber->stack.available);
 
     // The stack for this execution context is the one we allocated:
     sec->machine.stack_start = fiber->stack.current;
     sec->machine.stack_maxsize = fiber->stack.available;
-#endif
+
+    fiber->context.argument = (void*)fiber;
 
     return vm_stack;
 }
@@ -815,25 +847,6 @@ fiber_status_set(rb_fiber_t *fiber, enum fiber_status s) https://github.com/ruby/ruby/blob/trunk/cont.c#L847
     fiber->status = s;
 }
 
-static inline void
-ec_switch(rb_thread_t *th, rb_fiber_t *fiber)
-{
-    rb_execution_context_t *ec = &fiber->cont.saved_ec;
-    rb_ractor_set_current_ec(th->ractor, th->ec = ec);
-    // ruby_current_execution_context_ptr = th->ec = ec;
-
-    /*
-     * timer-thread may set trap interrupt on previous th->ec at any time;
-     * ensure we do not delay (or lose) the trap interrupt handling.
-     */
-    if (th->vm->ractor.main_thread == th &&
-        rb_signal_buff_size() > 0) {
-        RUBY_VM_SET_TRAP_INTERRUPT(ec);
-    }
-
-    VM_ASSERT(ec->fiber_ptr->cont.self == 0 || ec->vm_stack != NULL);
-}
-
 static rb_context_t *
 cont_ptr(VALUE obj)
 {
@@ -1041,7 +1054,7 @@ fiber_free(void *ptr) https://github.com/ruby/ruby/blob/trunk/cont.c#L1054
     rb_fiber_t *fiber = ptr;
     RUBY_FREE_ENTER("fiber");
 
-    //if (DEBUG) fprintf(stderr, "fiber_free: %p[%p]\n", fiber, fiber->stack.base);
+    if (DEBUG) fprintf(stderr, "fiber_free: %p[%p]\n", fiber, fiber->stack.base);
 
     if (fiber->cont.saved_ec.local_storage) {
         rb_id_table_free(fiber->cont.saved_ec.local_storage);
@@ -1278,13 +1291,6 @@ cont_capture(volatile int *volatile stat) https://github.com/ruby/ruby/blob/trunk/cont.c#L1291
 COMPILER_WARNING_POP
 
 static inline void
-fiber_restore_thread(rb_thread_t *th, rb_fiber_t *fiber)
-{
-    ec_switch(th, fiber);
-    VM_ASSERT(th->ec->fiber_ptr == fiber);
-}
-
-static inline void
 cont_restore_thread(rb_context_t *cont)
 {
     rb_thread_t *th = GET_THREAD();
@@  (... truncated)

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

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