Ruby 4.1.0dev (2026-04-04 revision 3b6245536cf55da9e8bfcdb03c845fe9ef931d7f)
thread_pthread.h (3b6245536cf55da9e8bfcdb03c845fe9ef931d7f)
1#ifndef RUBY_THREAD_PTHREAD_H
2#define RUBY_THREAD_PTHREAD_H
3/**********************************************************************
4
5 thread_pthread.h -
6
7 $Author$
8
9 Copyright (C) 2004-2007 Koichi Sasada
10
11**********************************************************************/
12
13#ifdef HAVE_PTHREAD_NP_H
14#include <pthread_np.h>
15#endif
16
17#define RB_NATIVETHREAD_LOCK_INIT PTHREAD_MUTEX_INITIALIZER
18#define RB_NATIVETHREAD_COND_INIT PTHREAD_COND_INITIALIZER
19
20// TLS can not be accessed across .so on arm64 and perhaps ppc64le too.
21#if defined(__arm64__) || defined(__aarch64__) || defined(__powerpc64__)
22# define RB_THREAD_CURRENT_EC_NOINLINE
23#endif
24
25// this data should be protected by timer_th.waiting_lock
27 enum thread_sched_waiting_flag {
28 thread_sched_waiting_none = 0x00,
29 thread_sched_waiting_timeout = 0x01,
30 thread_sched_waiting_io_read = 0x02,
31 thread_sched_waiting_io_write = 0x08,
32 thread_sched_waiting_io_force = 0x40, // ignore readable
33 } flags;
34
35 struct {
36 // should be compat with hrtime.h
37#ifdef MY_RUBY_BUILD_MAY_TIME_TRAVEL
38 int128_t timeout;
39#else
40 uint64_t timeout;
41#endif
42 uint32_t event_serial;
43 int fd; // -1 for timeout only
44 int result;
45 } data;
46
47 // connected to timer_th.waiting
48 struct ccan_list_node node;
49};
50
51// per-Thread scheduler helper data
53 struct {
54 struct ccan_list_node ubf;
55
56 // connected to ractor->threads.sched.reqdyq
57 // locked by ractor->threads.sched.lock
58 struct ccan_list_node readyq;
59 // Indicates whether thread is on the readyq.
60 // There is no clear relationship between this and th->status.
61 bool is_ready;
62
63 // connected to vm->ractor.sched.timeslice_threads
64 // locked by vm->ractor.sched.lock
65 struct ccan_list_node timeslice_threads;
66
67 // connected to vm->ractor.sched.running_threads
68 // locked by vm->ractor.sched.lock
69 struct ccan_list_node running_threads;
70
71 // connected to vm->ractor.sched.zombie_threads
72 struct ccan_list_node zombie_threads;
73 } node;
74
75 struct rb_thread_sched_waiting waiting_reason;
76 uint32_t event_serial;
77
78 bool finished;
79 bool malloc_stack;
80 void *context_stack;
81 size_t context_stack_size;
82 struct coroutine_context *context;
83};
84
85struct rb_native_thread {
86 rb_atomic_t serial;
87 struct rb_vm_struct *vm;
88
89 rb_nativethread_id_t thread_id;
90
91#ifdef RB_THREAD_T_HAS_NATIVE_ID
92 int tid;
93#endif
94
95 struct rb_thread_struct *running_thread;
96
97 // to control native thread
98#if defined(__GLIBC__) || defined(__FreeBSD__)
99 union
100#else
101 /*
102 * assume the platform condvars are badly implemented and have a
103 * "memory" of which mutex they're associated with
104 */
105 struct
106#endif
107 {
108 rb_nativethread_cond_t intr; /* th->interrupt_lock */
109 rb_nativethread_cond_t readyq; /* use sched->lock */
110 } cond;
111
112#ifdef USE_SIGALTSTACK
113 void *altstack;
114#endif
115
116 struct coroutine_context *nt_context;
117 int dedicated;
118
119 size_t machine_stack_maxsize;
120};
121
122#undef except
123#undef try
124#undef leave
125#undef finally
126
127// per-Ractor
128struct rb_thread_sched {
129 rb_nativethread_lock_t lock_;
130#if VM_CHECK_MODE
131 struct rb_thread_struct *lock_owner;
132#endif
133 struct rb_thread_struct *running; // running thread or NULL
134 // Most recently running thread or NULL. If this thread wakes up before the newly running
135 // thread completes the transfer of control, it can interrupt and resume running.
136 // The new thread clears this field when it takes control.
137 struct rb_thread_struct *runnable_hot_th;
138 int runnable_hot_th_waiting;
139 bool is_running;
140 bool is_running_timeslice;
141 bool enable_mn_threads;
142
143 struct ccan_list_head readyq;
144 int readyq_cnt;
145 // ractor scheduling
146 struct ccan_list_node grq_node;
147};
148
149#ifdef RB_THREAD_LOCAL_SPECIFIER
150 NOINLINE(void rb_current_ec_set(struct rb_execution_context_struct *));
151
152 # ifdef RB_THREAD_CURRENT_EC_NOINLINE
153 NOINLINE(struct rb_execution_context_struct *rb_current_ec(void));
154 # else
155 RUBY_EXTERN RB_THREAD_LOCAL_SPECIFIER struct rb_execution_context_struct *ruby_current_ec;
156
157 // for RUBY_DEBUG_LOG()
158 RUBY_EXTERN RB_THREAD_LOCAL_SPECIFIER rb_atomic_t ruby_nt_serial;
159 #define RUBY_NT_SERIAL 1
160 # endif
161#else
162typedef pthread_key_t native_tls_key_t;
163
164static inline void *
165native_tls_get(native_tls_key_t key)
166{
167 // return value should be checked by caller
168 return pthread_getspecific(key);
169}
170
171static inline void
172native_tls_set(native_tls_key_t key, void *ptr)
173{
174 if (UNLIKELY(pthread_setspecific(key, ptr) != 0)) {
175 rb_bug("pthread_setspecific error");
176 }
177}
178
179RUBY_EXTERN native_tls_key_t ruby_current_ec_key;
180#endif
181
182struct rb_ractor_struct;
183void rb_ractor_sched_wait(struct rb_execution_context_struct *ec, struct rb_ractor_struct *cr, rb_unblock_function_t *ubf, void *ptr);
184void rb_ractor_sched_wakeup(struct rb_ractor_struct *r, struct rb_thread_struct *th);
185
186#endif /* RUBY_THREAD_PTHREAD_H */
std::atomic< unsigned > rb_atomic_t
Type that is eligible for atomic operations.
Definition atomic.h:69
#define RUBY_EXTERN
Declaration of externally visible global variables.
Definition dllexport.h:45
void rb_unblock_function_t(void *)
This is the type of UBFs.
Definition thread.h:336