|  | @@ -319,6 +319,7 @@ typedef struct {
 | 
	
		
			
				|  |  |    gpr_timespec deadline;
 | 
	
		
			
				|  |  |    grpc_cq_completion *stolen_completion;
 | 
	
		
			
				|  |  |    void *tag; /* for pluck */
 | 
	
		
			
				|  |  | +  bool first_loop;
 | 
	
		
			
				|  |  |  } cq_is_finished_arg;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static bool cq_is_next_finished(grpc_exec_ctx *exec_ctx, void *arg) {
 | 
	
	
		
			
				|  | @@ -342,7 +343,8 @@ static bool cq_is_next_finished(grpc_exec_ctx *exec_ctx, void *arg) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      gpr_mu_unlock(cq->mu);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  return gpr_time_cmp(a->deadline, gpr_now(a->deadline.clock_type)) < 0;
 | 
	
		
			
				|  |  | +  return !a->first_loop &&
 | 
	
		
			
				|  |  | +         gpr_time_cmp(a->deadline, gpr_now(a->deadline.clock_type)) < 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #ifndef NDEBUG
 | 
	
	
		
			
				|  | @@ -370,7 +372,6 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
 | 
	
		
			
				|  |  |                                        gpr_timespec deadline, void *reserved) {
 | 
	
		
			
				|  |  |    grpc_event ret;
 | 
	
		
			
				|  |  |    grpc_pollset_worker *worker = NULL;
 | 
	
		
			
				|  |  | -  int first_loop = 1;
 | 
	
		
			
				|  |  |    gpr_timespec now;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    GPR_TIMER_BEGIN("grpc_completion_queue_next", 0);
 | 
	
	
		
			
				|  | @@ -392,8 +393,13 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
 | 
	
		
			
				|  |  |    GRPC_CQ_INTERNAL_REF(cc, "next");
 | 
	
		
			
				|  |  |    gpr_mu_lock(cc->mu);
 | 
	
		
			
				|  |  |    cq_is_finished_arg is_finished_arg = {
 | 
	
		
			
				|  |  | -      gpr_atm_no_barrier_load(&cc->things_queued_ever), cc, deadline, NULL,
 | 
	
		
			
				|  |  | -      NULL};
 | 
	
		
			
				|  |  | +      .last_seen_things_queued_ever =
 | 
	
		
			
				|  |  | +          gpr_atm_no_barrier_load(&cc->things_queued_ever),
 | 
	
		
			
				|  |  | +      .cq = cc,
 | 
	
		
			
				|  |  | +      .deadline = deadline,
 | 
	
		
			
				|  |  | +      .stolen_completion = NULL,
 | 
	
		
			
				|  |  | +      .tag = NULL,
 | 
	
		
			
				|  |  | +      .first_loop = true};
 | 
	
		
			
				|  |  |    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(
 | 
	
		
			
				|  |  |        cq_is_next_finished, &is_finished_arg);
 | 
	
		
			
				|  |  |    for (;;) {
 | 
	
	
		
			
				|  | @@ -427,14 +433,13 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      now = gpr_now(GPR_CLOCK_MONOTONIC);
 | 
	
		
			
				|  |  | -    if (!first_loop && gpr_time_cmp(now, deadline) >= 0) {
 | 
	
		
			
				|  |  | +    if (!is_finished_arg.first_loop && gpr_time_cmp(now, deadline) >= 0) {
 | 
	
		
			
				|  |  |        gpr_mu_unlock(cc->mu);
 | 
	
		
			
				|  |  |        memset(&ret, 0, sizeof(ret));
 | 
	
		
			
				|  |  |        ret.type = GRPC_QUEUE_TIMEOUT;
 | 
	
		
			
				|  |  |        dump_pending_tags(cc);
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    first_loop = 0;
 | 
	
		
			
				|  |  |      /* Check alarms - these are a global resource so we just ping
 | 
	
		
			
				|  |  |         each time through on every pollset.
 | 
	
		
			
				|  |  |         May update deadline to ensure timely wakeups.
 | 
	
	
		
			
				|  | @@ -461,6 +466,7 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc,
 | 
	
		
			
				|  |  |          break;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    is_finished_arg.first_loop = false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret);
 | 
	
		
			
				|  |  |    GRPC_CQ_INTERNAL_UNREF(cc, "next");
 | 
	
	
		
			
				|  | @@ -523,7 +529,8 @@ static bool cq_is_pluck_finished(grpc_exec_ctx *exec_ctx, void *arg) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      gpr_mu_unlock(cq->mu);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  return gpr_time_cmp(a->deadline, gpr_now(a->deadline.clock_type)) < 0;
 | 
	
		
			
				|  |  | +  return !a->first_loop &&
 | 
	
		
			
				|  |  | +         gpr_time_cmp(a->deadline, gpr_now(a->deadline.clock_type)) < 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
 | 
	
	
		
			
				|  | @@ -533,7 +540,6 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
 | 
	
		
			
				|  |  |    grpc_cq_completion *prev;
 | 
	
		
			
				|  |  |    grpc_pollset_worker *worker = NULL;
 | 
	
		
			
				|  |  |    gpr_timespec now;
 | 
	
		
			
				|  |  | -  int first_loop = 1;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    GPR_TIMER_BEGIN("grpc_completion_queue_pluck", 0);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -556,8 +562,13 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
 | 
	
		
			
				|  |  |    GRPC_CQ_INTERNAL_REF(cc, "pluck");
 | 
	
		
			
				|  |  |    gpr_mu_lock(cc->mu);
 | 
	
		
			
				|  |  |    cq_is_finished_arg is_finished_arg = {
 | 
	
		
			
				|  |  | -      gpr_atm_no_barrier_load(&cc->things_queued_ever), cc, deadline, NULL,
 | 
	
		
			
				|  |  | -      tag};
 | 
	
		
			
				|  |  | +      .last_seen_things_queued_ever =
 | 
	
		
			
				|  |  | +          gpr_atm_no_barrier_load(&cc->things_queued_ever),
 | 
	
		
			
				|  |  | +      .cq = cc,
 | 
	
		
			
				|  |  | +      .deadline = deadline,
 | 
	
		
			
				|  |  | +      .stolen_completion = NULL,
 | 
	
		
			
				|  |  | +      .tag = tag,
 | 
	
		
			
				|  |  | +      .first_loop = true};
 | 
	
		
			
				|  |  |    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK(
 | 
	
		
			
				|  |  |        cq_is_pluck_finished, &is_finished_arg);
 | 
	
		
			
				|  |  |    for (;;) {
 | 
	
	
		
			
				|  | @@ -607,7 +618,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      now = gpr_now(GPR_CLOCK_MONOTONIC);
 | 
	
		
			
				|  |  | -    if (!first_loop && gpr_time_cmp(now, deadline) >= 0) {
 | 
	
		
			
				|  |  | +    if (!is_finished_arg.first_loop && gpr_time_cmp(now, deadline) >= 0) {
 | 
	
		
			
				|  |  |        del_plucker(cc, tag, &worker);
 | 
	
		
			
				|  |  |        gpr_mu_unlock(cc->mu);
 | 
	
		
			
				|  |  |        memset(&ret, 0, sizeof(ret));
 | 
	
	
		
			
				|  | @@ -615,7 +626,6 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
 | 
	
		
			
				|  |  |        dump_pending_tags(cc);
 | 
	
		
			
				|  |  |        break;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    first_loop = 0;
 | 
	
		
			
				|  |  |      /* Check alarms - these are a global resource so we just ping
 | 
	
		
			
				|  |  |         each time through on every pollset.
 | 
	
		
			
				|  |  |         May update deadline to ensure timely wakeups.
 | 
	
	
		
			
				|  | @@ -642,6 +652,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag,
 | 
	
		
			
				|  |  |          break;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    is_finished_arg.first_loop = false;
 | 
	
		
			
				|  |  |      del_plucker(cc, tag, &worker);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  done:
 |