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>
 | 
			
		||||
 | 
			
		||||
	* 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_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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue