|  | @@ -37,6 +37,7 @@
 | 
	
		
			
				|  |  |  #include <grpc/support/log.h>
 | 
	
		
			
				|  |  |  #include <grpc/support/thd.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#include "src/core/lib/debug/trace.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/iomgr/timer.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  typedef struct completed_thread {
 | 
	
	
		
			
				|  | @@ -44,6 +45,8 @@ typedef struct completed_thread {
 | 
	
		
			
				|  |  |    struct completed_thread *next;
 | 
	
		
			
				|  |  |  } completed_thread;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +extern grpc_tracer_flag grpc_timer_check_trace;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  // global mutex
 | 
	
		
			
				|  |  |  static gpr_mu g_mu;
 | 
	
		
			
				|  |  |  // are we multi-threaded
 | 
	
	
		
			
				|  | @@ -83,10 +86,13 @@ static void gc_completed_threads(void) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void start_timer_thread_and_unlock(void) {
 | 
	
		
			
				|  |  | +  GPR_ASSERT(g_threaded);
 | 
	
		
			
				|  |  |    ++g_waiter_count;
 | 
	
		
			
				|  |  |    ++g_thread_count;
 | 
	
		
			
				|  |  |    gpr_mu_unlock(&g_mu);
 | 
	
		
			
				|  |  | -  gpr_log(GPR_DEBUG, "Spawn timer thread");
 | 
	
		
			
				|  |  | +  if (GRPC_TRACER_ON(grpc_timer_check_trace)) {
 | 
	
		
			
				|  |  | +    gpr_log(GPR_DEBUG, "Spawn timer thread");
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |    gpr_thd_id thd;
 | 
	
		
			
				|  |  |    gpr_thd_options opt = gpr_thd_options_default();
 | 
	
		
			
				|  |  |    gpr_thd_options_set_joinable(&opt);
 | 
	
	
		
			
				|  | @@ -122,7 +128,9 @@ static void timer_thread(void *unused) {
 | 
	
		
			
				|  |  |          // if there's no thread waiting with a timeout, kick an existing waiter
 | 
	
		
			
				|  |  |          // so that the next deadline is not missed
 | 
	
		
			
				|  |  |          if (!g_has_timed_waiter) {
 | 
	
		
			
				|  |  | -          gpr_log(GPR_DEBUG, "kick untimed waiter");
 | 
	
		
			
				|  |  | +          if (GRPC_TRACER_ON(grpc_timer_check_trace)) {
 | 
	
		
			
				|  |  | +            gpr_log(GPR_DEBUG, "kick untimed waiter");
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  |            gpr_cv_signal(&g_cv_wait);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          gpr_mu_unlock(&g_mu);
 | 
	
	
		
			
				|  | @@ -149,15 +157,21 @@ static void timer_thread(void *unused) {
 | 
	
		
			
				|  |  |          // cancel an existing one quickly (and when it actually times out it'll
 | 
	
		
			
				|  |  |          // figure stuff out instead of incurring a wakeup)
 | 
	
		
			
				|  |  |          my_timed_waiter_generation = ++g_timed_waiter_generation;
 | 
	
		
			
				|  |  | -        gpr_log(GPR_DEBUG, "sleep for a while");
 | 
	
		
			
				|  |  | +        if (GRPC_TRACER_ON(grpc_timer_check_trace)) {
 | 
	
		
			
				|  |  | +          gpr_log(GPR_DEBUG, "sleep for a while");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |        } else {
 | 
	
		
			
				|  |  |          next = inf_future;
 | 
	
		
			
				|  |  | -        gpr_log(GPR_DEBUG, "sleep until kicked");
 | 
	
		
			
				|  |  | +        if (GRPC_TRACER_ON(grpc_timer_check_trace)) {
 | 
	
		
			
				|  |  | +          gpr_log(GPR_DEBUG, "sleep until kicked");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |        gpr_cv_wait(&g_cv_wait, &g_mu, next);
 | 
	
		
			
				|  |  | -      gpr_log(GPR_DEBUG, "wait ended: was_timed:%d kicked:%d",
 | 
	
		
			
				|  |  | -              my_timed_waiter_generation == g_timed_waiter_generation,
 | 
	
		
			
				|  |  | -              g_kicked);
 | 
	
		
			
				|  |  | +      if (GRPC_TRACER_ON(grpc_timer_check_trace)) {
 | 
	
		
			
				|  |  | +        gpr_log(GPR_DEBUG, "wait ended: was_timed:%d kicked:%d",
 | 
	
		
			
				|  |  | +                my_timed_waiter_generation == g_timed_waiter_generation,
 | 
	
		
			
				|  |  | +                g_kicked);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |        // if this was the timed waiter, then we need to check timers, and flag
 | 
	
		
			
				|  |  |        // that there's now no timed waiter... we'll look for a replacement if
 | 
	
		
			
				|  |  |        // there's work to do after checking timers (code above)
 | 
	
	
		
			
				|  | @@ -170,8 +184,8 @@ static void timer_thread(void *unused) {
 | 
	
		
			
				|  |  |          grpc_timer_consume_kick();
 | 
	
		
			
				|  |  |          g_kicked = false;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | +      gpr_mu_unlock(&g_mu);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    gpr_mu_unlock(&g_mu);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    // terminate the thread: drop the waiter count, thread count, and let whomever
 | 
	
		
			
				|  |  |    // stopped the threading stuff know that we're done
 | 
	
	
		
			
				|  | @@ -186,7 +200,9 @@ static void timer_thread(void *unused) {
 | 
	
		
			
				|  |  |    g_completed_threads = ct;
 | 
	
		
			
				|  |  |    gpr_mu_unlock(&g_mu);
 | 
	
		
			
				|  |  |    grpc_exec_ctx_finish(&exec_ctx);
 | 
	
		
			
				|  |  | -  gpr_log(GPR_DEBUG, "End timer thread");
 | 
	
		
			
				|  |  | +  if (GRPC_TRACER_ON(grpc_timer_check_trace)) {
 | 
	
		
			
				|  |  | +    gpr_log(GPR_DEBUG, "End timer thread");
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void start_threads(void) {
 | 
	
	
		
			
				|  | @@ -214,11 +230,20 @@ void grpc_timer_manager_init(void) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static void stop_threads(void) {
 | 
	
		
			
				|  |  |    gpr_mu_lock(&g_mu);
 | 
	
		
			
				|  |  | +  if (GRPC_TRACER_ON(grpc_timer_check_trace)) {
 | 
	
		
			
				|  |  | +    gpr_log(GPR_DEBUG, "stop timer threads: threaded=%d", g_threaded);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |    if (g_threaded) {
 | 
	
		
			
				|  |  |      g_threaded = false;
 | 
	
		
			
				|  |  |      gpr_cv_broadcast(&g_cv_wait);
 | 
	
		
			
				|  |  | +    if (GRPC_TRACER_ON(grpc_timer_check_trace)) {
 | 
	
		
			
				|  |  | +      gpr_log(GPR_DEBUG, "num timer threads: %d", g_thread_count);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      while (g_thread_count > 0) {
 | 
	
		
			
				|  |  |        gpr_cv_wait(&g_cv_shutdown, &g_mu, gpr_inf_future(GPR_CLOCK_REALTIME));
 | 
	
		
			
				|  |  | +      if (GRPC_TRACER_ON(grpc_timer_check_trace)) {
 | 
	
		
			
				|  |  | +        gpr_log(GPR_DEBUG, "num timer threads: %d", g_thread_count);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |        gc_completed_threads();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 |