зеркало из https://github.com/github/ruby.git
simplify altstack and enable reuse with thread cache
Instead of allocating and registering the altstack in different places, do it together to reduce code and improve readability. When thread cache is enabled, storing altstack in rb_thread_t is wasteful and we may reuse altstack in the same pthread. This also lets us clearly allow use of xmalloc to allow GC to recover from ENOMEM. [ruby-core:85621] [Feature #14487] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63213 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
e72a86fc93
Коммит
475b4aa40b
10
gc.c
10
gc.c
|
@ -2403,16 +2403,6 @@ Init_heap(void)
|
|||
heap_add_pages(objspace, heap_eden, gc_params.heap_init_slots / HEAP_PAGE_OBJ_LIMIT);
|
||||
init_mark_stack(&objspace->mark_stack);
|
||||
|
||||
#ifdef USE_SIGALTSTACK
|
||||
{
|
||||
/* altstack of another threads are allocated in another place */
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
void *tmp = th->altstack;
|
||||
th->altstack = malloc(rb_sigaltstack_size());
|
||||
free(tmp); /* free previously allocated area */
|
||||
}
|
||||
#endif
|
||||
|
||||
objspace->profile.invoke_time = getrusage_time();
|
||||
finalizer_table = st_init_numtable();
|
||||
}
|
||||
|
|
|
@ -1704,7 +1704,6 @@ int rb_match_nth_defined(int nth, VALUE match);
|
|||
/* signal.c */
|
||||
extern int ruby_enable_coredump;
|
||||
int rb_get_next_signal(void);
|
||||
int rb_sigaltstack_size(void);
|
||||
|
||||
/* st.c */
|
||||
extern void rb_hash_bulk_insert(long, const VALUE *, VALUE);
|
||||
|
|
17
signal.c
17
signal.c
|
@ -554,7 +554,7 @@ typedef RETSIGTYPE ruby_sigaction_t(int);
|
|||
#endif
|
||||
|
||||
#ifdef USE_SIGALTSTACK
|
||||
int
|
||||
static int
|
||||
rb_sigaltstack_size(void)
|
||||
{
|
||||
/* XXX: BSD_vfprintf() uses >1500KiB stack and x86-64 need >5KiB stack. */
|
||||
|
@ -577,19 +577,18 @@ rb_sigaltstack_size(void)
|
|||
}
|
||||
|
||||
/* alternate stack for SIGSEGV */
|
||||
void
|
||||
rb_register_sigaltstack(rb_thread_t *th)
|
||||
void *
|
||||
rb_register_sigaltstack(void)
|
||||
{
|
||||
stack_t newSS, oldSS;
|
||||
|
||||
if (!th->altstack)
|
||||
rb_bug("rb_register_sigaltstack: th->altstack not initialized\n");
|
||||
|
||||
newSS.ss_sp = th->altstack;
|
||||
newSS.ss_size = rb_sigaltstack_size();
|
||||
newSS.ss_sp = xmalloc(newSS.ss_size);
|
||||
newSS.ss_flags = 0;
|
||||
|
||||
sigaltstack(&newSS, &oldSS); /* ignore error. */
|
||||
|
||||
return newSS.ss_sp;
|
||||
}
|
||||
#endif /* USE_SIGALTSTACK */
|
||||
|
||||
|
@ -1532,9 +1531,7 @@ Init_signal(void)
|
|||
install_sighandler(SIGILL, (sighandler_t)sigill);
|
||||
#endif
|
||||
#ifdef SIGSEGV
|
||||
# ifdef USE_SIGALTSTACK
|
||||
rb_register_sigaltstack(GET_THREAD());
|
||||
# endif
|
||||
RB_ALTSTACK_INIT(GET_VM()->main_altstack);
|
||||
install_sighandler(SIGSEGV, (sighandler_t)sigsegv);
|
||||
#endif
|
||||
}
|
||||
|
|
5
thread.c
5
thread.c
|
@ -652,11 +652,6 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s
|
|||
rb_thread_list_t *join_list;
|
||||
rb_thread_t *main_th;
|
||||
VALUE errinfo = Qnil;
|
||||
# ifdef USE_SIGALTSTACK
|
||||
void rb_register_sigaltstack(rb_thread_t *th);
|
||||
|
||||
rb_register_sigaltstack(th);
|
||||
# endif
|
||||
|
||||
if (th == th->vm->main_thread)
|
||||
rb_bug("thread_start_func_2 must not be used for main thread");
|
||||
|
|
|
@ -840,6 +840,7 @@ static void *
|
|||
thread_start_func_1(void *th_ptr)
|
||||
{
|
||||
rb_thread_t *th = th_ptr;
|
||||
RB_ALTSTACK_INIT(void *altstack);
|
||||
#if USE_THREAD_CACHE
|
||||
thread_start:
|
||||
#endif
|
||||
|
@ -868,6 +869,7 @@ thread_start_func_1(void *th_ptr)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
RB_ALTSTACK_FREE(altstack);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
9
vm.c
9
vm.c
|
@ -2216,6 +2216,7 @@ ruby_vm_destruct(rb_vm_t *vm)
|
|||
vm->frozen_strings = 0;
|
||||
}
|
||||
rb_vm_gvl_destroy(vm);
|
||||
RB_ALTSTACK_FREE(vm->main_altstack);
|
||||
if (objspace) {
|
||||
rb_objspace_free(objspace);
|
||||
}
|
||||
|
@ -2473,9 +2474,6 @@ thread_free(void *ptr)
|
|||
RUBY_GC_INFO("main thread\n");
|
||||
}
|
||||
else {
|
||||
#ifdef USE_SIGALTSTACK
|
||||
free(th->altstack);
|
||||
#endif
|
||||
ruby_xfree(ptr);
|
||||
}
|
||||
|
||||
|
@ -2535,11 +2533,6 @@ th_init(rb_thread_t *th, VALUE self)
|
|||
th->self = self;
|
||||
rb_threadptr_root_fiber_setup(th);
|
||||
|
||||
/* allocate thread stack */
|
||||
#ifdef USE_SIGALTSTACK
|
||||
/* altstack of main thread is reallocated in another place */
|
||||
th->altstack = malloc(rb_sigaltstack_size());
|
||||
#endif
|
||||
{
|
||||
/* vm_stack_size is word number.
|
||||
* th->vm->default_params.thread_vm_stack_size is byte size. */
|
||||
|
|
14
vm_core.h
14
vm_core.h
|
@ -101,7 +101,13 @@
|
|||
#endif
|
||||
|
||||
#if defined(SIGSEGV) && defined(HAVE_SIGALTSTACK) && defined(SA_SIGINFO) && !defined(__NetBSD__)
|
||||
#define USE_SIGALTSTACK
|
||||
# define USE_SIGALTSTACK
|
||||
void *rb_register_sigaltstack(void);
|
||||
# define RB_ALTSTACK_INIT(var) var = rb_register_sigaltstack()
|
||||
# define RB_ALTSTACK_FREE(var) xfree(var)
|
||||
#else /* noop */
|
||||
# define RB_ALTSTACK_INIT(var)
|
||||
# define RB_ALTSTACK_FREE(var)
|
||||
#endif
|
||||
|
||||
/*****************/
|
||||
|
@ -538,6 +544,9 @@ typedef struct rb_vm_struct {
|
|||
|
||||
struct rb_thread_struct *main_thread;
|
||||
struct rb_thread_struct *running_thread;
|
||||
#ifdef USE_SIGALTSTACK
|
||||
void *main_altstack;
|
||||
#endif
|
||||
|
||||
rb_serial_t fork_gen;
|
||||
struct list_head waiting_fds; /* <=> struct waiting_fd */
|
||||
|
@ -883,9 +892,6 @@ typedef struct rb_thread_struct {
|
|||
/* misc */
|
||||
unsigned int abort_on_exception: 1;
|
||||
unsigned int report_on_exception: 1;
|
||||
#ifdef USE_SIGALTSTACK
|
||||
void *altstack;
|
||||
#endif
|
||||
uint32_t running_time_us; /* 12500..800000 */
|
||||
VALUE name;
|
||||
} rb_thread_t;
|
||||
|
|
Загрузка…
Ссылка в новой задаче