1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39686 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
kosaki 2013-03-10 04:00:21 +00:00
parent 9c021064a2
commit bcf1293681
2 changed files with 42 additions and 9 deletions

View file

@ -1,3 +1,14 @@
Wed Mar 6 23:30:21 2013 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
* 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@gmail.com> Wed Mar 6 22:36:19 2013 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
* thread_pthread.c (rb_thread_wakeup_timer_thread_fd): add fd * thread_pthread.c (rb_thread_wakeup_timer_thread_fd): add fd

View file

@ -44,6 +44,7 @@ static void native_cond_broadcast(rb_thread_cond_t *cond);
static void native_cond_wait(rb_thread_cond_t *cond, pthread_mutex_t *mutex); 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_initialize(rb_thread_cond_t *cond, int flags);
static void native_cond_destroy(rb_thread_cond_t *cond); 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; static pthread_t timer_thread_id;
#define RB_CONDATTR_CLOCK_MONOTONIC 1 #define RB_CONDATTR_CLOCK_MONOTONIC 1
@ -63,6 +64,10 @@ static pthread_t timer_thread_id;
# define USE_SLEEPY_TIMER_THREAD 0 # define USE_SLEEPY_TIMER_THREAD 0
#endif #endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
static void static void
gvl_acquire_common(rb_vm_t *vm) gvl_acquire_common(rb_vm_t *vm)
{ {
@ -70,8 +75,12 @@ gvl_acquire_common(rb_vm_t *vm)
vm->gvl.waiting++; vm->gvl.waiting++;
if (vm->gvl.waiting == 1) { 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) { while (vm->gvl.acquired) {
@ -1153,6 +1162,7 @@ static int check_signal_thread_list(void) { return 0; }
#if USE_SLEEPY_TIMER_THREAD #if USE_SLEEPY_TIMER_THREAD
static int timer_thread_pipe[2] = {-1, -1}; 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; static int timer_thread_pipe_owner_process;
/* only use signal-safe system calls here */ /* only use signal-safe system calls here */
@ -1190,6 +1200,12 @@ rb_thread_wakeup_timer_thread(void)
rb_thread_wakeup_timer_thread_fd(timer_thread_pipe[1]); 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 */ /* VM-dependent API is not available for this function */
static void static void
consume_communication_pipe(int fd) consume_communication_pipe(int fd)
@ -1278,6 +1294,7 @@ setup_communication_pipe(void)
return; return;
} }
setup_communication_pipe_internal(timer_thread_pipe); setup_communication_pipe_internal(timer_thread_pipe);
setup_communication_pipe_internal(timer_thread_pipe_low);
/* validate pipe on this process */ /* validate pipe on this process */
timer_thread_pipe_owner_process = getpid(); timer_thread_pipe_owner_process = getpid();
@ -1295,20 +1312,22 @@ timer_thread_sleep(rb_global_vm_lock_t* gvl)
{ {
int result; int result;
int need_polling; int need_polling;
struct pollfd pollfd; struct pollfd pollfds[2];
pollfd.fd = timer_thread_pipe[0]; pollfds[0].fd = timer_thread_pipe[0];
pollfd.events = POLLIN; pollfds[0].events = POLLIN;
pollfds[1].fd = timer_thread_pipe_low[0];
pollfds[1].events = POLLIN;
need_polling = check_signal_thread_list(); need_polling = check_signal_thread_list();
if (gvl->waiting > 0 || need_polling) { if (gvl->waiting > 0 || need_polling) {
/* polling (TIME_QUANTUM_USEC usec) */ /* polling (TIME_QUANTUM_USEC usec) */
result = poll(&pollfd, 1, TIME_QUANTUM_USEC/1000); result = poll(pollfds, 1, TIME_QUANTUM_USEC/1000);
} }
else { else {
/* wait (infinite) */ /* wait (infinite) */
result = poll(&pollfd, 1, -1); result = poll(pollfds, ARRAY_SIZE(pollfds), -1);
} }
if (result == 0) { if (result == 0) {
@ -1316,6 +1335,7 @@ timer_thread_sleep(rb_global_vm_lock_t* gvl)
} }
else if (result > 0) { else if (result > 0) {
consume_communication_pipe(timer_thread_pipe[0]); consume_communication_pipe(timer_thread_pipe[0]);
consume_communication_pipe(timer_thread_pipe_low[0]);
} }
else { /* result < 0 */ else { /* result < 0 */
switch (errno) { switch (errno) {
@ -1510,8 +1530,10 @@ int
rb_reserved_fd_p(int fd) rb_reserved_fd_p(int fd)
{ {
#if USE_SLEEPY_TIMER_THREAD #if USE_SLEEPY_TIMER_THREAD
if (fd == timer_thread_pipe[0] || if (fd == timer_thread_pipe[0] ||
fd == timer_thread_pipe[1]) { fd == timer_thread_pipe[1] ||
fd == timer_thread_pipe_low[0] ||
fd == timer_thread_pipe_low[1]) {
return 1; return 1;
} }
else { else {