mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
vm_trace.c: MJIT-limited thread-safety for postponed_job
[Bug #15316] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66001 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
01e2bf35bc
commit
67485fee42
3 changed files with 22 additions and 1 deletions
14
mjit.c
14
mjit.c
|
@ -106,6 +106,20 @@ mjit_gc_finish_hook(void)
|
|||
CRITICAL_SECTION_FINISH(4, "mjit_gc_finish_hook");
|
||||
}
|
||||
|
||||
/* Wrap critical section to prevent [Bug #15316] */
|
||||
void
|
||||
mjit_postponed_job_register_start_hook(void)
|
||||
{
|
||||
CRITICAL_SECTION_START(4, "mjit_postponed_job_register_start_hook");
|
||||
}
|
||||
|
||||
/* Unwrap critical section of mjit_postponed_job_register_start_hook() */
|
||||
void
|
||||
mjit_postponed_job_register_finish_hook(void)
|
||||
{
|
||||
CRITICAL_SECTION_FINISH(4, "mjit_postponed_job_register_finish_hook");
|
||||
}
|
||||
|
||||
/* Iseqs can be garbage collected. This function should call when it
|
||||
happens. It removes iseq from the unit. */
|
||||
void
|
||||
|
|
4
mjit.h
4
mjit.h
|
@ -66,6 +66,8 @@ RUBY_SYMBOL_EXPORT_END
|
|||
|
||||
extern int mjit_compile(FILE *f, const struct rb_iseq_constant_body *body, const char *funcname, struct rb_call_cache *cc_entries, union iseq_inline_storage_entry *is_entries);
|
||||
extern void mjit_init(struct mjit_options *opts);
|
||||
extern void mjit_postponed_job_register_start_hook(void);
|
||||
extern void mjit_postponed_job_register_finish_hook(void);
|
||||
extern void mjit_gc_start_hook(void);
|
||||
extern void mjit_gc_finish_hook(void);
|
||||
extern void mjit_free_iseq(const rb_iseq_t *iseq);
|
||||
|
@ -131,6 +133,8 @@ void mjit_child_after_fork(void);
|
|||
#else /* USE_MJIT */
|
||||
static inline struct mjit_cont *mjit_cont_new(rb_execution_context_t *ec){return NULL;}
|
||||
static inline void mjit_cont_free(struct mjit_cont *cont){}
|
||||
static inline void mjit_postponed_job_register_start_hook(void){}
|
||||
static inline void mjit_postponed_job_register_finish_hook(void){}
|
||||
static inline void mjit_gc_start_hook(void){}
|
||||
static inline void mjit_gc_finish_hook(void){}
|
||||
static inline void mjit_free_iseq(const rb_iseq_t *iseq){}
|
||||
|
|
|
@ -1588,7 +1588,7 @@ enum postponed_job_register_result {
|
|||
PJRR_INTERRUPTED = 2
|
||||
};
|
||||
|
||||
/* Async-signal-safe */
|
||||
/* Async-signal-safe, thread-safe against MJIT worker thread */
|
||||
static enum postponed_job_register_result
|
||||
postponed_job_register(rb_execution_context_t *ec, rb_vm_t *vm,
|
||||
unsigned int flags, rb_postponed_job_func_t func, void *data, int max, int expected_index)
|
||||
|
@ -1596,11 +1596,13 @@ postponed_job_register(rb_execution_context_t *ec, rb_vm_t *vm,
|
|||
rb_postponed_job_t *pjob;
|
||||
|
||||
if (expected_index >= max) return PJRR_FULL; /* failed */
|
||||
if (mjit_enabled) mjit_postponed_job_register_start_hook();
|
||||
|
||||
if (ATOMIC_CAS(vm->postponed_job_index, expected_index, expected_index+1) == expected_index) {
|
||||
pjob = &vm->postponed_job_buffer[expected_index];
|
||||
}
|
||||
else {
|
||||
if (mjit_enabled) mjit_postponed_job_register_finish_hook();
|
||||
return PJRR_INTERRUPTED;
|
||||
}
|
||||
|
||||
|
@ -1609,6 +1611,7 @@ postponed_job_register(rb_execution_context_t *ec, rb_vm_t *vm,
|
|||
pjob->data = data;
|
||||
|
||||
RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(ec);
|
||||
if (mjit_enabled) mjit_postponed_job_register_finish_hook();
|
||||
|
||||
return PJRR_SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue