aboutsummaryrefslogtreecommitdiffstats
path: root/thread_pthread.c
diff options
context:
space:
mode:
authorkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-03-10 04:00:21 +0000
committerkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-03-10 04:00:21 +0000
commitbcf12936810465caa1e6b019652ae42bf9fc22f0 (patch)
tree0d6722fa28e338707234d6f258573e29b351280a /thread_pthread.c
parent9c021064a28639fbb9ccb6a9877fc504f377624c (diff)
downloadruby-bcf12936810465caa1e6b019652ae42bf9fc22f0.tar.gz
* 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
Diffstat (limited to 'thread_pthread.c')
-rw-r--r--thread_pthread.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/thread_pthread.c b/thread_pthread.c
index a6dba44b56..4187cf00db 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -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_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;
# 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)
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) { return 0; }
#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)
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)
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* gvl)
{
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* gvl)
}
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
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 {