| 
					
				 | 
			
			
				@@ -71,6 +71,9 @@ struct grpc_completion_queue { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_refcount pending_events; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /** Once owning_refs drops to zero, we will destroy the cq */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_refcount owning_refs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** counter of how many things have ever been queued on this completion queue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      useful for avoiding locks to check the queue */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_atm things_queued_ever; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /** 0 initially, 1 once we've begun shutting down */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int shutdown; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int shutdown_called; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -125,15 +128,6 @@ void grpc_cq_global_shutdown(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-struct grpc_cq_alarm { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_timer alarm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_cq_completion completion; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /** completion queue where events about this alarm will be posted */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_completion_queue *cq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /** user supplied tag */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void *tag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 grpc_completion_queue *grpc_completion_queue_create(void *reserved) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_completion_queue *cc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GPR_ASSERT(!reserved); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -170,6 +164,7 @@ grpc_completion_queue *grpc_completion_queue_create(void *reserved) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   cc->is_server_cq = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   cc->is_non_listening_server_cq = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   cc->num_pluckers = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_atm_no_barrier_store(&cc->things_queued_ever, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #ifndef NDEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   cc->outstanding_tag_count = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -280,6 +275,7 @@ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GPR_ASSERT(found); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   shutdown = gpr_unref(&cc->pending_events); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_atm_no_barrier_fetch_add(&cc->things_queued_ever, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (!shutdown) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cc->completed_tail->next = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         ((uintptr_t)storage) | (1u & (uintptr_t)cc->completed_tail->next); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -318,6 +314,7 @@ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 typedef struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_atm last_seen_things_queued_ever; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_completion_queue *cq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_timespec deadline; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_cq_completion *stolen_completion; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -328,17 +325,23 @@ static bool cq_is_next_finished(grpc_exec_ctx *exec_ctx, void *arg) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   cq_is_finished_arg *a = arg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_completion_queue *cq = a->cq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GPR_ASSERT(a->stolen_completion == NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_mu_lock(cq->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (cq->completed_tail != &cq->completed_head) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    a->stolen_completion = (grpc_cq_completion *)cq->completed_head.next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    cq->completed_head.next = a->stolen_completion->next & ~(uintptr_t)1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (a->stolen_completion == cq->completed_tail) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      cq->completed_tail = &cq->completed_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_atm current_last_seen_things_queued_ever = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_atm_no_barrier_load(&cq->things_queued_ever); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (current_last_seen_things_queued_ever != a->last_seen_things_queued_ever) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_mu_lock(cq->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    a->last_seen_things_queued_ever = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        gpr_atm_no_barrier_load(&cq->things_queued_ever); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (cq->completed_tail != &cq->completed_head) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      a->stolen_completion = (grpc_cq_completion *)cq->completed_head.next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      cq->completed_head.next = a->stolen_completion->next & ~(uintptr_t)1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (a->stolen_completion == cq->completed_tail) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cq->completed_tail = &cq->completed_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_mu_unlock(cq->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_mu_unlock(cq->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_mu_unlock(cq->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return gpr_time_cmp(a->deadline, gpr_now(a->deadline.clock_type)) < 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -386,12 +389,13 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  cq_is_finished_arg is_finished_arg = {cc, deadline, NULL, NULL}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      cq_is_next_finished, &is_finished_arg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   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}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      cq_is_next_finished, &is_finished_arg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (;;) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (is_finished_arg.stolen_completion != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       gpr_mu_unlock(cc->mu); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -496,23 +500,29 @@ static bool cq_is_pluck_finished(grpc_exec_ctx *exec_ctx, void *arg) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   cq_is_finished_arg *a = arg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_completion_queue *cq = a->cq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GPR_ASSERT(a->stolen_completion == NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_mu_lock(cq->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_cq_completion *c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_cq_completion *prev = &cq->completed_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  while ((c = (grpc_cq_completion *)(prev->next & ~(uintptr_t)1)) != 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         &cq->completed_head) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (c->tag == a->tag) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      prev->next = (prev->next & (uintptr_t)1) | (c->next & ~(uintptr_t)1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (c == cq->completed_tail) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        cq->completed_tail = prev; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_atm current_last_seen_things_queued_ever = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_atm_no_barrier_load(&cq->things_queued_ever); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (current_last_seen_things_queued_ever != a->last_seen_things_queued_ever) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_mu_lock(cq->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    a->last_seen_things_queued_ever = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        gpr_atm_no_barrier_load(&cq->things_queued_ever); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_cq_completion *c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_cq_completion *prev = &cq->completed_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while ((c = (grpc_cq_completion *)(prev->next & ~(uintptr_t)1)) != 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+           &cq->completed_head) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (c->tag == a->tag) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        prev->next = (prev->next & (uintptr_t)1) | (c->next & ~(uintptr_t)1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (c == cq->completed_tail) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          cq->completed_tail = prev; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        gpr_mu_unlock(cq->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        a->stolen_completion = c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      gpr_mu_unlock(cq->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      a->stolen_completion = c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      prev = c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    prev = c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_mu_unlock(cq->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_mu_unlock(cq->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return gpr_time_cmp(a->deadline, gpr_now(a->deadline.clock_type)) < 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -543,12 +553,13 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  cq_is_finished_arg is_finished_arg = {cc, deadline, NULL, tag}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      cq_is_pluck_finished, &is_finished_arg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   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}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT_WITH_FINISH_CHECK( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      cq_is_pluck_finished, &is_finished_arg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (;;) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (is_finished_arg.stolen_completion != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       gpr_mu_unlock(cc->mu); 
			 |