| 
					
				 | 
			
			
				@@ -36,20 +36,22 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <stdlib.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <string.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <grpc/support/alloc.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <grpc/support/log.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <grpc/support/string_util.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <grpc/support/useful.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/channel/census_filter.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/channel/channel_args.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/channel/connected_channel.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/iomgr/iomgr.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/core/support/stack_lockfree.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/support/string.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/surface/call.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/surface/channel.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/surface/completion_queue.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/surface/init.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/transport/metadata.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <grpc/support/alloc.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <grpc/support/log.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <grpc/support/string_util.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include <grpc/support/useful.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 typedef struct listener { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   void *arg; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -72,8 +74,8 @@ typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 typedef struct requested_call { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   requested_call_type type; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  struct requested_call *next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   void *tag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_server *server; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_completion_queue *cq_bound_to_call; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_completion_queue *cq_for_notification; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_call **call; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -161,7 +163,7 @@ struct call_data { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 struct request_matcher { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   call_data *pending_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   call_data *pending_tail; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  requested_call *requests; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_stack_lockfree *requests; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 struct registered_method { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -197,8 +199,13 @@ struct grpc_server { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   registered_method *registered_methods; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   request_matcher unregistered_request_matcher; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** free list of available requested_calls indices */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_stack_lockfree *request_freelist; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** requested call backing data */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  requested_call *requested_calls; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int max_requested_calls; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_uint8 shutdown; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_atm shutdown_flag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_uint8 shutdown_published; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t num_shutdown_tags; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   shutdown_tag *shutdown_tags; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -290,8 +297,15 @@ static void channel_broadcaster_shutdown(channel_broadcaster *cb, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * request_matcher 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void request_matcher_init(request_matcher *request_matcher) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void request_matcher_init(request_matcher *request_matcher, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                 int entries) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   memset(request_matcher, 0, sizeof(*request_matcher)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  request_matcher->requests = gpr_stack_lockfree_create(entries); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void request_matcher_destroy(request_matcher *request_matcher) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(gpr_stack_lockfree_pop(request_matcher->requests) == -1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_stack_lockfree_destroy(request_matcher->requests); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void kill_zombie(void *elem, int success) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -328,6 +342,7 @@ static void server_delete(grpc_server *server) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_free(server->channel_filters); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   while ((rm = server->registered_methods) != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     server->registered_methods = rm->next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    request_matcher_destroy(&rm->request_matcher); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_free(rm->method); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_free(rm->host); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_free(rm); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -335,9 +350,12 @@ static void server_delete(grpc_server *server) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (i = 0; i < server->cq_count; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     GRPC_CQ_INTERNAL_UNREF(server->cqs[i], "server"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  request_matcher_destroy(&server->unregistered_request_matcher); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_stack_lockfree_destroy(server->request_freelist); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_free(server->cqs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_free(server->pollsets); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_free(server->shutdown_tags); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_free(server->requested_calls); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_free(server); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -377,11 +395,12 @@ static void destroy_channel(channel_data *chand) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                  request_matcher *request_matcher) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  requested_call *rc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   call_data *calld = elem->call_data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_mu_lock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  rc = request_matcher->requests; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (rc == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int request_id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  request_id = gpr_stack_lockfree_pop(request_matcher->requests); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (request_id == -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_mu_lock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_mu_lock(&calld->mu_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     calld->state = PENDING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_mu_unlock(&calld->mu_state); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -394,12 +413,10 @@ static void finish_start_new_rpc(grpc_server *server, grpc_call_element *elem, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     calld->pending_next = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_mu_unlock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    request_matcher->requests = rc->next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_mu_lock(&calld->mu_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     calld->state = ACTIVATED; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_mu_unlock(&calld->mu_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_mu_unlock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    begin_call(server, calld, rc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    begin_call(server, calld, &server->requested_calls[request_id]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -466,7 +483,7 @@ static int num_channels(grpc_server *server) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void maybe_finish_shutdown(grpc_server *server) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!server->shutdown || server->shutdown_published) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!gpr_atm_acq_load(&server->shutdown_flag) || server->shutdown_published) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -741,7 +758,17 @@ grpc_server *grpc_server_create_from_filters(grpc_channel_filter **filters, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   server->root_channel_data.next = server->root_channel_data.prev = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       &server->root_channel_data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  request_matcher_init(&server->unregistered_request_matcher); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* TODO(ctiller): expose a channel_arg for this */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  server->max_requested_calls = 32768; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  server->request_freelist = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_stack_lockfree_create(server->max_requested_calls); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i = 0; i < (size_t)server->max_requested_calls; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_stack_lockfree_push(server->request_freelist, i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  request_matcher_init(&server->unregistered_request_matcher, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                       server->max_requested_calls); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  server->requested_calls = gpr_malloc(server->max_requested_calls * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                       sizeof(*server->requested_calls)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* Server filter stack is: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -790,7 +817,7 @@ void *grpc_server_register_method(grpc_server *server, const char *method, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   m = gpr_malloc(sizeof(registered_method)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   memset(m, 0, sizeof(*m)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  request_matcher_init(&m->request_matcher); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  request_matcher_init(&m->request_matcher, server->max_requested_calls); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   m->method = gpr_strdup(method); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   m->host = gpr_strdup(host); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   m->next = server->registered_methods; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -906,13 +933,49 @@ void grpc_server_setup_transport(grpc_server *s, grpc_transport *transport, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_transport_perform_op(transport, &op); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+typedef struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  requested_call **requests; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t capacity; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} request_killer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void request_killer_init(request_killer *rk) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  memset(rk, 0, sizeof(*rk)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void request_killer_add(request_killer *rk, requested_call *rc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (rk->capacity == rk->count) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    rk->capacity = GPR_MAX(8, rk->capacity * 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    rk->requests = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        gpr_realloc(rk->requests, rk->capacity * sizeof(*rk->requests)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  rk->requests[rk->count++] = rc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void request_killer_add_request_matcher(request_killer *rk, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                               grpc_server *server, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                               request_matcher *rm) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int request_id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  while ((request_id = gpr_stack_lockfree_pop(rm->requests)) != -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    request_killer_add(rk, &server->requested_calls[request_id]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void request_killer_run(request_killer *rk, grpc_server *server) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  size_t i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i = 0; i < rk->count; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fail_call(server, rk->requests[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_free(rk->requests); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void grpc_server_shutdown_and_notify(grpc_server *server, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                      grpc_completion_queue *cq, void *tag) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   listener *l; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  requested_call *requests = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   registered_method *rm; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   shutdown_tag *sdt; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   channel_broadcaster broadcaster; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  request_killer reqkill; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* lock, and gather up some stuff to do */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_lock(&server->mu_global); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -923,7 +986,7 @@ void grpc_server_shutdown_and_notify(grpc_server *server, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   sdt = &server->shutdown_tags[server->num_shutdown_tags++]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   sdt->tag = tag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   sdt->cq = cq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (server->shutdown) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (gpr_atm_acq_load(&server->shutdown_flag)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_mu_unlock(&server->mu_global); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -931,34 +994,26 @@ void grpc_server_shutdown_and_notify(grpc_server *server, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   server->last_shutdown_message_time = gpr_now(GPR_CLOCK_REALTIME); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   channel_broadcaster_init(server, &broadcaster); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  request_killer_init(&reqkill); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* collect all unregistered then registered calls */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_lock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  requests = server->unregistered_request_matcher.requests; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  server->unregistered_request_matcher.requests = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  request_killer_add_request_matcher(&reqkill, server, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                     &server->unregistered_request_matcher); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   request_matcher_zombify_all_pending_calls( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       &server->unregistered_request_matcher); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (rm = server->registered_methods; rm; rm = rm->next) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    while (rm->request_matcher.requests != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      requested_call *c = rm->request_matcher.requests; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      rm->request_matcher.requests = c->next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      c->next = requests; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      requests = c; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    request_killer_add_request_matcher(&reqkill, server, &rm->request_matcher); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     request_matcher_zombify_all_pending_calls(&rm->request_matcher); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_unlock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  server->shutdown = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_atm_rel_store(&server->shutdown_flag, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   maybe_finish_shutdown(server); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_unlock(&server->mu_global); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* terminate all the requested calls */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  while (requests != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    requested_call *next = requests->next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    fail_call(server, requests); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    requests = next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  request_killer_run(&reqkill, server); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* Shutdown listeners */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (l = server->listeners; l; l = l->next) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -990,7 +1045,7 @@ void grpc_server_destroy(grpc_server *server) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   listener *l; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_lock(&server->mu_global); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  GPR_ASSERT(server->shutdown || !server->listeners); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(gpr_atm_acq_load(&server->shutdown_flag) || !server->listeners); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GPR_ASSERT(server->listeners_destroyed == num_listeners(server)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   while (server->listeners) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1021,9 +1076,14 @@ static grpc_call_error queue_call_request(grpc_server *server, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                           requested_call *rc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   call_data *calld = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   request_matcher *request_matcher = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_mu_lock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (server->shutdown) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_mu_unlock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int request_id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (gpr_atm_acq_load(&server->shutdown_flag)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    fail_call(server, rc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return GRPC_CALL_OK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  request_id = gpr_stack_lockfree_pop(server->request_freelist); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (request_id == -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* out of request ids: just fail this one */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     fail_call(server, rc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return GRPC_CALL_OK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1035,32 +1095,35 @@ static grpc_call_error queue_call_request(grpc_server *server, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       request_matcher = &rc->data.registered.registered_method->request_matcher; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (request_matcher->pending_head != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    calld = request_matcher->pending_head; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    request_matcher->pending_head = calld->pending_next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (calld != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_mu_unlock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_mu_lock(&calld->mu_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (calld->state == ZOMBIED) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      gpr_mu_unlock(&calld->mu_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      grpc_iomgr_closure_init( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          &calld->kill_zombie_closure, kill_zombie, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      grpc_iomgr_add_callback(&calld->kill_zombie_closure); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      return queue_call_request(server, rc); /* retry */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  server->requested_calls[request_id] = *rc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_free(rc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (gpr_stack_lockfree_push(request_matcher->requests, request_id)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* this was the first queued request: we need to lock and start 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       matching calls */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_mu_lock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while ((calld = request_matcher->pending_head) != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      request_id = gpr_stack_lockfree_pop(request_matcher->requests); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (request_id == -1) break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      request_matcher->pending_head = calld->pending_next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_mu_unlock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_mu_lock(&calld->mu_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (calld->state == ZOMBIED) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        gpr_mu_unlock(&calld->mu_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        grpc_iomgr_closure_init( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            &calld->kill_zombie_closure, kill_zombie, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        grpc_iomgr_add_callback(&calld->kill_zombie_closure); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        GPR_ASSERT(calld->state == PENDING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        calld->state = ACTIVATED; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        gpr_mu_unlock(&calld->mu_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        begin_call(server, calld, rc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_mu_lock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    GPR_ASSERT(calld->state == PENDING); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    calld->state = ACTIVATED; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_mu_unlock(&calld->mu_state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    begin_call(server, calld, rc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return GRPC_CALL_OK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    rc->next = request_matcher->requests; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    request_matcher->requests = rc; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_mu_unlock(&server->mu_call); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return GRPC_CALL_OK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return GRPC_CALL_OK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 grpc_call_error grpc_server_request_call( 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1078,6 +1141,7 @@ grpc_call_error grpc_server_request_call( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_cq_begin_op(cq_for_notification); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   rc->type = BATCH_CALL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  rc->server = server; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   rc->tag = tag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   rc->cq_bound_to_call = cq_bound_to_call; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   rc->cq_for_notification = cq_for_notification; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1100,6 +1164,7 @@ grpc_call_error grpc_server_request_registered_call( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_cq_begin_op(cq_for_notification); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   rc->type = REGISTERED_CALL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  rc->server = server; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   rc->tag = tag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   rc->cq_bound_to_call = cq_bound_to_call; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   rc->cq_for_notification = cq_for_notification; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1179,7 +1244,16 @@ static void begin_call(grpc_server *server, call_data *calld, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void done_request_event(void *req, grpc_cq_completion *c) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_free(req); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  requested_call *rc = req; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_server *server = rc->server; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (rc >= server->requested_calls && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      rc < server->requested_calls + server->max_requested_calls) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_stack_lockfree_push(server->request_freelist, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            rc - server->requested_calls); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_free(req); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void fail_call(grpc_server *server, requested_call *rc) { 
			 |