ruby-changes:27634
From: kosaki <ko1@a...>
Date: Sun, 10 Mar 2013 13:00:31 +0900 (JST)
Subject: [ruby-changes:27634] kosaki:r39686 (trunk): * thread_pthread.c (ARRAY_SIZE): new.
kosaki 2013-03-10 13:00:21 +0900 (Sun, 10 Mar 2013) New Revision: 39686 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=39686 Log: * thread_pthread.c (ARRAY_SIZE): new. * thread_pthread.c (gvl_acquire_common): use low priority notification for avoiding timer thread interval confusion. If we use timer_thread_pipe[1], every gvl_yield() request one more gvl_yield(). It lead to thread starvation. [Bug #7999] [ruby-core:53095] * thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low to reserved fds. Modified files: trunk/ChangeLog trunk/thread_pthread.c Index: ChangeLog =================================================================== --- ChangeLog (revision 39685) +++ ChangeLog (revision 39686) @@ -1,3 +1,14 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Wed Mar 6 23:30:21 2013 KOSAKI Motohiro <kosaki.motohiro@g...> + + * thread_pthread.c (ARRAY_SIZE): new. + * thread_pthread.c (gvl_acquire_common): use low priority + notification for avoiding timer thread interval confusion. + If we use timer_thread_pipe[1], every gvl_yield() request + one more gvl_yield(). It lead to thread starvation. + [Bug #7999] [ruby-core:53095] + * thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low + to reserved fds. + Wed Mar 6 22:36:19 2013 KOSAKI Motohiro <kosaki.motohiro@g...> * thread_pthread.c (rb_thread_wakeup_timer_thread_fd): add fd Index: thread_pthread.c =================================================================== --- thread_pthread.c (revision 39685) +++ thread_pthread.c (revision 39686) @@ -44,6 +44,7 @@ static void native_cond_broadcast(rb_thr https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L44 static void native_cond_wait(rb_thread_cond_t *cond, pthread_mutex_t *mutex); static void native_cond_initialize(rb_thread_cond_t *cond, int flags); static void native_cond_destroy(rb_thread_cond_t *cond); +static void rb_thread_wakeup_timer_thread_low(void); static pthread_t timer_thread_id; #define RB_CONDATTR_CLOCK_MONOTONIC 1 @@ -63,6 +64,10 @@ static pthread_t timer_thread_id; https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L64 # define USE_SLEEPY_TIMER_THREAD 0 #endif +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + static void gvl_acquire_common(rb_vm_t *vm) { @@ -70,8 +75,12 @@ gvl_acquire_common(rb_vm_t *vm) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L75 vm->gvl.waiting++; if (vm->gvl.waiting == 1) { - /* transit to polling mode */ - rb_thread_wakeup_timer_thread(); + /* + * Wake up timer thread iff timer thread is slept. + * When timer thread is polling mode, we don't want to + * make confusing timer thread interval time. + */ + rb_thread_wakeup_timer_thread_low(); } while (vm->gvl.acquired) { @@ -1153,6 +1162,7 @@ static int check_signal_thread_list(void https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1162 #if USE_SLEEPY_TIMER_THREAD static int timer_thread_pipe[2] = {-1, -1}; +static int timer_thread_pipe_low[2] = {-1, -1}; /* low priority */ static int timer_thread_pipe_owner_process; /* only use signal-safe system calls here */ @@ -1190,6 +1200,12 @@ rb_thread_wakeup_timer_thread(void) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1200 rb_thread_wakeup_timer_thread_fd(timer_thread_pipe[1]); } +static void +rb_thread_wakeup_timer_thread_low(void) +{ + rb_thread_wakeup_timer_thread_fd(timer_thread_pipe_low[1]); +} + /* VM-dependent API is not available for this function */ static void consume_communication_pipe(int fd) @@ -1278,6 +1294,7 @@ setup_communication_pipe(void) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1294 return; } setup_communication_pipe_internal(timer_thread_pipe); + setup_communication_pipe_internal(timer_thread_pipe_low); /* validate pipe on this process */ timer_thread_pipe_owner_process = getpid(); @@ -1295,20 +1312,22 @@ timer_thread_sleep(rb_global_vm_lock_t* https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1312 { int result; int need_polling; - struct pollfd pollfd; + struct pollfd pollfds[2]; - pollfd.fd = timer_thread_pipe[0]; - pollfd.events = POLLIN; + pollfds[0].fd = timer_thread_pipe[0]; + pollfds[0].events = POLLIN; + pollfds[1].fd = timer_thread_pipe_low[0]; + pollfds[1].events = POLLIN; need_polling = check_signal_thread_list(); if (gvl->waiting > 0 || need_polling) { /* polling (TIME_QUANTUM_USEC usec) */ - result = poll(&pollfd, 1, TIME_QUANTUM_USEC/1000); + result = poll(pollfds, 1, TIME_QUANTUM_USEC/1000); } else { /* wait (infinite) */ - result = poll(&pollfd, 1, -1); + result = poll(pollfds, ARRAY_SIZE(pollfds), -1); } if (result == 0) { @@ -1316,6 +1335,7 @@ timer_thread_sleep(rb_global_vm_lock_t* https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1335 } else if (result > 0) { consume_communication_pipe(timer_thread_pipe[0]); + consume_communication_pipe(timer_thread_pipe_low[0]); } else { /* result < 0 */ switch (errno) { @@ -1510,8 +1530,10 @@ int https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1530 rb_reserved_fd_p(int fd) { #if USE_SLEEPY_TIMER_THREAD - if (fd == timer_thread_pipe[0] || - fd == timer_thread_pipe[1]) { + if (fd == timer_thread_pipe[0] || + fd == timer_thread_pipe[1] || + fd == timer_thread_pipe_low[0] || + fd == timer_thread_pipe_low[1]) { return 1; } else { -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/