diff options
Diffstat (limited to 'vm_core.h')
-rw-r--r-- | vm_core.h | 119 |
1 files changed, 72 insertions, 47 deletions
@@ -419,6 +419,7 @@ struct rb_iseq_constant_body { char catch_except_p; /* If a frame of this ISeq may catch exception, set TRUE */ bool builtin_inline_p; // This ISeq's builtin func is safe to be inlined by MJIT + char access_outer_variables; #if USE_MJIT /* The following fields are MJIT related info. */ @@ -554,12 +555,30 @@ typedef const struct rb_builtin_function *RB_BUILTIN; typedef struct rb_vm_struct { VALUE self; - rb_global_vm_lock_t gvl; + struct { + struct list_head set; + unsigned int cnt; + unsigned int blocking_cnt; - struct rb_thread_struct *main_thread; + struct rb_ractor_struct *main_ractor; + struct rb_thread_struct *main_thread; // == vm->ractor.main_ractor->threads.main - /* persists across uncontended GVL release/acquire for time slice */ - const struct rb_thread_struct *running_thread; + struct { + // monitor + rb_nativethread_lock_t lock; + struct rb_ractor_struct *lock_owner; + unsigned int lock_rec; + + // barrier + bool barrier_waiting; + unsigned int barrier_cnt; + rb_nativethread_cond_t barrier_cond; + + // join at exit + rb_nativethread_cond_t terminate_cond; + bool terminate_waiting; + } sync; + } ractor; #ifdef USE_SIGALTSTACK void *main_altstack; @@ -570,9 +589,6 @@ typedef struct rb_vm_struct { struct list_head waiting_pids; /* PID > 0: <=> struct waitpid_state */ struct list_head waiting_grps; /* PID <= 0: <=> struct waitpid_state */ struct list_head waiting_fds; /* <=> struct waiting_fd */ - struct list_head living_threads; - VALUE thgroup_default; - int living_thread_num; /* set in single-threaded processes only: */ volatile int ubf_async_safe; @@ -580,9 +596,7 @@ typedef struct rb_vm_struct { unsigned int running: 1; unsigned int thread_abort_on_exception: 1; unsigned int thread_report_on_exception: 1; - unsigned int safe_level_: 1; - int sleeper; /* object management */ VALUE mark_object_ary; @@ -890,9 +904,12 @@ void rb_ec_initialize_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t // @param ec the execution context to update. void rb_ec_clear_vm_stack(rb_execution_context_t *ec); +typedef struct rb_ractor_struct rb_ractor_t; + typedef struct rb_thread_struct { - struct list_node vmlt_node; + struct list_node lt_node; // managed by a ractor VALUE self; + rb_ractor_t *ractor; rb_vm_t *vm; rb_execution_context_t *ec; @@ -955,9 +972,10 @@ typedef struct rb_thread_struct { } func; } invoke_arg; - enum { + enum thread_invoke_type { thread_invoke_type_none = 0, thread_invoke_type_proc, + thread_invoke_type_ractor_proc, thread_invoke_type_func } invoke_type; @@ -1039,8 +1057,12 @@ typedef struct { const struct rb_block block; unsigned int is_from_method: 1; /* bool */ unsigned int is_lambda: 1; /* bool */ + unsigned int is_isolated: 1; /* bool */ } rb_proc_t; +VALUE rb_proc_isolate(VALUE self); +VALUE rb_proc_isolate_bang(VALUE self); + typedef struct { VALUE flags; /* imemo header */ rb_iseq_t *iseq; @@ -1628,11 +1650,12 @@ VALUE rb_vm_env_local_variables(const rb_env_t *env); const rb_env_t *rb_vm_env_prev_env(const rb_env_t *env); const VALUE *rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const ID *dynvars); void rb_vm_inc_const_missing_count(void); -void rb_vm_gvl_destroy(rb_vm_t *vm); VALUE rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat); MJIT_STATIC void rb_vm_pop_frame(rb_execution_context_t *ec); +void rb_gvl_destroy(rb_global_vm_lock_t *gvl); + void rb_thread_start_timer_thread(void); void rb_thread_stop_timer_thread(void); void rb_thread_reset_timer_thread(void); @@ -1645,22 +1668,7 @@ rb_vm_living_threads_init(rb_vm_t *vm) list_head_init(&vm->waiting_pids); list_head_init(&vm->workqueue); list_head_init(&vm->waiting_grps); - list_head_init(&vm->living_threads); - vm->living_thread_num = 0; -} - -static inline void -rb_vm_living_threads_insert(rb_vm_t *vm, rb_thread_t *th) -{ - list_add_tail(&vm->living_threads, &th->vmlt_node); - vm->living_thread_num++; -} - -static inline void -rb_vm_living_threads_remove(rb_vm_t *vm, rb_thread_t *th) -{ - list_del(&th->vmlt_node); - vm->living_thread_num--; + list_head_init(&vm->ractor.set); } typedef int rb_backtrace_iter_func(void *, VALUE, int, VALUE); @@ -1700,20 +1708,24 @@ MJIT_STATIC const rb_callable_method_entry_t *rb_vm_frame_method_entry(const rb_ VALUE rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, enum ruby_tag_type *stateptr); +rb_execution_context_t *rb_vm_main_ractor_ec(rb_vm_t *vm); // ractor.c + /* for thread */ #if RUBY_VM_THREAD_MODEL == 2 RUBY_SYMBOL_EXPORT_BEGIN RUBY_EXTERN rb_vm_t *ruby_current_vm_ptr; -RUBY_EXTERN rb_execution_context_t *ruby_current_execution_context_ptr; RUBY_EXTERN rb_event_flag_t ruby_vm_event_flags; RUBY_EXTERN rb_event_flag_t ruby_vm_event_enabled_global_flags; RUBY_EXTERN unsigned int ruby_vm_event_local_num; +RUBY_EXTERN native_tls_key_t ruby_current_ec_key; + RUBY_SYMBOL_EXPORT_END #define GET_VM() rb_current_vm() +#define GET_RACTOR() rb_current_ractor() #define GET_THREAD() rb_current_thread() #define GET_EC() rb_current_execution_context() @@ -1723,6 +1735,19 @@ rb_ec_thread_ptr(const rb_execution_context_t *ec) return ec->thread_ptr; } +static inline rb_ractor_t * +rb_ec_ractor_ptr(const rb_execution_context_t *ec) +{ + const rb_thread_t *th = rb_ec_thread_ptr(ec); + if (th) { + VM_ASSERT(th->ractor != NULL); + return th->ractor; + } + else { + return NULL; + } +} + static inline rb_vm_t * rb_ec_vm_ptr(const rb_execution_context_t *ec) { @@ -1738,7 +1763,9 @@ rb_ec_vm_ptr(const rb_execution_context_t *ec) static inline rb_execution_context_t * rb_current_execution_context(void) { - return ruby_current_execution_context_ptr; + rb_execution_context_t *ec = native_tls_get(ruby_current_ec_key); + VM_ASSERT(ec != NULL); + return ec; } static inline rb_thread_t * @@ -1748,31 +1775,25 @@ rb_current_thread(void) return rb_ec_thread_ptr(ec); } +static inline rb_ractor_t * +rb_current_ractor(void) +{ + const rb_execution_context_t *ec = GET_EC(); + return rb_ec_ractor_ptr(ec); +} + static inline rb_vm_t * rb_current_vm(void) { +#if 0 // TODO: reconsider the assertions VM_ASSERT(ruby_current_vm_ptr == NULL || ruby_current_execution_context_ptr == NULL || rb_ec_thread_ptr(GET_EC()) == NULL || rb_ec_thread_ptr(GET_EC())->status == THREAD_KILLED || rb_ec_vm_ptr(GET_EC()) == ruby_current_vm_ptr); - return ruby_current_vm_ptr; -} - -static inline void -rb_thread_set_current_raw(const rb_thread_t *th) -{ - ruby_current_execution_context_ptr = th->ec; -} +#endif -static inline void -rb_thread_set_current(rb_thread_t *th) -{ - if (th->vm->running_thread != th) { - th->running_time_us = 0; - } - rb_thread_set_current_raw(th); - th->vm->running_thread = th; + return ruby_current_vm_ptr; } #else @@ -1783,13 +1804,17 @@ enum { TIMER_INTERRUPT_MASK = 0x01, PENDING_INTERRUPT_MASK = 0x02, POSTPONED_JOB_INTERRUPT_MASK = 0x04, - TRAP_INTERRUPT_MASK = 0x08 + TRAP_INTERRUPT_MASK = 0x08, + TERMINATE_INTERRUPT_MASK = 0x10, + VM_BARRIER_INTERRUPT_MASK = 0x20, }; #define RUBY_VM_SET_TIMER_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TIMER_INTERRUPT_MASK) #define RUBY_VM_SET_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, PENDING_INTERRUPT_MASK) #define RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, POSTPONED_JOB_INTERRUPT_MASK) #define RUBY_VM_SET_TRAP_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TRAP_INTERRUPT_MASK) +#define RUBY_VM_SET_TERMINATE_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TERMINATE_INTERRUPT_MASK) +#define RUBY_VM_SET_VM_BARRIER_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, VM_BARRIER_INTERRUPT_MASK) #define RUBY_VM_INTERRUPTED(ec) ((ec)->interrupt_flag & ~(ec)->interrupt_mask & \ (PENDING_INTERRUPT_MASK|TRAP_INTERRUPT_MASK)) #define RUBY_VM_INTERRUPTED_ANY(ec) ((ec)->interrupt_flag & ~(ec)->interrupt_mask) |