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

ruby-changes:70951

From: Yuta <ko1@a...>
Date: Wed, 19 Jan 2022 11:19:54 +0900 (JST)
Subject: [ruby-changes:70951] 420622b5a7 (master): [wasm] add no thread variant for freestanding environment

https://git.ruby-lang.org/ruby.git/commit/?id=420622b5a7

From 420622b5a793186dfa533e7702913fd5e4764e0f Mon Sep 17 00:00:00 2001
From: Yuta Saito <kateinoigakukun@g...>
Date: Sun, 16 Jan 2022 00:37:54 +0900
Subject: [wasm] add no thread variant for freestanding environment

This implementation does nothing around preemptive context switching
because there is no native thread.
---
 include/ruby/thread_native.h |   6 +
 thread.c                     |   2 +-
 thread_none.c                | 278 +++++++++++++++++++++++++++++++++++++++++++
 thread_none.h                |  17 +++
 tool/m4/ruby_thread.m4       |   4 +
 5 files changed, 306 insertions(+), 1 deletion(-)
 create mode 100644 thread_none.c
 create mode 100644 thread_none.h

diff --git a/include/ruby/thread_native.h b/include/ruby/thread_native.h
index 2945ff1e4d5..c23b15e133a 100644
--- a/include/ruby/thread_native.h
+++ b/include/ruby/thread_native.h
@@ -37,6 +37,12 @@ typedef pthread_t rb_nativethread_id_t; https://github.com/ruby/ruby/blob/trunk/include/ruby/thread_native.h#L37
 typedef pthread_mutex_t rb_nativethread_lock_t;
 typedef pthread_cond_t rb_nativethread_cond_t;
 
+#elif defined(__wasi__) // no-thread platforms
+
+typedef struct rb_nativethread_id_t *rb_nativethread_id_t;
+typedef struct rb_nativethread_lock_t *rb_nativethread_lock_t;
+typedef struct rb_nativethread_cond_t *rb_nativethread_cond_t;
+
 #elif defined(__DOXYGEN__)
 
 /** Opaque type that holds an ID of a native thread. */
diff --git a/thread.c b/thread.c
index 52ecf124bd7..95daed66684 100644
--- a/thread.c
+++ b/thread.c
@@ -340,7 +340,7 @@ rb_thread_s_debug_set(VALUE self, VALUE val) https://github.com/ruby/ruby/blob/trunk/thread.c#L340
 # define PRI_THREAD_ID "p"
 #endif
 
-NOINLINE(static int thread_start_func_2(rb_thread_t *th, VALUE *stack_start));
+MAYBE_UNUSED(NOINLINE(static int thread_start_func_2(rb_thread_t *th, VALUE *stack_start)));
 void ruby_sigchld_handler(rb_vm_t *); /* signal.c */
 
 static void
diff --git a/thread_none.c b/thread_none.c
new file mode 100644
index 00000000000..24e8e45e104
--- /dev/null
+++ b/thread_none.c
@@ -0,0 +1,278 @@ https://github.com/ruby/ruby/blob/trunk/thread_none.c#L1
+/*
+ A thread interface implementation without any system thread.
+
+ Assumption:
+ * There is a only single thread in the ruby process
+ * No signal happens targeting the ruby process
+
+ Note:
+ * No thread switching in the VM
+ * No timer thread because thread switching won't happen
+ * No mutex guard because the VM won't be racy
+*/
+
+#ifdef THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
+
+#include <time.h>
+
+#define DEBUG_OUT() (void)(0);
+
+#define TIME_QUANTUM_MSEC (100)
+#define TIME_QUANTUM_USEC (TIME_QUANTUM_MSEC * 1000)
+#define TIME_QUANTUM_NSEC (TIME_QUANTUM_USEC * 1000)
+
+// Do nothing for GVL
+static void
+gvl_acquire(rb_global_vm_lock_t *gvl, rb_thread_t *th)
+{
+}
+
+static void
+gvl_release(rb_global_vm_lock_t *gvl)
+{
+}
+
+static void
+gvl_yield(rb_global_vm_lock_t *gvl, rb_thread_t *th)
+{
+}
+
+void
+rb_gvl_init(rb_global_vm_lock_t *gvl)
+{
+}
+
+static void
+gvl_destroy(rb_global_vm_lock_t *gvl)
+{
+}
+
+// Do nothing for mutex guard
+void
+rb_native_mutex_lock(rb_nativethread_lock_t *lock)
+{
+}
+
+void
+rb_native_mutex_unlock(rb_nativethread_lock_t *lock)
+{
+}
+
+int
+rb_native_mutex_trylock(rb_nativethread_lock_t *lock)
+{
+    return 0;
+}
+
+void
+rb_native_mutex_initialize(rb_nativethread_lock_t *lock)
+{
+}
+
+void
+rb_native_mutex_destroy(rb_nativethread_lock_t *lock)
+{
+}
+
+void
+rb_native_cond_initialize(rb_nativethread_cond_t *cond)
+{
+}
+
+void
+rb_native_cond_destroy(rb_nativethread_cond_t *cond)
+{
+}
+
+void
+rb_native_cond_signal(rb_nativethread_cond_t *cond)
+{
+}
+
+void
+rb_native_cond_broadcast(rb_nativethread_cond_t *cond)
+{
+}
+
+void
+rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex)
+{
+}
+
+void
+rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec)
+{
+}
+
+// The only one thread in process
+static rb_thread_t *ruby_native_thread;
+
+rb_thread_t *
+ruby_thread_from_native(void)
+{
+    return ruby_native_thread;
+}
+
+int
+ruby_thread_set_native(rb_thread_t *th)
+{
+    if (th && th->ec) {
+        rb_ractor_set_current_ec(th->ractor, th->ec);
+    }
+    ruby_native_thread = th;
+    return 1; // always succeed
+}
+
+void
+Init_native_thread(rb_thread_t *th)
+{
+    // no TLS setup and no thread id setup
+    ruby_thread_set_native(th);
+    fill_thread_id_str(th);
+}
+
+static void
+native_thread_destroy(rb_thread_t *th)
+{
+}
+
+void
+ruby_init_stack(volatile VALUE *addr)
+{
+}
+
+static int
+native_thread_init_stack(rb_thread_t *th)
+{
+    return 0; // success
+}
+
+static int
+native_thread_create(rb_thread_t *th)
+{
+    th->status = THREAD_KILLED;
+    rb_ractor_living_threads_remove(th->ractor, th);
+    rb_notimplement();
+}
+
+// Do nothing for handling ubf because no other thread doesn't exist and unblock anything
+#define register_ubf_list(th) (void)(th)
+#define unregister_ubf_list(th) (void)(th)
+#define ubf_select 0
+
+inline static void
+ubf_wakeup_all_threads(void)
+{
+    return;
+}
+
+inline static int
+ubf_threads_empty(void)
+{
+    return 1; // true
+}
+
+inline static void
+ubf_list_atfork()
+{
+}
+
+inline static void
+ubf_timer_disarm(void)
+{
+}
+
+
+// No timer thread because thread switching won't happen
+#define TIMER_THREAD_CREATED_P() (1)
+inline static void
+rb_thread_create_timer_thread(void)
+{
+}
+
+void
+rb_thread_wakeup_timer_thread(int sig)
+{
+}
+
+inline static int
+native_stop_timer_thread(void)
+{
+    return 1; // success
+}
+
+inline static void
+native_reset_timer_thread(void)
+{
+}
+
+// Do nothing for thread naming
+inline static void
+native_set_thread_name(rb_thread_t *th)
+{
+}
+
+inline static void
+native_set_another_thread_name(rb_nativethread_id_t thread_id, VALUE name)
+{
+}
+
+// Don't expose native thread id for now to keep system's thread API agnostic
+#define USE_NATIVE_THREAD_NATIVE_THREAD_ID 0
+
+// No reserved fd for piping threads
+int
+rb_reserved_fd_p(int fd)
+{
+    return 0; // not reserved
+}
+
+// Don't expose native thread info for now to keep system's thread API agnostic
+rb_nativethread_id_t
+rb_nativethread_self(void)
+{
+    return NULL;
+}
+
+// Do nothing for sigwait things because of no signal assumption
+// Q(katei): is this correct description?
+int
+rb_sigwait_fd_get(const rb_thread_t *th)
+{
+    return -1;
+}
+
+NORETURN(void rb_sigwait_fd_put(rb_thread_t *, int));
+void
+rb_sigwait_fd_put(rb_thread_t *th, int fd)
+{
+    rb_bug("not implemented, should not be called rb_sigwait_fd_put");
+}
+
+NORETURN(void rb_sigwait_sleep(const rb_thread_t *, int, const rb_hrtime_t *));
+void
+rb_sigwait_sleep(const rb_thread_t *th, int sigwait_fd, const rb_hrtime_t *rel)
+{
+    rb_bug("not implemented, should not be called rb_sigwait_sleep");
+}
+
+static void
+native_sleep(rb_thread_t *th, rb_hrtime_t *rel)
+{
+    // No signal assumption allows the use of uninterruptible sleep
+    struct timespec ts;
+    (void)clock_nanosleep(CLOCK_REALTIME, 0, rb_hrtime2timespec(&ts, rel), NULL);
+}
+
+static int
+native_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, struct timeval *timeout, rb_thread_t *th)
+{
+    return rb_fd_select(n, readfds, writefds, exceptfds, timeout);
+}
+
+static VALUE
+rb_thread_start_unblock_thread(void)
+{
+    return Qfalse;
+}
+#endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */
diff --git a/thread_none.h b/thread_none.h
new file mode 100644
index 00000000000..eac2635ca73
--- /dev/null
+++ b/thread_none.h
@@ -0,0 +1,17 @@ https://github.com/ruby/ruby/blob/trunk/thread_none.h#L1
+#ifndef RUBY_THREAD_NONE_H
+#define RUBY_THREAD_NONE_H
+
+#define RB_NATIVETHREAD_LOCK_INIT (void)(0)
+#define RB_NATIVETHREAD_COND_INIT (void)(0)
+
+// no-thread impl doesn't use TLS but define this to avoid using tls key
+// based implementation in vm.c
+#define RB_THREAD_LOCAL_SPECIFIER
+
+typedef struct native_thread_data_struct {} native_thread_data_t;
+
+typedef struct rb_global_vm_lock_struct {} rb_global_vm_lock_t;
+
+RUBY_EXTERN struct rb_execution_context_struct *ruby_current_ec;
+
+#endif /* RUBY_THREAD_NONE_H */
diff --git a/tool/m4/ruby_thread.m4 b/tool/m4/ruby_thread.m4
index 3831bc4c061..2e58eddb988 100644
--- a/tool/m4/ruby_thread.m4
+++ b/tool/m4/ruby_thread.m4
@@ -8,6 +8,9 @@ AC_ARG_WITH(thread, https://github.com/ruby/ruby/blob/trunk/tool/m4/ruby_thread.m4#L8
         [mingw*], [
             THREAD_MODEL=win32
         ],
+        [wasi*], [
+            THREAD_MODEL=none
+        ],
         [
             AS_IF([test "$rb_with_pthread" = "yes"], [
                 THREAD_MODEL=pthread
@@ -19,6 +22,7 @@ AC_ARG_WITH(thread, https://github.com/ruby/ruby/blob/trunk/tool/m4/ruby_thread.m4#L22
 AS_CASE(["$THREAD_MODEL"],
 [pthread], [AC_CHECK_HEADERS(pthread.h)],
 [win32],   [],
+[none],    [],
 [""],      [AC_MSG_ERROR(thread model is missing)],
            [AC_MSG_ERROR(unknown thread model $THREAD_MODEL)])
 
-- 
cgit v1.2.1


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

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