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:
parent
9c021064a2
commit
bcf1293681
2 changed files with 42 additions and 9 deletions
11
ChangeLog
11
ChangeLog
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Reference in a new issue