Ruby 3.5.0dev (2025-07-02 revision 29657a1ecb2a546a8b1a2a46c6fc0fe163b83a6c)
thread_none.c (29657a1ecb2a546a8b1a2a46c6fc0fe163b83a6c)
1/*
2 A thread interface implementation without any system thread.
3
4 Assumption:
5 * There is a only single thread in the ruby process
6 * No signal happens targeting the ruby process
7
8 Note:
9 * No thread switching in the VM
10 * No timer thread because thread switching won't happen
11 * No mutex guard because the VM won't be racy
12*/
13
14#ifdef THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
15
16#include <time.h>
17
18#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
19# include "wasm/machine.h"
20#endif
21
22// Do nothing for GVL
23static void
24thread_sched_to_running(struct rb_thread_sched *sched, rb_thread_t *th)
25{
26}
27
28static void
29thread_sched_to_waiting(struct rb_thread_sched *sched, rb_thread_t *th)
30{
31}
32
33#define thread_sched_to_dead thread_sched_to_waiting
34
35static void
36thread_sched_yield(struct rb_thread_sched *sched, rb_thread_t *th)
37{
38}
39
40void
41rb_thread_sched_init(struct rb_thread_sched *sched, bool atfork)
42{
43}
44
45#if 0
46static void
47rb_thread_sched_destroy(struct rb_thread_sched *sched)
48{
49}
50#endif
51
52// Do nothing for mutex guard
53void
54rb_native_mutex_lock(rb_nativethread_lock_t *lock)
55{
56}
57
58void
59rb_native_mutex_unlock(rb_nativethread_lock_t *lock)
60{
61}
62
63int
64rb_native_mutex_trylock(rb_nativethread_lock_t *lock)
65{
66 return 0;
67}
68
69void
70rb_native_mutex_initialize(rb_nativethread_lock_t *lock)
71{
72}
73
74void
75rb_native_mutex_destroy(rb_nativethread_lock_t *lock)
76{
77}
78
79void
80rb_native_cond_initialize(rb_nativethread_cond_t *cond)
81{
82}
83
84void
85rb_native_cond_destroy(rb_nativethread_cond_t *cond)
86{
87}
88
89void
90rb_native_cond_signal(rb_nativethread_cond_t *cond)
91{
92}
93
94void
95rb_native_cond_broadcast(rb_nativethread_cond_t *cond)
96{
97}
98
99void
100rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex)
101{
102}
103
104void
105rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec)
106{
107}
108
109// The only one thread in process
110static rb_thread_t *ruby_native_thread;
111
113ruby_thread_from_native(void)
114{
115 return ruby_native_thread;
116}
117
118int
119ruby_thread_set_native(rb_thread_t *th)
120{
121 if (th && th->ec) {
122 rb_ractor_set_current_ec(th->ractor, th->ec);
123 }
124 ruby_native_thread = th;
125 return 1; // always succeed
126}
127
128void
129Init_native_thread(rb_thread_t *main_th)
130{
131 // no TLS setup and no thread id setup
132 ruby_thread_set_native(main_th);
133}
134
135void
136ruby_mn_threads_params(void)
137{
138}
139
140static void
141native_thread_destroy_atfork(struct rb_native_thread *nt)
142{
143 /* no-op */
144}
145
146static int
147native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame)
148{
149#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
150 th->ec->machine.stack_start = (VALUE *)rb_wasm_stack_get_base();
151#endif
152 return 0; // success
153}
154
155static int
156native_thread_create(rb_thread_t *th)
157{
158 th->status = THREAD_KILLED;
159 rb_ractor_living_threads_remove(th->ractor, th);
161}
162
163// Do nothing for handling ubf because no other thread doesn't exist and unblock anything
164#define register_ubf_list(th) (void)(th)
165#define unregister_ubf_list(th) (void)(th)
166#define ubf_select 0
167
168inline static void
169ubf_wakeup_all_threads(void)
170{
171 return;
172}
173
174inline static int
175ubf_threads_empty(void)
176{
177 return 1; // true
178}
179
180inline static void
181ubf_list_atfork()
182{
183}
184
185inline static void
186ubf_timer_disarm(void)
187{
188}
189
190
191// No timer thread because thread switching won't happen
192#define TIMER_THREAD_CREATED_P() (1)
193inline static void
194rb_thread_create_timer_thread(void)
195{
196}
197
198void
199rb_thread_wakeup_timer_thread(int sig)
200{
201}
202
203inline static int
204native_stop_timer_thread(void)
205{
206 return 1; // success
207}
208
209inline static void
210native_reset_timer_thread(void)
211{
212}
213
214// Do nothing for thread naming
215inline static void
216native_set_thread_name(rb_thread_t *th)
217{
218}
219
220inline static void
221native_set_another_thread_name(rb_nativethread_id_t thread_id, VALUE name)
222{
223}
224
225// Don't expose native thread id for now to keep system's thread API agnostic
226#define USE_NATIVE_THREAD_NATIVE_THREAD_ID 0
227
228// No reserved fd for piping threads
229int
230rb_reserved_fd_p(int fd)
231{
232 return 0; // not reserved
233}
234
235// Don't expose native thread info for now to keep system's thread API agnostic
236rb_nativethread_id_t
238{
239 return NULL;
240}
241
242// Do nothing for sigwait things because of no signal assumption
243// Q(katei): is this correct description?
244int
245rb_sigwait_fd_get(const rb_thread_t *th)
246{
247 return -1;
248}
249
250NORETURN(void rb_sigwait_fd_put(rb_thread_t *, int));
251void
252rb_sigwait_fd_put(rb_thread_t *th, int fd)
253{
254 rb_bug("not implemented, should not be called rb_sigwait_fd_put");
255}
256
257NORETURN(void rb_sigwait_sleep(const rb_thread_t *, int, const rb_hrtime_t *));
258void
259rb_sigwait_sleep(const rb_thread_t *th, int sigwait_fd, const rb_hrtime_t *rel)
260{
261 rb_bug("not implemented, should not be called rb_sigwait_sleep");
262}
263
264static void
265native_sleep(rb_thread_t *th, rb_hrtime_t *rel)
266{
267 // No signal assumption allows the use of uninterruptible sleep
268 struct timespec ts;
269 (void)clock_nanosleep(CLOCK_REALTIME, 0, rb_hrtime2timespec(&ts, rel), NULL);
270}
271
272static int
273native_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, struct timeval *timeout, rb_thread_t *th)
274{
275 return rb_fd_select(n, readfds, writefds, exceptfds, timeout);
276}
277
278static bool
279th_has_dedicated_nt(const rb_thread_t *th)
280{
281 return true;
282}
283
284void
285rb_add_running_thread(rb_thread_t *th)
286{
287 // do nothing
288}
289
290void
291rb_del_running_thread(rb_thread_t *th)
292{
293 // do nothing
294}
295
296void
297rb_threadptr_sched_free(rb_thread_t *th)
298{
299 // do nothing
300}
301
302void
303rb_ractor_sched_barrier_start(rb_vm_t *vm, rb_ractor_t *cr)
304{
305 // do nothing
306}
307
308void
309rb_ractor_sched_barrier_join(rb_vm_t *vm, rb_ractor_t *cr)
310{
311 // do nothing
312}
313
314void
315rb_threadptr_remove(rb_thread_t *th)
316{
317 // do nothing
318}
319
320void
321rb_thread_sched_mark_zombies(rb_vm_t *vm)
322{
323 // do nothing
324}
325
326bool
328{
329 return false;
330}
331
332void *
333rb_thread_prevent_fork(void *(*func)(void *), void *data)
334{
335 return func(data);
336}
337
338#endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */
void rb_notimplement(void)
Definition error.c:3836
int rb_reserved_fd_p(int fd)
Queries if the given FD is reserved or not.
bool rb_thread_lock_native_thread(void)
Declare the current Ruby thread should acquire a dedicated native thread on M:N thread scheduler.
#define rb_fd_select
Waits for multiple file descriptors at once.
Definition posix.h:66
The data structure which wraps the fd_set bitmap used by select(2).
Definition largesize.h:71
rb_nativethread_id_t rb_nativethread_self(void)
Queries the ID of the native thread that is calling this function.
void rb_native_mutex_lock(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_lock.
void rb_native_cond_initialize(rb_nativethread_cond_t *cond)
Fills the passed condition variable with an initial value.
int rb_native_mutex_trylock(rb_nativethread_lock_t *lock)
Identical to rb_native_mutex_lock(), except it doesn't block in case rb_native_mutex_lock() would.
void rb_native_cond_broadcast(rb_nativethread_cond_t *cond)
Signals a condition variable.
void rb_native_mutex_initialize(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_initialize.
void rb_native_mutex_unlock(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_unlock.
void rb_native_mutex_destroy(rb_nativethread_lock_t *lock)
Just another name of rb_nativethread_lock_destroy.
void rb_native_cond_destroy(rb_nativethread_cond_t *cond)
Destroys the passed condition variable.
void rb_native_cond_signal(rb_nativethread_cond_t *cond)
Signals a condition variable.
void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex)
Waits for the passed condition variable to be signalled.
void rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec)
Identical to rb_native_cond_wait(), except it additionally takes timeout in msec resolution.
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40