54 #undef _FORTIFY_SOURCE
55 #undef __USE_FORTIFY_LEVEL
56 #define __USE_FORTIFY_LEVEL 0
67 #ifndef USE_NATIVE_THREAD_PRIORITY
68 #define USE_NATIVE_THREAD_PRIORITY 0
69 #define RUBY_THREAD_PRIORITY_MAX 3
70 #define RUBY_THREAD_PRIORITY_MIN -3
74 #define THREAD_DEBUG 0
93 #define eKillSignal INT2FIX(0)
94 #define eTerminateSignal INT2FIX(1)
97 #define closed_stream_error GET_VM()->special_exceptions[ruby_error_closed_stream]
107 #define THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
123 #define RB_GC_SAVE_MACHINE_REGISTER_STACK(th) \
124 do{(th)->machine.register_stack_end = rb_ia64_bsp();}while(0)
126 #define RB_GC_SAVE_MACHINE_REGISTER_STACK(th)
128 #define RB_GC_SAVE_MACHINE_CONTEXT(th) \
130 FLUSH_REGISTER_WINDOWS; \
131 RB_GC_SAVE_MACHINE_REGISTER_STACK(th); \
132 setjmp((th)->machine.regs); \
133 SET_MACHINE_STACK_END(&(th)->machine.stack_end); \
136 #define GVL_UNLOCK_BEGIN() do { \
137 rb_thread_t *_th_stored = GET_THREAD(); \
138 RB_GC_SAVE_MACHINE_CONTEXT(_th_stored); \
139 gvl_release(_th_stored->vm);
141 #define GVL_UNLOCK_END() \
142 gvl_acquire(_th_stored->vm, _th_stored); \
143 rb_thread_set_current(_th_stored); \
147 #define only_if_constant(expr, notconst) (__builtin_constant_p(expr) ? (expr) : (notconst))
149 #define only_if_constant(expr, notconst) notconst
151 #define BLOCKING_REGION(exec, ubf, ubfarg, fail_if_interrupted) do { \
152 rb_thread_t *__th = GET_THREAD(); \
153 struct rb_blocking_region_buffer __region; \
154 if (blocking_region_begin(__th, &__region, (ubf), (ubfarg), fail_if_interrupted) || \
156 !only_if_constant(fail_if_interrupted, TRUE)) { \
158 blocking_region_end(__th, &__region); \
163 #ifdef HAVE_VA_ARGS_MACRO
164 void rb_thread_debug(
const char *file,
int line,
const char *
fmt, ...);
165 #define thread_debug(fmt, ...) rb_thread_debug(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
166 #define POSITION_FORMAT "%s:%d:"
167 #define POSITION_ARGS ,file, line
169 void rb_thread_debug(
const char *
fmt, ...);
170 #define thread_debug rb_thread_debug
171 #define POSITION_FORMAT
172 #define POSITION_ARGS
175 # if THREAD_DEBUG < 0
176 static int rb_thread_debug_enabled;
187 rb_thread_s_debug(
void)
189 return INT2NUM(rb_thread_debug_enabled);
203 rb_thread_debug_enabled =
RTEST(val) ?
NUM2INT(val) : 0;
207 # define rb_thread_debug_enabled THREAD_DEBUG
210 #define thread_debug if(0)printf
214 #define thread_start_func_2(th, st, rst) thread_start_func_2(th, st)
217 VALUE *register_stack_start));
223 #define DEBUG_OUT() \
224 WaitForSingleObject(&debug_mutex, INFINITE); \
225 printf(POSITION_FORMAT"%p - %s" POSITION_ARGS, GetCurrentThreadId(), buf); \
227 ReleaseMutex(&debug_mutex);
229 #elif defined(HAVE_PTHREAD_H)
232 #define DEBUG_OUT() \
233 pthread_mutex_lock(&debug_mutex); \
234 printf(POSITION_FORMAT"%#"PRIxVALUE" - %s" POSITION_ARGS, (VALUE)pthread_self(), buf); \
236 pthread_mutex_unlock(&debug_mutex);
239 #error "unsupported thread type"
243 static int debug_mutex_initialized = 1;
248 #ifdef HAVE_VA_ARGS_MACRO
249 const char *file,
int line,
251 const char *
fmt, ...)
256 if (!rb_thread_debug_enabled)
return;
258 if (debug_mutex_initialized == 1) {
259 debug_mutex_initialized = 0;
260 native_mutex_initialize(&debug_mutex);
282 native_mutex_initialize(lock);
288 native_mutex_destroy(lock);
294 native_mutex_lock(lock);
300 native_mutex_unlock(lock);
308 if (fail_if_interrupted) {
377 if (th != main_thread) {
383 thread_debug(
"terminate_i: main thread (%p)\n", (
void *)th);
416 if (err)
rb_bug(
"invalid keeping_mutexes: %s", err);
427 rb_bug(
"rb_thread_terminate_all: called by child thread (%p, %p)",
435 thread_debug(
"rb_thread_terminate_all (main thread: %p)\n", (
void *)th);
470 th->
machine.register_stack_start = th->
machine.register_stack_end = 0;
491 native_thread_destroy(th);
499 native_thread_init_stack(th);
511 # ifdef USE_SIGALTSTACK
514 rb_register_sigaltstack(th);
518 rb_bug(
"thread_start_func_2 must not be used for main thread");
520 ruby_thread_set_native(th);
524 th->
machine.register_stack_start = register_stack_start;
528 gvl_acquire(th->
vm, th);
530 thread_debug(
"thread start (get lock): %p\n", (
void *)th);
583 rb_bug(
"thread_start_func_2: locking_mutex must not be set (%p:%"PRIxVALUE")",
603 join_list = join_list->
next;
614 native_mutex_lock(&
th->vm->thread_destruct_lock);
616 th->vm->running_thread =
NULL;
617 native_mutex_unlock(&
th->vm->thread_destruct_lock);
632 "can't start a new thread (frozen ThreadGroup)");
652 native_cond_initialize(&th->
interrupt_cond, RB_CONDATTR_CLOCK_MONOTONIC);
655 err = native_thread_create(th);
752 #define DELAY_INFTY 1E30
770 if ((*p)->th ==
th) {
813 if (th == target_th) {
816 if (
GET_VM()->main_thread == target_th) {
856 return target_th->
self;
955 #if SIGNEDNESS_OF_TIME_T < 0
956 # define TIMEVAL_SEC_MAX SIGNED_INTEGER_MAX(TYPEOF_TIMEVAL_TV_SEC)
957 # define TIMEVAL_SEC_MIN SIGNED_INTEGER_MIN(TYPEOF_TIMEVAL_TV_SEC)
958 #elif SIGNEDNESS_OF_TIME_T > 0
959 # define TIMEVAL_SEC_MAX ((TYPEOF_TIMEVAL_TV_SEC)(~(unsigned_time_t)0))
960 # define TIMEVAL_SEC_MIN ((TYPEOF_TIMEVAL_TV_SEC)0)
967 const double TIMEVAL_SEC_MAX_PLUS_ONE = (2*(double)(TIMEVAL_SEC_MAX/2+1));
971 if (TIMEVAL_SEC_MAX_PLUS_ONE <=
d) {
972 time.
tv_sec = TIMEVAL_SEC_MAX;
975 else if (
d <= TIMEVAL_SEC_MIN) {
976 time.
tv_sec = TIMEVAL_SEC_MIN;
998 while (th->
status == status) {
1003 native_sleep(th, 0);
1008 if (!spurious_check)
1011 th->
status = prev_status;
1017 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
1038 to.
tv_sec = TIMEVAL_SEC_MAX;
1042 if (to.
tv_sec == TIMEVAL_SEC_MAX)
1053 native_sleep(th, &tv);
1066 if (!spurious_check)
1069 th->
status = prev_status;
1089 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
1183 gvl_yield(th->
vm, th);
1211 thread_debug(
"enter blocking region (%p)\n", (
void *)th);
1213 gvl_release(th->
vm);
1224 gvl_acquire(th->
vm, th);
1226 thread_debug(
"leave blocking region (%p)\n", (
void *)th);
1227 remove_signal_thread_list(th);
1247 int saved_errno =
errno;
1252 errno = saved_errno;
1262 int saved_errno = 0;
1272 saved_errno =
errno;
1273 }, ubf, data2, fail_if_interrupted);
1275 if (!fail_if_interrupted) {
1279 errno = saved_errno;
1388 int saved_errno = 0;
1397 saved_errno =
errno;
1411 errno = saved_errno;
1421 void *(*f)(
void*) = (
void *(*)(
void*))
func;
1467 fprintf(stderr,
"[BUG] rb_thread_call_with_gvl() is called by non-ruby thread\n");
1475 rb_bug(
"rb_thread_call_with_gvl: called by a thread which has GVL.");
1572 for (i=0; i<mask_stack_len; i++) {
1573 mask = mask_stack[mask_stack_len-(i+1)];
1575 for (j=0; j<ancestors_len; j++) {
1630 switch (mask_timing) {
1952 }
while (old != interrupt);
1960 int postponed_job_interrupt = 0;
1966 int timer_interrupt;
1967 int pending_interrupt;
1975 if (postponed_job_interrupt) {
2011 if (timer_interrupt) {
2012 unsigned long limits_us = TIME_QUANTUM_USEC;
2083 #if defined(POSIX_SIGNAL) && defined(SIGSEGV) && defined(HAVE_SIGALTSTACK)
2084 #define USE_SIGALTSTACK
2091 #ifdef USE_SIGALTSTACK
2170 if (th == target_th) {
2350 "stopping only thread\n\tnote: use sleep to stop forever");
2747 str =
rb_sprintf(
"#<%s:%p %s>", cname, (
void *)thread, status);
2836 if (!
id)
return Qnil;
2923 if (!
id)
return Qnil;
3094 if (!
RHASH(locals)->ntbl)
3162 #if USE_NATIVE_THREAD_PRIORITY
3164 native_thread_apply_priority(th);
3180 #if defined(NFDBITS) && defined(HAVE_RB_FD_INIT)
3217 fds->fdset =
ALLOC(fd_set);
3218 FD_ZERO(fds->fdset);
3224 size_t size = howmany(
rb_fd_max(src), NFDBITS) *
sizeof(fd_mask);
3226 if (size <
sizeof(fd_set))
3227 size =
sizeof(fd_set);
3228 dst->maxfd = src->maxfd;
3230 memcpy(dst->fdset, src->fdset, size);
3236 if (fds->fdset)
xfree(fds->fdset);
3245 MEMZERO(fds->fdset, fd_mask, howmany(fds->maxfd, NFDBITS));
3251 size_t m = howmany(n + 1, NFDBITS) *
sizeof(fd_mask);
3252 size_t o = howmany(fds->maxfd, NFDBITS) *
sizeof(fd_mask);
3254 if (m <
sizeof(fd_set)) m =
sizeof(fd_set);
3255 if (o <
sizeof(fd_set)) o =
sizeof(fd_set);
3258 fds->fdset =
xrealloc(fds->fdset, m);
3259 memset((
char *)fds->fdset + o, 0, m - o);
3261 if (n >= fds->maxfd) fds->maxfd = n + 1;
3274 if (n >= fds->maxfd)
return;
3281 if (n >= fds->maxfd)
return 0;
3282 return FD_ISSET(n, fds->fdset) != 0;
3288 size_t size = howmany(max, NFDBITS) *
sizeof(fd_mask);
3290 if (size <
sizeof(fd_set)) size =
sizeof(fd_set);
3292 dst->fdset =
xrealloc(dst->fdset, size);
3293 memcpy(dst->fdset, src, size);
3299 size_t size = howmany(
rb_fd_max(src), NFDBITS) *
sizeof(fd_mask);
3301 if (size >
sizeof(fd_set)) {
3310 size_t size = howmany(
rb_fd_max(src), NFDBITS) *
sizeof(fd_mask);
3312 if (size <
sizeof(fd_set))
3313 size =
sizeof(fd_set);
3314 dst->maxfd = src->maxfd;
3315 dst->fdset =
xrealloc(dst->fdset, size);
3316 memcpy(dst->fdset, src->fdset, size);
3319 #ifdef __native_client__
3320 int select(
int nfds, fd_set *readfds, fd_set *writefds,
3321 fd_set *exceptfds,
struct timeval *timeout);
3340 return select(n, r, w, e, timeout);
3348 #define FD_ZERO(f) rb_fd_zero(f)
3349 #define FD_SET(i, f) rb_fd_set((i), (f))
3350 #define FD_CLR(i, f) rb_fd_clr((i), (f))
3351 #define FD_ISSET(i, f) rb_fd_isset((i), (f))
3353 #elif defined(_WIN32)
3358 set->capa = FD_SETSIZE;
3359 set->fdset =
ALLOC(fd_set);
3360 FD_ZERO(set->fdset);
3377 if (max > FD_SETSIZE || (UINT)max > dst->fd_count) {
3381 memcpy(dst->fd_array, src->fdset->fd_array, max);
3382 dst->fd_count =
max;
3399 for (i = 0; i < set->fdset->fd_count; i++) {
3400 if (set->fdset->fd_array[i] == s) {
3404 if (set->fdset->fd_count >= (
unsigned)set->capa) {
3405 set->capa = (set->fdset->fd_count / FD_SETSIZE + 1) * FD_SETSIZE;
3406 set->fdset =
xrealloc(set->fdset,
sizeof(
unsigned int) +
sizeof(SOCKET) * set->capa);
3408 set->fdset->fd_array[set->fdset->fd_count++] =
s;
3416 #define FD_ZERO(f) rb_fd_zero(f)
3417 #define FD_SET(i, f) rb_fd_set((i), (f))
3418 #define FD_CLR(i, f) rb_fd_clr((i), (f))
3419 #define FD_ISSET(i, f) rb_fd_isset((i), (f))
3422 #define rb_fd_rcopy(d, s) (*(d) = *(s))
3440 limit += (double)timeout->
tv_sec+(
double)timeout->
tv_usec*1e-6;
3441 wait_rest = *timeout;
3442 timeout = &wait_rest;
3456 result = native_fd_select(n, read, write, except, timeout, th);
3480 wait_rest.
tv_sec = (time_t)d;
3508 thread_debug(
"rb_thread_wait_fd_rw(%d, %s)\n", fd, read ?
"read" :
"write");
3519 thread_debug(
"rb_thread_wait_fd_rw(%d, %s): done\n", fd, read ?
"read" :
"write");
3583 if (!read && !write && !except) {
3601 return do_select(max, read, write, except, timeout);
3609 #if defined(HAVE_POLL) && defined(__linux__)
3616 #define POLLIN_SET (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR)
3617 #define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
3618 #define POLLEX_SET (POLLPRI)
3623 ppoll(
struct pollfd *fds, nfds_t nfds,
3624 const struct timespec *ts,
const sigset_t *sigmask)
3631 if (ts->
tv_sec > TIMET_MAX/1000)
3635 tmp2 = ts->
tv_nsec / (1000 * 1000);
3636 if (TIMET_MAX - tmp < tmp2)
3639 timeout_ms = tmp + tmp2;
3645 return poll(fds, nfds, timeout_ms);
3671 fds.events = (short)events;
3676 result = ppoll(&fds, 1, timeout,
NULL);
3677 if (result < 0) lerrno =
errno;
3704 if (fds.revents & POLLNVAL) {
3714 if (fds.revents & POLLIN_SET)
3716 if (fds.revents & POLLOUT_SET)
3718 if (fds.revents & POLLEX_SET)
3804 #ifdef USE_CONSERVATIVE_STACK_END
3809 *stack_end_p = &stack_end;
3849 if (vm->prove_profile.enable) {
3852 if (vm->during_gc) {
3862 if (timer_thread_id && native_stop_timer_thread(close_anyway)) {
3863 native_reset_timer_thread();
3870 native_reset_timer_thread();
3877 rb_thread_create_timer_thread();
3898 if (
RTEST(coverages)) {
3971 return ptr ?
sizeof(
struct thgroup) : 0;
4153 "can't move from the enclosed thread group");
4186 #define GetMutexPtr(obj, tobj) \
4187 TypedData_Get_Struct((obj), rb_mutex_t, &mutex_data_type, (tobj))
4189 #define mutex_mark NULL
4199 if (err)
rb_bug(
"%s", err);
4201 native_mutex_destroy(&mutex->
lock);
4202 native_cond_destroy(&mutex->
cond);
4237 native_mutex_initialize(&mutex->
lock);
4238 native_cond_initialize(&mutex->
cond, RB_CONDATTR_CLOCK_MONOTONIC);
4300 native_mutex_lock(&mutex->
lock);
4301 if (mutex->
th == 0) {
4307 native_mutex_unlock(&mutex->
lock);
4315 int interrupted = 0;
4338 timeout_rel.
tv_nsec = timeout_ms * 1000 * 1000;
4339 timeout = native_cond_timeout(&mutex->
cond, timeout_rel);
4340 err = native_cond_timedwait(&mutex->
cond, &mutex->
lock, &timeout);
4343 native_cond_wait(&mutex->
cond, &mutex->
lock);
4356 native_mutex_lock(&mutex->
lock);
4358 native_cond_broadcast(&mutex->
cond);
4359 native_mutex_unlock(&mutex->
lock);
4393 while (mutex->
th != th) {
4396 volatile int timeout_ms = 0;
4403 native_mutex_lock(&mutex->
lock);
4417 interrupted =
lock_func(th, mutex, (
int)timeout_ms);
4418 native_mutex_unlock(&mutex->
lock);
4421 if (patrol_thread == th)
4422 patrol_thread =
NULL;
4427 if (mutex->
th && interrupted == 2) {
4431 th->
status = prev_status;
4461 if (mutex->
th == th)
4472 native_mutex_lock(&mutex->
lock);
4474 if (mutex->
th == 0) {
4475 err =
"Attempt to unlock a mutex which is not locked";
4477 else if (mutex->
th != th) {
4478 err =
"Attempt to unlock a mutex which is locked by another thread";
4483 native_cond_signal(&mutex->
cond);
4486 native_mutex_unlock(&mutex->
lock);
4490 while (*th_mutex != mutex) {
4537 if (mutex->
th == th)
4576 if (!
NIL_P(timeout)) {
4581 if (
NIL_P(timeout)) {
4587 end =
time(0) - beg;
4675 #define GetThreadShieldPtr(obj) ((VALUE)rb_check_typeddata((obj), &thread_shield_data_type))
4676 #define THREAD_SHIELD_WAITING_MASK (FL_USER0|FL_USER1|FL_USER2|FL_USER3|FL_USER4|FL_USER5|FL_USER6|FL_USER7|FL_USER8|FL_USER9|FL_USER10|FL_USER11|FL_USER12|FL_USER13|FL_USER14|FL_USER15|FL_USER16|FL_USER17|FL_USER18|FL_USER19)
4677 #define THREAD_SHIELD_WAITING_SHIFT (FL_USHIFT)
4678 #define rb_thread_shield_waiting(b) (int)((RBASIC(b)->flags&THREAD_SHIELD_WAITING_MASK)>>THREAD_SHIELD_WAITING_SHIFT)
4706 return thread_shield;
4723 if (!mutex)
return Qfalse;
4821 #if SIZEOF_LONG == SIZEOF_VOIDP
4822 #define OBJ_ID_EQL(obj_id, other) ((obj_id) == (other))
4823 #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
4824 #define OBJ_ID_EQL(obj_id, other) (RB_TYPE_P((obj_id), T_BIGNUM) ? \
4825 rb_big_eql((obj_id), (other)) : ((obj_id) == (other)))
4831 if (paired_obj_id) {
4866 VALUE other_paired_obj = pair_list;
4888 if (pair_list ==
Qundef) {
4945 if (outer && !outermost) {
4959 if (!
recursive_pop(p.list, p.objid, p.pairid))
goto invalid;
4960 if (!
recursive_pop(p.list, ID2SYM(recursive_key), 0))
goto invalid;
4962 if (result == p.list) {
5082 #define rb_intern(str) rb_intern_const(str)
5104 #if THREAD_DEBUG < 0
5170 recursive_key =
rb_intern(
"__recursive_key__");
5179 gvl_acquire(th->
vm, th);
5183 RB_CONDATTR_CLOCK_MONOTONIC);
5193 rb_thread_create_timer_thread();
5196 (
void)native_mutex_trylock;
5221 native_mutex_lock(&mutex->
lock);
5225 native_mutex_unlock(&mutex->
lock);
5231 #ifdef DEBUG_DEADLOCK_CHECK
5244 native_mutex_lock(&mutex->
lock);
5246 native_mutex_unlock(&mutex->
lock);
5262 if (patrol_thread && patrol_thread !=
GET_THREAD())
return;
5269 argv[1] =
rb_str_new2(
"No live threads left. Deadlock?");
5270 #ifdef DEBUG_DEADLOCK_CHECK
5283 if (coverage &&
RBASIC(coverage)->klass == 0) {
5299 return GET_VM()->coverages;
5305 GET_VM()->coverages = coverages;
5341 err =
kill(pid, sig);
static int vm_living_thread_num(rb_vm_t *vm)
#define RB_TYPE_P(obj, type)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
VALUE rb_mutex_locked_p(VALUE mutex)
void rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th)
rb_thread_list_t * join_list
static VALUE thgroup_enclose(VALUE group)
rb_nativethread_cond_t cond
static VALUE rb_thread_variable_p(VALUE thread, VALUE key)
#define RUBY_VM_CHECK_INTS(th)
unsigned long running_time_us
#define RUBY_EVENT_THREAD_END
#define rb_fd_init_copy(d, s)
VALUE rb_exc_new(VALUE etype, const char *ptr, long len)
static VALUE thgroup_add(VALUE group, VALUE thread)
static int check_deadlock_i(st_data_t key, st_data_t val, int *found)
#define RUBY_EVENT_THREAD_BEGIN
VALUE rb_thread_main(void)
int ruby_thread_has_gvl_p(void)
VALUE rb_ary_pop(VALUE ary)
VALUE rb_get_coverages(void)
static VALUE rb_thread_s_handle_interrupt(VALUE self, VALUE mask_arg)
static const rb_thread_t * patrol_thread
struct rb_mutex_struct * next_mutex
void ruby_thread_stack_overflow(rb_thread_t *th)
void rb_bug(const char *fmt,...)
static VALUE rb_thread_priority(VALUE thread)
int gettimeofday(struct timeval *, struct timezone *)
void rb_postponed_job_flush(rb_vm_t *vm)
RUBY_EXTERN VALUE rb_cModule
static int lock_func(rb_thread_t *th, rb_mutex_t *mutex, int timeout_ms)
static const char * rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t volatile *th)
static void thread_cleanup_func_before_exec(void *th_ptr)
static VALUE trap(int sig, sighandler_t func, VALUE command)
struct rb_thread_struct * running_thread
VALUE rb_make_exception(int argc, VALUE *argv)
void rb_thread_wait_fd(int)
void rb_thread_atfork_before_exec(void)
const char * rb_obj_classname(VALUE)
void rb_nativethread_lock_unlock(rb_nativethread_lock_t *lock)
#define RUBY_VM_SET_INTERRUPT(th)
static VALUE rb_thread_abort_exc_set(VALUE thread, VALUE val)
VALUE rb_proc_location(VALUE self)
int pending_interrupt_queue_checked
static void rb_mutex_abandon_all(rb_mutex_t *mutexes)
struct rb_blocking_region_buffer * rb_thread_blocking_region_begin(void)
static int max(int a, int b)
int st_lookup(st_table *, st_data_t, st_data_t *)
VALUE(* func)(VALUE, VALUE, int)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
static VALUE thgroup_enclosed_p(VALUE group)
void rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing)
VALUE rb_thread_list(void)
#define GetProcPtr(obj, ptr)
static VALUE thread_join_sleep(VALUE arg)
VALUE rb_blocking_function_t(void *)
st_table * st_init_numtable(void)
static int terminate_atfork_before_exec_i(st_data_t key, st_data_t val, st_data_t current_th)
void ruby_kill(rb_pid_t pid, int sig)
void rb_thread_blocking_region_end(struct rb_blocking_region_buffer *region)
static VALUE rb_thread_variables(VALUE thread)
struct rb_thread_struct * th
VALUE rb_ary_delete_at(VALUE ary, long pos)
SSL_METHOD *(* func)(void)
rb_unblock_function_t * func
static void update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
static VALUE thread_s_new(int argc, VALUE *argv, VALUE klass)
void rb_error_frozen(const char *what)
VALUE pending_interrupt_mask_stack
VALUE rb_ary_shift(VALUE ary)
static VALUE threadptr_local_aref(rb_thread_t *th, ID id)
VALUE rb_mod_ancestors(VALUE mod)
static VALUE mutex_initialize(VALUE self)
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
VALUE rb_hash_lookup2(VALUE, VALUE, VALUE)
static void rb_mutex_abandon_keeping_mutexes(rb_thread_t *th)
void rb_threadptr_signal_raise(rb_thread_t *th, int sig)
struct rb_thread_struct volatile * th
static struct timeval double2timeval(double d)
SOCKET rb_w32_get_osfhandle(int)
#define TH_JUMP_TAG(th, st)
static VALUE mutex_alloc(VALUE klass)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
static const rb_data_type_t mutex_data_type
VALUE rb_ary_push(VALUE ary, VALUE item)
VALUE rb_mutex_lock(VALUE mutex)
st_table * living_threads
void rb_signal_exec(rb_thread_t *th, int sig)
static int handle_interrupt_arg_check_i(VALUE key, VALUE val)
VALUE rb_ary_tmp_new(long capa)
static VALUE rb_thread_safe_level(VALUE thread)
static VALUE rb_thread_aset(VALUE self, VALUE id, VALUE val)
VALUE rb_exec_recursive_paired_outer(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
struct st_hash_type * type
void rb_threadptr_pending_interrupt_enque(rb_thread_t *th, VALUE v)
#define OBJ_ID_EQL(obj_id, other)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_thread_alloc(VALUE klass)
static VALUE rb_mutex_sleep_forever(VALUE time)
static VALUE rb_thread_abort_exc(VALUE thread)
static void blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region)
void rb_nativethread_lock_initialize(rb_nativethread_lock_t *lock)
VALUE rb_ary_clear(VALUE ary)
pthread_mutex_t rb_nativethread_lock_t
static void clear_coverage(void)
static void sleep_forever(rb_thread_t *th, int nodeadlock, int spurious_check)
RUBY_EXTERN VALUE rb_eIOError
rb_nativethread_lock_t lock
void rb_thread_sleep_deadly(void)
VALUE rb_vm_thread_backtrace(int argc, VALUE *argv, VALUE thval)
#define RUBY_VM_SET_TRAP_INTERRUPT(th)
static size_t thgroup_memsize(const void *ptr)
static void rb_mutex_abandon_locking_mutex(rb_thread_t *th)
static VALUE sym_immediate
static int blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer *region, rb_unblock_function_t *ubf, void *arg, int fail_if_interrupted)
static void thread_shield_mark(void *ptr)
VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, int argc, const VALUE *argv, const rb_block_t *blockptr)
static size_t mutex_memsize(const void *ptr)
static volatile int system_working
static VALUE thread_join(rb_thread_t *target_th, double delay)
static VALUE remove_from_join_list(VALUE arg)
struct st_table * rb_hash_tbl_raw(VALUE hash)
static int rb_threadptr_dead(rb_thread_t *th)
ID rb_check_id(volatile VALUE *namep)
Returns ID for the given name if it is interned already, or 0.
static VALUE rb_thread_alive_p(VALUE thread)
#define rb_fd_rcopy(d, s)
void rb_thread_start_timer_thread(void)
VALUE rb_ivar_get(VALUE, ID)
static rb_fdset_t * init_set_fd(int fd, rb_fdset_t *fds)
ID rb_frame_last_func(void)
void rb_thread_terminate_all(void)
VALUE rb_mutex_sleep(VALUE self, VALUE timeout)
void rb_hash_foreach(VALUE, int(*)(ANYARGS), VALUE)
unsigned long rb_event_flag_t
VALUE rb_hash_delete(VALUE, VALUE)
static VALUE rb_thread_stop_p(VALUE thread)
static void thread_cleanup_func(void *th_ptr, int atfork)
static double timeofday(void)
static VALUE rb_thread_s_abort_exc_set(VALUE self, VALUE val)
static rb_atomic_t threadptr_get_interrupts(rb_thread_t *th)
VALUE(* first_func)(ANYARGS)
#define MEMZERO(p, type, n)
static VALUE rb_thread_s_main(VALUE klass)
void rb_exc_raise(VALUE mesg)
static void rb_thread_wait_fd_rw(int fd, int read)
static VALUE sym_on_blocking
static void rb_thread_schedule_limits(unsigned long limits_us)
int st_delete(st_table *, st_data_t *, st_data_t *)
static void rb_threadptr_interrupt_common(rb_thread_t *th, int trap)
static VALUE thgroup_s_alloc(VALUE klass)
#define RUBY_VM_INTERRUPTED_ANY(th)
static int thread_list_i(st_data_t key, st_data_t val, void *data)
static VALUE coverage(VALUE fname, int n)
#define closed_stream_error
static const char * thread_status_name(rb_thread_t *th)
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
VALUE rb_block_proc(void)
#define rb_fd_select(n, rfds, wfds, efds, timeout)
#define RUBY_THREAD_PRIORITY_MAX
static VALUE rb_thread_priority_set(VALUE thread, VALUE prio)
static int do_select(int n, rb_fdset_t *read, rb_fdset_t *write, rb_fdset_t *except, struct timeval *timeout)
static void sleep_for_polling(rb_thread_t *th)
#define RUBY_EVENT_COVERAGE
#define TypedData_Get_Struct(obj, type, data_type, sval)
int rb_block_given_p(void)
int rb_threadptr_set_raised(rb_thread_t *th)
static const rb_data_type_t thread_shield_data_type
VALUE * rb_vm_ep_local_ep(VALUE *ep)
static VALUE rb_thread_inspect(VALUE thread)
static VALUE rb_threadptr_raise(rb_thread_t *, int, VALUE *)
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
#define RARRAY_CONST_PTR(a)
#define RARRAY_AREF(a, i)
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
void * blocking_region_buffer
struct rb_thread_struct::@192 machine
static VALUE exec_recursive(VALUE(*func)(VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE arg, int outer)
static VALUE thread_create_core(VALUE thval, VALUE args, VALUE(*fn)(ANYARGS))
void rb_define_const(VALUE, const char *, VALUE)
static int rb_threadptr_pending_interrupt_include_p(rb_thread_t *th, VALUE err)
void rb_thread_stop_timer_thread(int close_anyway)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
static void rb_threadptr_ready(rb_thread_t *th)
static int rb_threadptr_pending_interrupt_empty_p(rb_thread_t *th)
int rb_thread_alone(void)
void rb_thread_recycle_stack_release(VALUE *)
VALUE rb_thread_shield_wait(VALUE self)
void rb_threadptr_check_signal(rb_thread_t *mth)
int thread_abort_on_exception
static VALUE rb_thread_variable_get(VALUE thread, VALUE key)
VALUE rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, int *stateptr)
void ruby_thread_init_stack(rb_thread_t *th)
VALUE rb_mutex_owned_p(VALUE self)
static VALUE rb_thread_exit(void)
#define TypedData_Wrap_Struct(klass, data_type, sval)
VALUE rb_thread_shield_release(VALUE self)
unsigned char buf[MIME_BUF_SIZE]
void rb_unblock_function_t(void *)
void ruby_stop(int ex)
Calls ruby_cleanup() and exits the process.
#define GVL_UNLOCK_BEGIN()
static const rb_data_type_t thgroup_data_type
void rb_throw_obj(VALUE tag, VALUE value)
static VALUE thread_s_current(VALUE klass)
static void sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec, int spurious_check)
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
#define ATOMIC_CAS(var, oldval, newval)
void rb_thread_polling(void)
#define GetMutexPtr(obj, tobj)
static VALUE rb_thread_backtrace_locations_m(int argc, VALUE *argv, VALUE thval)
int rb_thread_select(int max, fd_set *read, fd_set *write, fd_set *except, struct timeval *timeout)
VALUE rb_thread_shield_destroy(VALUE self)
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
static int recursive_pop(VALUE list, VALUE obj, VALUE paired_obj)
struct rb_unblock_callback oldubf
#define rb_thread_set_current(th)
void rb_thread_atfork(void)
VALUE rb_thread_current(void)
static int thgroup_list_i(st_data_t key, st_data_t val, st_data_t data)
VALUE special_exceptions[ruby_special_error_count]
struct rb_mutex_struct * keeping_mutexes
VALUE rb_sprintf(const char *format,...)
VALUE rb_mutex_trylock(VALUE mutex)
static int set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg, struct rb_unblock_callback *old, int fail_if_interrupted)
#define RUBY_TYPED_FREE_IMMEDIATELY
static int thread_fd_close_i(st_data_t key, st_data_t val, st_data_t data)
#define rb_fd_copy(d, s, n)
union select_args::@177 as
VALUE rb_class_inherited_p(VALUE, VALUE)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
VALUE rb_obj_is_mutex(VALUE obj)
#define RUBY_VM_SET_TIMER_INTERRUPT(th)
static VALUE thread_initialize(VALUE thread, VALUE args)
static void rb_check_deadlock(rb_vm_t *vm)
static VALUE rb_mutex_synchronize_m(VALUE self, VALUE args)
VALUE rb_thread_run(VALUE)
static VALUE thread_shield_alloc(VALUE klass)
void rb_mutex_allow_trap(VALUE self, int val)
VALUE rb_thread_kill(VALUE)
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
#define THREAD_SHIELD_WAITING_MASK
#define SAVE_ROOT_JMPBUF(th, stmt)
#define RUBY_TYPED_DEFAULT_FREE
int rb_remove_event_hook(rb_event_hook_func_t func)
static int keys_i(VALUE key, VALUE value, VALUE ary)
#define UNINITIALIZED_VAR(x)
struct rb_thread_struct * main_thread
VALUE rb_thread_local_aref(VALUE, ID)
static int clear_coverage_i(st_data_t key, st_data_t val, st_data_t dummy)
static VALUE rb_thread_s_pending_interrupt_p(int argc, VALUE *argv, VALUE self)
int rb_threadptr_reset_raised(rb_thread_t *th)
rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1))
VALUE rb_thread_wakeup_alive(VALUE)
void rb_threadptr_pending_interrupt_clear(rb_thread_t *th)
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
void rb_gc_set_stack_end(VALUE **stack_end_p)
static void rb_thread_shield_waiting_dec(VALUE b)
VALUE rb_exec_recursive_outer(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
int clock_gettime(clockid_t, struct timespec *)
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
static VALUE thread_value(VALUE self)
static void reset_unblock_function(rb_thread_t *th, const struct rb_unblock_callback *old)
rb_atomic_t interrupt_flag
rb_nativethread_cond_t interrupt_cond
static void timer_thread_function(void *)
#define rb_fd_isset(n, f)
void rb_thread_schedule(void)
void rb_sys_fail(const char *mesg)
void rb_threadptr_restore_recursive_data(rb_thread_t *th, VALUE old)
#define rb_fd_resize(n, f)
static VALUE rb_thread_backtrace_m(int argc, VALUE *argv, VALUE thval)
RUBY_EXTERN char * strerror(int)
static VALUE rb_thread_pending_interrupt_p(int argc, VALUE *argv, VALUE target_thread)
enum rb_thread_status status
static void st_delete_wrap(st_table *table, st_data_t key)
void rb_thread_sleep_forever(void)
static VALUE thread_s_pass(VALUE klass)
VALUE rb_threadptr_reset_recursive_data(rb_thread_t *th)
static VALUE thread_join_m(int argc, VALUE *argv, VALUE self)
const char * rb_class2name(VALUE)
VALUE rb_thread_wakeup(VALUE)
#define thread_start_func_2(th, st, rst)
VALUE rb_mutex_unlock(VALUE mutex)
enum rb_thread_status prev_status
static VALUE mutex_sleep(int argc, VALUE *argv, VALUE self)
struct timeval rb_time_interval(VALUE num)
#define THREAD_SHIELD_WAITING_SHIFT
static void rb_threadptr_to_kill(rb_thread_t *th)
void rb_reset_coverages(void)
void rb_thread_wait_for(struct timeval)
static VALUE thgroup_list(VALUE group)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
unsigned long interrupt_mask
struct st_hash_type st_hashtype_num
#define RUBY_THREAD_PRIORITY_MIN
void rb_thread_sleep(int)
VALUE rb_thread_group(VALUE thread)
struct rb_unblock_callback unblock
VALUE rb_thread_shield_new(void)
#define BLOCKING_REGION(exec, ubf, ubfarg, fail_if_interrupted)
void rb_thread_execute_interrupts(VALUE th)
RUBY_SYMBOL_EXPORT_BEGIN void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
static VALUE recursive_list_access(VALUE sym)
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
#define RB_GC_SAVE_MACHINE_CONTEXT(th)
#define TypedData_Make_Struct(klass, type, data_type, sval)
void rb_thread_reset_timer_thread(void)
rb_nativethread_id_t thread_id
rb_nativethread_lock_t thread_destruct_lock
RUBY_EXTERN VALUE rb_cObject
int rb_signal_buff_size(void)
static void rb_thread_shield_waiting_inc(VALUE b)
int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
struct rb_encoding_entry * list
static VALUE rb_threadptr_pending_interrupt_deque(rb_thread_t *th, enum handle_interrupt_timing timing)
static void recursive_push(VALUE list, VALUE obj, VALUE paired_obj)
static VALUE thread_start(VALUE klass, VALUE args)
static VALUE threadptr_local_aset(rb_thread_t *th, ID id, VALUE val)
void rb_nativethread_lock_lock(rb_nativethread_lock_t *lock)
static VALUE rb_mutex_wait_for(VALUE time)
VALUE rb_ary_dup(VALUE ary)
int st_insert(st_table *, st_data_t, st_data_t)
void rb_thread_fd_close(int)
#define GetThreadPtr(obj, ptr)
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
static VALUE thread_raise_m(int argc, VALUE *argv, VALUE self)
#define rb_thread_shield_waiting(b)
#define EXEC_EVENT_HOOK(th_, flag_, self_, id_, klass_, data_)
static void sleep_timeval(rb_thread_t *th, struct timeval time, int spurious_check)
void st_clear(st_table *)
VALUE rb_thread_stop(void)
VALUE rb_obj_alloc(VALUE)
void rb_threadptr_trap_interrupt(rb_thread_t *th)
#define ruby_native_thread_p()
static int terminate_i(st_data_t key, st_data_t val, rb_thread_t *main_thread)
struct rb_thread_list_struct * next
#define RUBY_VM_INTERRUPTED(th)
#define RBASIC_CLEAR_CLASS(obj)
static VALUE rb_thread_s_abort_exc(void)
VALUE rb_hash_aref(VALUE, VALUE)
void rb_vm_gvl_destroy(rb_vm_t *vm)
int rb_threadptr_pending_interrupt_active_p(rb_thread_t *th)
static VALUE rb_thread_aref(VALUE thread, VALUE key)
VALUE rb_uninterruptible(VALUE(*b_proc)(ANYARGS), VALUE data)
static void mutex_locked(rb_thread_t *th, VALUE self)
static VALUE ident_hash_new(void)
VALUE rb_thread_create(VALUE(*)(ANYARGS), void *)
VALUE rb_thread_local_aset(VALUE, ID, VALUE)
static VALUE rb_thread_keys(VALUE self)
#define GetThreadShieldPtr(obj)
rb_nativethread_lock_t interrupt_lock
#define RARRAY_ASET(a, i, v)
VALUE pending_interrupt_queue
static void getclockofday(struct timeval *tp)
static VALUE select_single_cleanup(VALUE ptr)
VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val)
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
static VALUE select_single(VALUE ptr)
struct rb_mutex_struct rb_mutex_t
void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data)
#define RUBY_INTERNAL_EVENT_SWITCH
int rb_get_next_signal(void)
static int thread_keys_i(ID key, VALUE value, VALUE ary)
static void * call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2, int fail_if_interrupted)
#define GET_THROWOBJ_STATE(obj)
static VALUE rb_thread_variable_set(VALUE thread, VALUE id, VALUE val)
void rb_threadptr_interrupt(rb_thread_t *th)
VALUE rb_thread_blocking_region(rb_blocking_function_t *func, void *data1, rb_unblock_function_t *ubf, void *data2)
void rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
static void mutex_free(void *ptr)
static rb_thread_t * GET_THREAD(void)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
int rb_thread_fd_writable(int)
#define GET_THROWOBJ_VAL(obj)
VALUE rb_vm_thread_backtrace_locations(int argc, VALUE *argv, VALUE thval)
void rb_set_coverages(VALUE coverages)
int select(int num_fds, fd_set *in_fds, fd_set *out_fds, fd_set *ex_fds, struct timeval *timeout)
static VALUE rb_thread_key_p(VALUE self, VALUE key)
#define RUBY_VM_CHECK_INTS_BLOCKING(th)
VALUE rb_convert_type(VALUE, int, const char *, const char *)
static VALUE rb_thread_s_kill(VALUE obj, VALUE th)
static VALUE recursive_check(VALUE list, VALUE obj_id, VALUE paired_obj_id)
RUBY_EXTERN VALUE rb_cThread
void rb_reset_random_seed(void)
void rb_threadptr_signal_exit(rb_thread_t *th)
#define rb_thread_check_trap_pending()
static void lock_interrupt(void *ptr)
static void rb_thread_atfork_internal(int(*atfork)(st_data_t, st_data_t, st_data_t))
#define TYPEOF_TIMEVAL_TV_SEC
struct timeval rb_time_timeval(VALUE)
int rb_thread_interrupted(VALUE thval)
static enum handle_interrupt_timing rb_threadptr_pending_interrupt_check_mask(rb_thread_t *th, VALUE err)
static int terminate_atfork_i(st_data_t key, st_data_t val, st_data_t current_th)
void rb_nativethread_lock_destroy(rb_nativethread_lock_t *lock)